概念:
区别于二叉搜索树BST和平衡二叉树AVL,伸展树本质在BST基础上还规定类每次访问之后将访问的节点变成根节点,这样使得被访问过的节点尽可能靠近根节点,这样下次再次访问时更快定位。因此不像AVL那样需要保存高度信息节省了存储空间。具有二叉查找树的所有性质。在性能上又比普通的二叉查找树有所改进:普通的二叉查找树在最坏情况下的查找操作的时间复杂度为O(n)(当二叉树退化成一条链的时候),而伸展树在任何情况下的平摊时间复杂度均为 O(log2n).
原理:
伸展树实现O(log2n)量级的平摊复杂度依靠每次对伸展树进行查询、修改、删除操作之后,都进行旋转操作 Splay(x, root),该操作将节点x旋转到树的根部。 伸展树的旋转有六种类型,如果去掉镜像的重复,则为三种:/:zig(\:zag)、zig-zig(zag-zag)、zig-zag(zag-zig)。
设计方法:
基于旋找展开原理可存在自低向上和自顶向下两种设计方法
x是我们查找路径上需要旋找的一根非根节点,当x的父节点y是根节点下的情况:
y->lson==x--------zig
y->rson==x-------zag
对于这种情况直接参看AVL树里的单左旋(zag旋转)和单右旋(zig旋转)即可
zig-zig or zag-zag旋转:
x是我们查找路径上需要旋找的一根非根节点,当x的父节点是y,y的父节点是z的情况:
z->lson==y;y->lson==x--------zig-zig->先对y,z进行zig旋找再对x和y节点进行zig旋转
z->rson==y;y->rson==x--------zag-zag->先对y,z进行zag旋找再对x和y节点进行zag旋转
zig-zag or zag-zig旋转:
x是我们查找路径上需要旋找的一根非根节点,当x的父节点是y,y的父节点是z的情况:
z->lson==y;y->rson==x--------zig-zag->先对x,y进行zag旋找再对z和y节点进行zig旋转
z->rson==y;y->lson==x--------zag-zig->先对y,x进行zig旋找再对x和y节点进行zag旋转
C++类实现:
tree.h
#ifndef SPtree #define SPtree /********************Splay tree**********************/ class node{ public: eletype val; node *lson; node *rson; node *parent;//自低需要父节点 node():val(0),lson(NULL),rson(NULL),parent(NULL){} node(eletype k,node*l,node*r,node *p):val(k),lson(l),rson(r),parent(p){} }; typedef node *node_; class SPTree{ public: node*root; public: SPTree(); ~SPTree(); void postorder(); void inorder(); node*Find(eletype x); node* Find1(node *root1,eletype x); node *Findmax(); void splay_frombottom(eletype x); void Insert(eletype x); void Remove(eletype x); void Destroy(); private: void postorder(node_ root1)const; void inorder(node_ root1)const; node* Find(node *root1,eletype x); node *Findmax(node *root1); node* Splayfrombottom(node *y,node*&x); void singleRotaLeft(node*&k2); void singleRotaRight(node*&k2); void DoubleRotaLeft(node *&k2); void DoubleRotaRight(node *&k2); node*Insert(node*&root1,eletype x); node*Remove(node*&root1,eletype x); void Destroy(node*&root1); }; #endiftree.cpp /*************Splay**********************/ //自低向上的设计 SPTree::SPTree():root(NULL){} SPTree::~SPTree(){ Destroy(root); } void SPTree::singleRotaRight(node*&y){ if(y==NULL)return ; //y节点,y节点父节点,y节点子节点x及x子节点 node *z=y->parent; node *x=y->lson; x->parent=z; if(x->rson)x->rson->parent=y; y->parent=x; y->lson=x->rson; x->rson=y; if(z){if(z->lson==y)z->lson=x;else z->rson=x;} y= x; } void SPTree::singleRotaLeft(node*&y){ if(y==NULL)return ; node *z=y->parent; node *x=y->rson; x->parent=z; if(x->lson)x->lson->parent=y; y->parent=x; y->rson=x->lson; x->lson=y; if(z){if(z->lson==y)z->lson=x;else z->rson=x;} y=x; } void SPTree::DoubleRotaLeft(node *&y){ singleRotaRight(y->rson); singleRotaLeft(y); } void SPTree::DoubleRotaRight(node *&y){ singleRotaLeft(y->lson); singleRotaRight(y); } node* SPTree::Splayfrombottom(node *y,node*&x)//待变成根节点的指针x和当前y {node *p=x->parent; node *g; while(p){ g=p->parent; if(p->lson==x)//x is left {if(g==NULL)singleRotaRight(p);//zig else if(g->lson==p) {singleRotaRight(g);singleRotaRight(p);}//zig-zig else {DoubleRotaLeft(g);}//zag-zig\/ } else if(p->rson==x)// x is right {if(g==NULL)singleRotaLeft(p);//zag else if(g->rson==p){singleRotaLeft(g);singleRotaLeft(p);}//zag-zag else DoubleRotaRight(g);//zag-zig } else ;// x is root p=x->parent; } return x; } void SPTree::splay_frombottom(eletype key){ node *X=Find(root,key); root=Splayfrombottom(root,X); } node*SPTree::Find(node *x,eletype key){ if(x==NULL)return x; else{ if(key<x->val) return Find(x->lson,key); else if(key>x->val)return Find(x->rson,key); else return x; } } node *SPTree::Find(eletype k){ node*p=Find(root,k); if(p==NULL){cout<<"empty tree!"<<endl;return p;} if(p!=root) {root=Splayfrombottom(root,p);return root;} else return p; } node *SPTree::Find1(node *root1,eletype x){ if(root1==NULL){return root1;} node *p=Find(root1,x); if(p==NULL){cout<<"empty tree!"<<endl;return p;} if(p!=root) {root=Splayfrombottom(root,p);return root;} else return p; } node *SPTree::Findmax(node *x){ if(x==NULL){cout<<"empty tree!"<<endl;return x;} node *p=x; while(p->rson)p=p->rson; return Splayfrombottom(x,p); } node *SPTree::Insert(node *&root1,eletype k) {if(root==NULL){root1=(node*)malloc(sizeof(node)); if(root1==NULL){cout<<"not enough memory!"<<endl;exit(1);} root1->val=k;root1->lson=root1->rson=root1->parent=NULL; return root1; } if(k==root1->val)return root1; //不是根节点时先寻找到合适x再进行插入 else{ node *tmp=root1; node *qre=root1; // 需要记住中间量故不采用递归 while(tmp){ if(k<tmp->val){qre=tmp;tmp=tmp->lson;} else if(k>tmp->val){qre=tmp;tmp=tmp=tmp->rson;} else break;//x==tmp->val } if(tmp==NULL)//no x insert it {node *X=new node();X->val=k; X->parent=qre; if(qre->val>k)qre->lson=X; else qre->rson=X; tmp=X;//这样x没有和有都是存在tmp中 } root1=Splayfrombottom(root1,tmp); } return root1; } void SPTree::Insert(eletype key){ root=Insert(root,key); //splay_frombottom(key);Insert已经完成旋转 } node *SPTree::Remove(node *&root2,eletype x){ if(root2==NULL){cout<<"empty Tree!"<<endl;exit(1);} node *root1=Find1(root2,x);//要寻找的点已经变成根节点 if(x==root1->val){ if(root1->lson&&root1->rson) {node *ltree=root1->lson;node *rtree=root1->rson; ltree->parent=rtree->parent=NULL; free(root1); ltree=Findmax(ltree); ltree->rson=rtree; rtree->parent=ltree; return ltree; } else if(root1->lson){node *ltree=root1->lson; ltree->parent=NULL; free(root1); return ltree; } else if(root1->rson){node *rtree=root1->rson; rtree->parent=NULL; free(root1); return rtree; } else {free(root1);root1=NULL;return root1; } } else {cout<<"not exist!"<<endl;return root1;} } void SPTree::Remove(eletype k){ root=Remove(root,k); } void SPTree::Destroy(node *&root1){ if(root1==NULL)return; if(root1->lson)Destroy(root1->lson); if(root1->rson)Destroy(root1->rson); free(root1); } void SPTree::Destroy(){ Destroy(root); } void SPTree::postorder(node *root1)const{ if(root1){ postorder(root1->lson); postorder(root1->rson); cout<<root1->val<<" "; } } void SPTree::postorder(){ postorder(root); cout<<endl; } void SPTree::inorder(node_ root1)const{ if(root1){ inorder(root1->lson); cout<<root1->val<<" "; inorder(root1->rson); } } void SPTree::inorder(){ inorder(root); cout<<endl; }测试程序 #include<iostream> #include<stdlib.h> #include<string.h> #include"Tree.h" static int arr[]={ 10,50,40,30,20,60}; using namespace std; int main(){ int i; //AVLtree<int>*tree=new AVLtree<int>(); SPTree *tree=new SPTree(); int len=sizeof(arr)/sizeof(int); for(i=0;i<len;i++){; tree->Insert(arr[i]); } tree->postorder(); tree->inorder(); i=30; cout<<"Rotate at"<<" "<<i<<endl; tree->Remove(i); tree->postorder(); tree->inorder(); tree->Destroy(); cout<<endl; }