• 二叉搜索树(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;
    
    }
  • 相关阅读:
    EF CodeFirst下,当实体结构发生修改怎么更新数据库结构 【常用总结】
    基于 ASP.NET Core 的 EF Core 入门
    autofac 一个接口多个实现的情况
    C#中使用HttpClient来Post数据的内容HttpContent的各种格式
    # 使用HttpClient的post,get 封装
    C# 模拟提交带附件(input type=file)的表单
    C#使用HttpClient上传文件并附带其他参数
    2021年总结一下
    PhpStorm+Xdebug断点调试
    PHP数组排序
  • 原文地址:https://www.cnblogs.com/narjaja/p/8405972.html
Copyright © 2020-2023  润新知