• Treap树


    随机构造的二叉搜索树是趋向于平衡的.因此,一般来说,要为一组固定的元素建立平衡二叉树,可以先随机排列这些元素,然后按照排列的顺序将它们插入倒树中.Treap树先按照结点的优先级将结点排序,然后再逐一插入二叉树中.Treap树中结点的关键字遵循二叉搜索树的性质,且优先级遵循最小堆的性质.

    编程实现:

    #include<iostream>
    using namespace std;
    class Node{
    public:
        char key;
        int priority;
        Node* p = nullptr;
        Node* left = nullptr;
        Node* right = nullptr;
        Node() = default;
        Node(char k, int w):key(k),priority(w){}
    };
    void left_rotate(Node* &x){//结点指针要传递引用
        Node* y =x->right;
        x->right = y->left;
        y->left = x;
        x = y;
    }
    void right_rotate(Node* &x){//结点指针要传递引用
        Node* y =x->left;
        x->left = y->right;
        y->right = x;
        x = y;
    }
    void insert(char key,int priority, Node* &tree){//结点指针要传递引用
        if(tree == nullptr){//找到位置,建立结点
            tree = new Node(key, priority);
        }
        else if(key < tree->key){
            insert(key, priority, tree->left);
            if(tree->left->priority < tree->priority){//左子结点优先级小于当前结点优先级,右旋当前结点
                right_rotate(tree);
            }
        }
        else if(key > tree->key){
            insert(key, priority, tree->right);
            if(tree->right->priority < tree->priority){//右子结点优先级小于当前结点优先级,左旋当前结点
                left_rotate(tree);
            }
        }
    }
    void remove(char key, Node* &tree){//结点指针要传递引用
        if(tree != nullptr){
            if(key < tree->key){
                remove(key, tree->left);
            }
            else if(key > tree->key){
                remove(key, tree->right);
            }
            else{
                if(tree->left != nullptr && tree->right != nullptr){
                    if(tree->left->priority < tree->right->priority){ //左子结点优先级较小,右旋
                        right_rotate(tree);
                        remove(key,tree->right);//1
                    }
                    else{//右子结点优先级较小,左旋
                        left_rotate(tree);
                        remove(key,tree->left);//2
                    }
                    //remove(key,tree);1和2可以由这句代替
                }
                else{
                    Node* t = tree;
                                    tree = (tree->left == nullptr) ? tree->right : tree->left;
                    delete t;
                }
            }
        }
    }
    void inorder_traverse(Node* tree){
        if(tree != nullptr){
            inorder_traverse(tree->left);
            cout<<tree->key<<" , ";
            inorder_traverse(tree->right);
        }
    }
    int main(){
        Node* tree = nullptr;
        insert('G',4, tree);
        insert('B',7, tree);
        insert('H',5, tree);
        insert('K',65, tree);
        insert('A',10, tree);
        insert('E',23, tree);
        inorder_traverse(tree);
        cout<<endl;
        remove('B', tree);
        inorder_traverse(tree);
        cout<<endl;
        return 0;
    }
    View Code

    运行结果:

    思考:为什么结点指针要传递引用?

    因为这里改变的是结点指针变量本身而不是结点指针指向的对象.

    受交换两个变量的值的影响,我一直以为只要指针作为参数时传递的是地址,函数对指针的操作在函数调用结束后仍然有效.其实不然,这里要分三种情况:

    1.函数操作对象本身//函数调用结束后函数对对象的操作无效
    2.函数操作指针指向的对象//函数调用结束后函数对指针指向的对象的操作仍然有效,和操作引用是同样的效果
    3.函数操作指针本身//函数调用结束后函数对指针指向的对象的操作无效,对指针的操作也无效,回到1了,指针在这里就是一个普通变量
    4.函数操作指针的引用//函数调用结束后函数对指针指向的对象的操作无效,对指针的操作有效,和操作指针的指针是同样的效果
    #include<iostream>
    using namespace std;
    
    void swap(int *vp1, int *vp2) {
        int a = *vp1;
        *vp1 = *vp2;
        *vp2 = a;
    }
    
    void swap2(int *vp1, int *vp2) {
        int* a = vp1;
        vp1 = vp2;
        vp2 = a;
    }
    
    void swap3(int* &vp1, int* &vp2){
        int* a = vp1;
        vp1 = vp2;
        vp2 = a;
    }
    
    int main(){
        int a=1,b=2;
        swap(&a,&b);
        cout<<"swap :"<<a<<","<<b<<endl;
        swap2(&a,&b);
        cout<<"swap2:"<<a<<","<<b<<endl;
        int* p1 = &a;
        int* p2 = &b;
        //swap3(&a,&b);invalid initialization of non-const reference of type ‘int*&’ from an rvalue of type ‘int*’
        swap3(p1,p2);
        cout<<"swap3:"<<*p1<<","<<*p2<<endl;
        return 0;
    }
    View Code

    运行结果:

     

    参考:https://www.byvoid.com/upload/wp/2010/12/treap-analysis-and-application.pdf

  • 相关阅读:
    一个你爱,一个爱你,你选择哪一个
    Flask 中的 SQLAlchemy 使用教程
    Flas-SQLAchemy数据库操作使用学习笔记
    Flask-SQLAlchemy获取一个字段里去掉重复的数据
    Python 列表(list)、字典(dict)、字符串(string)常用基本操作小结
    pycharm快捷键、常用设置、包管理
    [原创]python MySQLdb在windows环境下的安装、出错问题以及解决办法
    Highcharts下载与使用_数据报表图
    Markdown入门指南-指间阁
    Sublime Text3 配置markdown插件
  • 原文地址:https://www.cnblogs.com/bukekangli/p/4423482.html
Copyright © 2020-2023  润新知