伸展树(splay tree)实现
2012-08-31 11:08
232 查看
前面讲解了平衡二叉查找树,注意到一个结点被访问后,接下来很有可能被再次访问,所以可以采取把最近访问的结点上移(比如说移动到根结点),方便以下访问。这次要讲解的伸展树就是来解决该问题的。
伸展树又称自适应查找树,它的各种操作平均复杂度为O(lgn),其复杂度边界是均摊的。虽然某次操作可能需要代价O(n),但是连续M次操作的代价为O(M*lgn)。
伸展树的最核心的操作就是伸展,插入、删除、查找都要用到伸展操作。一般来说,伸展操作可以从搜索路径上最后一个结点开始,自底向上进行左旋和右旋操作,但是该方式需要知道父节点信息,而计算父节点或存储父节点需要较大的开销。于是一般采用自顶向下的实现方式。从根结点开始搜索某一结点x,不断进行左旋和右旋,同时把大于x的结点接到树R的左子树中,把小于x的结点接到树L的右子树上,直到查找路径的最后一个结点。然后把树进行重组,就得到了伸展后的树。
详细原理请看参考资料,参考资料[1][2]都对原理进行了详尽的阐述,并提供了实现。下面直接给出代码,代码中有详细注释。
参考资料:
[1]Data Structures and Algorithm Analysis in C++(third editon) (数据结构与算法分析C++描述,第3版 )
[2一篇博客文章:/article/5853733.html
[3]详细C和java实现:http://www.link.cs.cmu.edu/link/ftp-site/splaying/
伸展树又称自适应查找树,它的各种操作平均复杂度为O(lgn),其复杂度边界是均摊的。虽然某次操作可能需要代价O(n),但是连续M次操作的代价为O(M*lgn)。
伸展树的最核心的操作就是伸展,插入、删除、查找都要用到伸展操作。一般来说,伸展操作可以从搜索路径上最后一个结点开始,自底向上进行左旋和右旋操作,但是该方式需要知道父节点信息,而计算父节点或存储父节点需要较大的开销。于是一般采用自顶向下的实现方式。从根结点开始搜索某一结点x,不断进行左旋和右旋,同时把大于x的结点接到树R的左子树中,把小于x的结点接到树L的右子树上,直到查找路径的最后一个结点。然后把树进行重组,就得到了伸展后的树。
详细原理请看参考资料,参考资料[1][2]都对原理进行了详尽的阐述,并提供了实现。下面直接给出代码,代码中有详细注释。
#include <cstdlib> #include <iostream> using namespace std; typedef struct BinNode { int data; struct BinNode* left; struct BinNode* right; }BinNode, *BiTree; BinNode* splay(int i, BinNode* t) { BinNode N; //哨位结点 BinNode* L; BinNode* R; BinNode* y; // if(t == NULL) //空树 // return t; N.left = N.right = NULL; L = R = &N; //指针L和R初始指向哨位结点N while(true) { if(i < t->data) { if(t->left != NULL && i < t->left->data)//右旋转 { y = t->left; t->left = y->right; y->right = t; t = y; } if(t->left == NULL) { break; } R->left = t; //右链接,把t挂接为R的左子树 R = t; //t为新的R t = t->left; //在t的左子树中继续查找 } else if(i > t->data) { if(t->right != NULL && i > t->right->data)//左旋转 { y = t->right; t->right = y->left; y->left = t; t = y; } if(t->right == NULL) { break; } L->right = t; //左链接,把t挂接为L的右子树 L = t; //t为新的L t = t->right; //在t右子树中继续查找 } else //与当前根结点元素相同,重复 { break; } } L->right = t->left; //重新组合 R->left = t->right; t->left = N.right; //N.right为实际左子树的根 t->right = N.left; //N.left为实际右子树的根 return t; } BinNode* insert(int i, BinNode* t) { BinNode* newNode = new BinNode;//开辟一个新结点 newNode->data = i; newNode->left = newNode->right = NULL; if(t == NULL) //t为空树 { return newNode; } t = splay(i,t); //返回伸展后的新根结点 if(i < t->data) //欲插入元素在树中不存在,且小于根结点元素值 { newNode->left = t->left; newNode->right = t; t->left = NULL; return newNode; } else if(i > t->data) //欲插入元素在树中不存在,且小于根结点元素值 { newNode->right = t->right; newNode->left = t; t->right = NULL; } else //欲插入元素在树中存在,即等于根结点元素值 { delete newNode; return t; } } BinNode* remove(int i, BinNode* t) { BinNode* newRoot = NULL; if(t == NULL) //空树 { return t; } t = splay(i,t); if(i == t->data) //找到该元素结点 { if(t->left == NULL) //根结点左子树为空 { newRoot = t->right; } else { newRoot = splay(i, t->left);//newRoot必然指向t的左结点中最大的结点, //也就是伸展前t的前驱结点 newRoot->right= t->right; } delete t; return newRoot; } return t; //树中不存在该元素 } BinNode* search(int i, BinNode* t, bool& exist) { exist = false; if(t == NULL) return NULL; t = splay(i, t); if(i == t->data) { exist = true; } return t; } void inOrder(BinNode* t) { if(t) { inOrder(t->left); cout<<t->data<<" "; inOrder(t->right); } } void preOrder(BinNode* t) { if(t) { cout<<t->data<<" "; preOrder(t->left); preOrder(t->right); } } void printTree(BinNode* t) { cout<<"preOrder: "<<endl; preOrder(t); cout<<endl; cout<<"inOrder: "<<endl; inOrder(t); cout<<endl<<endl; } int main(int argc, char *argv[]) { BinNode* root = NULL; bool res = false; //insert for(int i=20; i>0; i--) root = insert(i,root); cout<<"after insert: "<<endl; printTree(root); //remove for(int i= 1; i<20; i += 2) root = remove(i,root); cout<<"after remove :"<<endl; printTree(root); //search cout<<"search elements: "<<endl; for(int i=1; i<20; i++) { root = search(i,root,res); if(res) { cout<<"("<<i<<","<<"yes"<<")"<<endl;; } else { cout<<"("<<i<<","<<"no"<<")"<<endl; } } cout<<"after search: "<<endl; printTree(root); system("PAUSE"); return EXIT_SUCCESS; }
参考资料:
[1]Data Structures and Algorithm Analysis in C++(third editon) (数据结构与算法分析C++描述,第3版 )
[2一篇博客文章:/article/5853733.html
[3]详细C和java实现:http://www.link.cs.cmu.edu/link/ftp-site/splaying/
相关文章推荐
- 二叉查找树,AVL,伸展树(splay tree)c/c++实现
- [从头学数学] 第258节 Python实现数据结构:伸展树(splay tree)
- 伸展树(Splay tree)图解与实现
- 伸展树( splay tree)
- splay tree(伸展树)学习小结(一)
- Splay Tree数组实现+详解
- Splay Tree(伸展树)[NOI2005]维修数列
- 伸展树C++类实现<一>自低向上设计
- 伸展树(指针版本实现排序)
- 伸展树(Splay tree)
- 伸展树c++ 实现
- 伸展树(一)之 图文解析 和 C语言的实现
- 伸展树的实现
- 纸上谈兵:伸展树(splay tree)
- 【BBST 之伸展树 (Splay Tree)】
- 树学习 ---------伸展树(splay Tree)
- 伸展树(Splay tree)浅谈
- 伸展树详解及实现(C语言)
- 伸展树的python实现
- 伸展树(Splay tree)学习小结