码迷,mamicode.com
首页 > 其他好文 > 详细

Treap树

时间:2015-04-14 00:13:54      阅读:146      评论:0      收藏:0      [点我收藏+]

标签:

随机构造的二叉搜索树是趋向于平衡的.因此,一般来说,要为一组固定的元素建立平衡二叉树,可以先随机排列这些元素,然后按照排列的顺序将它们插入倒树中.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.函数操作指针本身//函数调用结束后函数对指针的操作无效
技术分享
#include<iostream>
using namespace std;
//情况1
void swap(int *vp1, int *vp2) {
    int a = *vp1;
    *vp1 = *vp2;
    *vp2 = a;
}
//情况2
void swap2(int *vp1, int *vp2) {
    int* a = vp1;
    vp1 = vp2;
    vp2 = a;
}
int main(){
    int a=1,b=2;
    swap2(&a,&b);
    cout<<"swap2:"<<a<<","<<b<<endl;
    swap(&a,&b);
    cout<<"swap :"<<a<<","<<b<<endl;
    return 0;
}
View Code

运行结果:

技术分享

 

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

Treap树

标签:

原文地址:http://www.cnblogs.com/bukekangli/p/4423482.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!