C++实现的完整伸展树程序
来源:互联网 发布:扭力单位转换软件 编辑:程序博客网 时间:2024/05/21 12:41
原文链接:http://blog.csdn.net/iqrocket/article/details/8143689
这两天学了伸展树,然后参考老师的一些源代码自己尝试写了下完整的实现过程。不过发现程序有些错误,于是自己开始调试,通过仔细地调试、一步步跟踪最终解决了自己发现的问题,在这个过程中发现伸展树的伸展过程挺复杂的,不过自己也从中提高了自己调试程序的能力,也加深了自己对伸展树程序执行过程的理解。如果大家发现以下程序的问题的话欢迎一起交流学习。
- #include <iostream>
- using namespace std;
- struct Node
- {
- Node* lc,*rc,*par;
- int val,weight; //weight表示该值出现的次数
- }*root;
- //右旋的操作(以x为轴心)
- void rRotate(Node* x)
- {
- //先处理x的右孩子
- Node* y=x->par;
- y->lc=x->rc;
- //x的右孩子不为空时
- if(x->rc) x->rc->par=y;
- //处理x
- x->par=y->par;
- //当y有双亲时
- if(y->par)
- {
- if(y==y->par->lc)
- y->par->lc=x;
- else
- y->par->rc=x;
- }
- //处理y
- x->rc=y;
- y->par=x;
- }
- //左旋的操作(以x为轴心)
- void lRotate(Node* x)
- {
- //先处理x的右孩子
- Node* y=x->par;
- y->rc=x->lc;
- if(x->lc) x->lc->par=y;
- //处理x
- x->par=y->par;
- //当y有双亲时
- if(y->par)
- {
- if(y==y->par->lc)
- y->par->lc=x;
- else
- y->par->rc=x;
- }
- //处理y
- x->lc=y;
- y->par=x;
- }
- //将结点x调整到以y为双亲的位置
- void Splay(Node* x,Node* y)
- {
- while(x->par!=y)
- {
- //快结束时
- if(x->par->par==y)
- {
- //判断x是双亲的左孩子还是右孩子
- (x->par->lc==x)? rRotate(x):lRotate(x);
- }
- else
- {
- //如果x双亲是它双亲的左孩子时
- if(x->par->par->lc==x->par)
- {
- //左左结构
- if(x->par->lc==x)
- {
- //两次右旋
- rRotate(x->par);
- rRotate(x);
- }
- //左右结构
- else
- {
- //先左旋再右旋
- lRotate(x);
- rRotate(x);
- }
- }
- else
- {
- //右右结构
- if(x->par->rc==x)
- {
- //两次左旋
- lRotate(x->par);
- lRotate(x);
- }
- //右左结构
- else
- {
- //先右旋再左旋
- rRotate(x);
- lRotate(x);
- }
- }
- }
- }
- //如果y为空,则将x置为根
- if(0==y) root=x;
- }
- //查找结点的函数
- bool find(Node* x,int key)
- {
- if(!x) return false;
- //找到时
- if(x->val==key)
- {
- Splay(x,0); //将x伸展到树根
- return true;
- }
- else
- {
- //递归调用继续查找
- if(x->val>key)
- return find(x->lc,key);
- else
- return find(x->rc,key);
- }
- }
- //插入操作
- void insert(int key)
- {
- Node *ptr=root,*y=0;
- int lrChose=0; //判断新的结点应该为y的左孩子还是右孩子
- while(true)
- {
- //找到插入位置时
- if(!ptr)
- {
- ptr=new Node;
- ptr->lc=ptr->rc=0;
- ptr->val=key;
- ptr->weight=1;
- ptr->par=y;
- if(y!=0)
- {
- if(0==lrChose) y->lc=ptr;
- else y->rc=ptr;
- }
- Splay(ptr,0); //做伸展
- break;
- }
- y=ptr;
- if(key==ptr->val)
- {
- ++ptr->weight;
- Splay(ptr,0);
- break;
- }
- else
- if(key<ptr->val)
- {
- ptr=ptr->lc;
- lrChose=0;//表示新的结点在y的左孩子位置插入
- }
- else
- {
- ptr=ptr->rc;
- lrChose=1; //表示新的结点在y的右孩子位置插入
- }
- }
- }
- void preOrder(Node* r)
- {
- if(r!=0)
- {
- for(int i=0;i<r->weight;++i)
- cout<<r->val<<" ";
- preOrder(r->lc);
- preOrder(r->rc);
- }
- }
- //合并两棵树的函数
- Node* join(Node* n1,Node* n2)
- {
- //将n1和n2置为各自树的树根
- if(n1) n1->par=0;
- if(n2) n2->par=0;
- //当其中一棵树为空时直接返回另一棵
- if(!n1) return n2;
- if(!n2) return n1;
- n1->par=n2->par=0;
- Node* temp=n1;
- //找出n1树最大的结点(在最右边)
- while(temp->rc) temp=temp->rc;
- Splay(temp,0); //将temp伸展到树根(此时temp所在树的树根temp无右子树)
- temp->rc=n2;
- n2->par=temp;
- return temp; //返回合并后的树根
- }
- //删除结点的函数
- void remove(Node* x)
- {
- Splay(x,0); //先将x伸展到树根
- root=join(x->lc,x->rc); //合并左右子树
- delete x; //最后释放x的空间
- }
- //删除最小值
- void delMin(int& min,int& cnt)
- {
- Node* x=root;
- //最小值在最左边
- while(x->lc) x=x->lc;
- //通过引用参数带回改结点的一些信息
- min=x->val;
- cnt=x->weight;
- remove(x);
- }
- //删除最大值
- void delMax(int& max,int& cnt)
- {
- Node* x=root;
- //最大值在最右边
- while(x->rc) x=x->rc;
- //通过引用参数带回改结点的一些信息
- max=x->val;
- cnt=x->weight;
- remove(x);
- }
- int main()
- {
- //test
- int val=0;
- while(cin>>val)
- insert(val);
- preOrder(root); //前序遍历
- cout<<endl;
- cin.clear(); //恢复输入流
- int findNum=0;
- cout<<"Enter the integer you want find:";
- cin>>findNum;
- if(find(root,findNum))
- cout<<"Has found!"<<endl;
- else
- cout<<"Has not found!"<<endl;
- int max=0,min=0,cnt=0;
- delMin(min,cnt);
- cout<<"min:"<<min<<",num:"<<cnt<<endl;
- delMax(max,cnt);
- cout<<"max:"<<max<<",num:"<<cnt<<endl;
- }
通过伸展树,自己也获得了些启发,排序二叉树当输入的数据比较特殊时,所生成的树会像一条链表那样,这样会降低程序的效率,并且由于一般的排序二叉树一旦形成,结构很难再改变,因此这种结构会持续影响效率;而伸展树虽然刚建立起来时也有可能遇到这种情况,但随着操作越多,它的结构会越优化,算法效率会越高,因为它每执行一样操作几乎都会做一次伸展,使得树形结构趋于合理。而这正是我们做项目或者做系统需要考虑的,如何让自己的系统越来越优化而不是越来越糟糕使我们每个做项目的人都要去考虑的问题。
0 0
- C++实现的完整伸展树程序
- C++实现的完整伸展树程序
- 伸展树的实现
- c语言实现伸展树
- 伸展树的代码实现
- 伸展树的python实现
- SplayTree伸展树的实现
- 伸展树详解及实现(C语言)
- 伸展树 之 Java的实现
- 伸展树实现文件C语言(Aplaytree.c)
- 伸展树实现文件C语言(Splaytree.c)
- C++Builder 实现功能比较完整的托盘程序
- 伸展树(一)之 图文解析 和 C语言的实现
- 伸展树(一)之 图文解析 和 C语言的实现
- 伸展树(一)之 图文解析 和 C语言的实现
- 伸展树--Java实现
- 伸展树c++ 实现
- 伸展树实现
- jboss无法自动创建Queue和Topic 发布时出现错误javax.naming.namenotfoundexception: myqueue not bound
- 你所不知道的事儿--C++类模板的声明和实现不能分离
- Shell运算符:Shell算数运算符、关系运算符、布尔运算符、字符串运算符、文件测试运算符
- mybatis JDBC类型
- c++:把数据输入文件
- C++实现的完整伸展树程序
- 最长递增子序列
- Win7 C盘空间不足怎么扩大(C盘空间越来越小解决方法)[win7 32位亲测]
- 我的懒惰与畏难情绪
- Xcode 复制多行/移动某行/删除多行 快捷键
- 进程间通信WM_COPYDATA的基本实现
- jquery选择器
- Android模拟位置实现
- ACM zoj 1789(并查集实现)