#include<cstdio> struct node{ int value; node *left,*right; }; void insert(node *&root,int value){ if(root==NULL){ root=new node; root->value=value; root->left=root->right=NULL; } else { if(root->value>value) insert(root->left,value); else insert(root->right,value); } } void del(){ } void dfs(node *root){ if(root==NULL){ return ; } else { dfs(root->left); printf("%d\n",root->value); dfs(root->right); } } int main(){ node * root=NULL; insert(root,5); insert(root,4); insert(root,7); insert(root,6); insert(root,2); insert(root,3); insert(root,2); dfs(root); return 0; }
输出结果 2 2 3 4 5 6 7
Treap同时满足BST性质和最小堆性质,不可避免地要对结构进行调整,
调整方式称为旋转。
treap节点结构
struct Treap_node{ int value; int fix;//节点的值和优先值 Treap_node *left,*right;//节点左右子树的指针 };
右旋:
左旋:
右旋:
void right_rotate(Treap_node *&root){//指针的引用 Treap_node *R=root->left; root->left=R->right;//将原根的左节点接上原左节点的右节点 R->right=root;//右节点 root=R;//修改当前根为原根的左节点 }
左旋:
void left_rotate(Treap_node *&root){//指针的引用 Treap_node *R=root->right; root->right=R->left; R->left=root; root=R; }
一、 插入:
- 从根节点开始插入:
- 如果要插入的值 ≤当前节点的值,在当前节点的左子树插入
插入后如果左子树的优先级<当前节点,右旋 调整。
- 如果要插入的值 ≥当前节点的值,在当前节点的右子树插入
插入后如果右子树的优先级<当前节点,左旋 调整。
void Treap_insert(Treap_node *&p,int value){ if(!p){ p=new Treap_node; p->value=value; p->fix=rand(); p->left=p->right=NULL; } else if(value<=p->value){ Treap_insert(p->left,value); if(p->left->fix<p->fix) right_rotate(p); } else { Treap_insert(p->right,value); if(p->right->fix<p->fix) left_rotate(p); } }
二、 删除
- 首先找到这个节点
- 如果该节点为 叶结点或者链节点 可以直接删除。
左节点为空,让右节点代替该节点。反之左节点代替。
- 如果节点有两个非空子节点。我们的策略是通过旋转,使得节点变成第二种情况。
如果左节点的优先级<右节点,右旋,访问右节点。
如果左节点的优先级>右节点,左旋,访问左节点。
void Treap_delete(Treap_node *&p,int value){ if(p->value==value){ if(!p->left||!p->right){ Treap_node *t=p; if(!p->right) p=p->left; else p=p->right; delete t; } else { if(p->left->fix<p->right->fix){ right_rotate(p); Treap_delete(p->right,value); } else { left_rotate(p); Treap_delete(p->left,value); } } } else if(p->value<value){ Treap_delete(p->right,value); } else Treap_delete(p->left,value); }
完整代码:
#include<cstdio> #include<stdlib.h> struct Treap_node{ int value; int fix;//节点的值和优先值 Treap_node *left,*right;//节点左右子树的指针 }; void left_rotate(Treap_node *&root){//指针的引用 Treap_node *R=root->right; root->right=R->left; R->left=root; root=R; } void right_rotate(Treap_node *&root){//指针的引用 Treap_node *R=root->left; root->left=R->right;//将原根的左节点接上原左节点的右节点 R->right=root;//右节点 root=R;//修改当前根为原根的左节点 } void Treap_insert(Treap_node *&p,int value){ if(!p){ p=new Treap_node; p->value=value; p->fix=rand(); p->left=p->right=NULL; } else if(value<=p->value){ Treap_insert(p->left,value); if(p->left->fix<p->fix) right_rotate(p); } else { Treap_insert(p->right,value); if(p->right->fix<p->fix) left_rotate(p); } } void Treap_delete(Treap_node *&p,int value){ if(p->value==value){ if(!p->left||!p->right){ Treap_node *t=p; if(!p->right) p=p->left; else p=p->right; delete t; } else { if(p->left->fix<p->right->fix){ right_rotate(p); Treap_delete(p->right,value); } else { left_rotate(p); Treap_delete(p->left,value); } } } else if(p->value<value){ Treap_delete(p->right,value); } else Treap_delete(p->left,value); } void dfs(Treap_node *p){ if(!p){ return ; } else { printf("%d\n",p->value); dfs(p->left); dfs(p->right); } } int main(){ Treap_node *p=NULL; Treap_insert(p,5); Treap_insert(p,6); Treap_insert(p,4); Treap_insert(p,8); Treap_insert(p,7); //dfs(p); Treap_delete(p,5); dfs(p); return 0; }
还需要整理相关复杂度的知识。