zoukankan      html  css  js  c++  java
  • 二叉搜索树(BST)

    (第一段日常扯蛋,大家不要看)这几天就要回家了,osgearth暂时也不想弄了,毕竟不是几天就能弄出来的,所以打算过完年回来再弄。这几天闲着也是闲着,就掏出了之前买的算法导论看了看,把二叉搜索树实现了下。

    一、算法导论中讲解

    1、二叉搜索树

    节点

    每个节点包含key(关键字)、left(指向左孩子)、right(指向右孩子)、parent(指向父节点)。

    额外可有可无num(相同关键字的节点个数)。

    规则

    整个二叉树的根节点的parent指向NULL,且唯一。

    左子树上所有节点的key均小于其根节点的key。

    右子树上所有节点的key均大于其根节点的key。

    最低层的节点的left与right指向NULL。

    2、二叉搜索树的遍历

    二叉搜索树的遍历分为先序遍历,中序遍历,后序遍历(由x.key的输出位置决定)。

    中序遍历即为按照key从大到小输出。

    3、查询二叉树

    循环查找

    迭代查找

    4、最大关键字元素和最小关键字元素

    5、后继和前驱

    6、插入

    对于BST插入只能插入到最下层,例如插入13。

    伪代码:

    7、删除

    删除分为三种情况

      1.删除节点的left(或者right)指向NULL,直接把right(或者left)提升到该节点处。

                          

      2.删除节点的right和left不为NULL,且其right的left为NULL,直接把right提升到该节点处。

      3.删除节点的right和left不为NULL,且其right的left不为NULL,找到删除节点的后继(即大于删除节点key的最小key所在节点y),把后继y的right提到后继y的位置(即让后继y的parent的left指向后继y的right),再用删除节点的right和left分别代替后继y的right和left,最后再用后继y把删除节点替换掉。

    伪代码:

    节点替换

    删除

    三、c++代码

    #include <iostream>
    #include <memory>
    #include <vector>
    
    using namespace std;
    
    //节点结构
    struct Node {
        int key;
        int num;
        shared_ptr<Node> parent;
        shared_ptr<Node> left;
        shared_ptr<Node> right;
        Node(int _key) : key(_key), num(1),parent(NULL), left(NULL), right(NULL) {}
    };
    
    //循环插入
    bool Insert(shared_ptr<Node>& root, int _key) {
        shared_ptr<Node> node(new Node(_key));
        if (root == NULL) {
            root = node;
            return true;
        }
        shared_ptr<Node> x = root;
        shared_ptr<Node> y;
        while(x != NULL) {
            y = x;
            if (node->key == x->key) {
                x->num++;
                return true;
            }
            if (node->key < x->key) x = x->left;
            else x = x->right;
        }
        if (node->key < y->key) {
            y->left = node;
            node->parent = y;
        }
        else {
            y->right = node;
            node->parent = y;
        }
        return true;
    }
    
    //迭代插入
    bool reInsert(shared_ptr<Node>& root, shared_ptr<Node> node) {
        if (root == NULL) {
            root = node;
            return true;
        }
        if (node->key == root->key) {
            root->num++;
            return true;
        }
        if (node->key < root->key) return reInsert(root->left, node);
        else return reInsert(root->right, node);
    }
    
    //创建二叉树
    void BSTCreat(shared_ptr<Node>& root, vector<int> keys) {
        for (int key : keys) {
            Insert(root, key);
        }
    }
    
    //遍历
    void showBST(shared_ptr<Node>& root) {
        if (root != NULL) {
    //     //cout << root->key << " ";//先序遍历
    //        showBST(root->left);
    //        cout << root->key << " "; //中序遍历
    //        showBST(root->right);
    //     //cout << root->key << " ";//后序遍历
            //cout << root->key << " "; //first
            showBST(root->left);
            cout << root->key << " "; //mid
            showBST(root->right);
            //cout << root->key << " "; //end
        }
    }
    
    //删除节点
    bool Delete(shared_ptr<Node>& root, int _key) {
        if(root == NULL) return false;
        if(root->key < _key) return Delete(root->right, _key);
        else if(root->key > _key)return Delete(root->left, _key);
        else {
            if (root->right==NULL) {
                root = root->left;
                return true;
            }
            if (root->left==NULL) {
                root = root->right;
                return true;
            }
            if (root->right->left==NULL) {
                root->right->left = root->left;
                root = root->right;
                return true;
            }
            shared_ptr<Node> y = root->right;
            while(y->left!=NULL) {
                y = y->left;
            }
            y->parent->left = y->right;
            y->right = root->right;
            y->left = root->left;
            root = y;
            return true;
        }
    }
    
    bool isSubtree(shared_ptr<Node> pRootA, shared_ptr<Node> pRootB) {
        if (pRootB == NULL) return true;
        if (pRootA == NULL) return false;
        if (pRootB->key == pRootA->key) {
            return isSubtree(pRootA->left, pRootB->left)
                    && isSubtree(pRootA->right, pRootB->right);
        } else return false;
    }
    
    bool HasSubtree(shared_ptr<Node> pRootA, shared_ptr<Node> pRootB)
    {
        if (pRootA == NULL || pRootB == NULL) return false;
        return isSubtree(pRootA, pRootB) ||
                HasSubtree(pRootA->left, pRootB) ||
                HasSubtree(pRootA->right, pRootB);
    }
    
    int main() {
        vector<int> keys1{1,2,3,4,5,6,7};
        vector<int> keys2{3,4,5};
    
        shared_ptr<Node> root1;
        shared_ptr<Node> root2;
        BSTCreat(root1, keys1);
        BSTCreat(root2, keys2);
    
        cerr << HasSubtree(root1, root2) << endl;
    
        return 0;
    
    }
  • 相关阅读:
    how to uninstall devkit
    asp.net中bin目录下的 dll.refresh文件
    查找2个分支的共同父节点
    Three ways to do WCF instance management
    WCF Concurrency (Single, Multiple, and Reentrant) and Throttling
    检查string是否为double
    How to hide TabPage from TabControl
    获取当前系统中的时区
    git svn cygwin_exception
    lodoop打印控制具体解释
  • 原文地址:https://www.cnblogs.com/narjaja/p/8405972.html
Copyright © 2011-2022 走看看