伸展树(splay)
2015-10-28 09:34
267 查看
在书上或者别人的博客上看的时候感觉还不是很明显,但是自己写出来并调试之后感觉真是十分的炫酷
特别是调试的时候,感觉这棵树就好像活的一样
(在不断的访问最后的一个节点的时候,能看到树的层数在不断的减少,直到理论的极限
(如果想知道一颗活的树是什么样的体验,可以自己调试一发
(这里窝为了方便直接用0~n-1作为树的元素,你也可以选择自己喜欢的一个方式
(因为只是第一份代码,所以还没有添加动态删除节点和动态添加节点这两个功能
(以后的可能还会优化图形界面和其它的一些功能
(如果有时间的话
(第一份代码写的比较复杂,不过既然已经调试出来了,还是先放在这里了
=============update==============
给出一些学习的建议吧
刚开始学的时候建议在纸上模拟几遍左旋和右旋的过程,最好能到想到zig或zag就可以在脑海里模拟出这个过程(
然后看双旋的时候也是
双旋到想到x在哪个方向能在纸上模拟出这个过程就可以了
然后就可以自己独立写一遍了,(这个时候会感觉自己写的十分复杂。。。就像我上面那个代码一样QAQ
再接着可以压缩自己的代码(提示:根据双旋的对称性)
以及下面是我优化过的代码
特别是调试的时候,感觉这棵树就好像活的一样
(在不断的访问最后的一个节点的时候,能看到树的层数在不断的减少,直到理论的极限
(如果想知道一颗活的树是什么样的体验,可以自己调试一发
(这里窝为了方便直接用0~n-1作为树的元素,你也可以选择自己喜欢的一个方式
(因为只是第一份代码,所以还没有添加动态删除节点和动态添加节点这两个功能
(以后的可能还会优化图形界面和其它的一些功能
(如果有时间的话
(第一份代码写的比较复杂,不过既然已经调试出来了,还是先放在这里了
#include<bits/stdc++.h> using namespace std; struct node{ int val; node *l,*r; }; node *newnode(int x){ node *ret = new node; ret->l=ret->r=NULL; ret->val = x; return ret; } void zig(node* &o){ node *k = o->l; o->l = k->r; k->r = o; o = k; } void zag(node* &o){ node *k = o->r; o->r = k->l; k->l = o; o = k; } void inser(int x,node *rot){ if(rot->val > x){ if(rot->l==NULL) rot->l = newnode(x); else inser(x,rot->l); } else{ if(rot->r==NULL){ rot->r = newnode(x); } else{ inser(x,rot->r); } } } bool fndx(node *&rot,int x,int &d){ if(rot->val == x){ d = 0; return true; } else{ int k; if(rot->val > x){ //to left if(rot->l == NULL || fndx(rot->l,x,k)==false) return false; else{ if(k==0){ d = -1; return true; } else{ if(k == -1){ // zig zig zig(rot);zig(rot); } else{ // k=1, zag zig zag(rot->l);zig(rot); } d = 0; return true; } } } else{ if(rot->r == NULL || fndx(rot->r,x,k)==false) return false; else{ if(k==0){ d = 1; return true; } else{ if(k == 1){ // zag zag zag(rot);zag(rot); } else{ // zig zag zig(rot->r);zag(rot); } d = 0; return true; } } } } } bool fnd(node *&root,int x){ int k; if(fndx(root,x,k)==false){ return false; } else{ if(k){ if(k==1) zag(root); else zig(root); } return true; } } void out(node *s,int d,int k){ if(s->l) out(s->l,d+1,-1); for(int i =0;i<d;i++) printf(" "); if(k!=0){ printf(" "); if(k==1) printf("\\"); else printf("/"); } else{ printf("-"); } printf("%d\n",s->val); if(s->r) out(s->r,d+1,1); } int n =30; int main(){ node *root = newnode(0); for(int i = 1;i<n;i++){ inser(i,root); } out(root,0,0); int x; while(~scanf("%d",&x)){ printf("after find %d",x); puts("----------------"); fnd(root,x); out(root,0,0); } return 0; }
=============update==============
给出一些学习的建议吧
刚开始学的时候建议在纸上模拟几遍左旋和右旋的过程,最好能到想到zig或zag就可以在脑海里模拟出这个过程(
然后看双旋的时候也是
双旋到想到x在哪个方向能在纸上模拟出这个过程就可以了
然后就可以自己独立写一遍了,(这个时候会感觉自己写的十分复杂。。。就像我上面那个代码一样QAQ
再接着可以压缩自己的代码(提示:根据双旋的对称性)
以及下面是我优化过的代码
#include<bits/stdc++.h> using namespace std; #define l ch[0] #define r ch[1] struct node{ int val; node *ch[2]; }; node *newnode(int x){ node * ret = new node; ret->l=ret->r=NULL; ret->val = x; return ret; } void inser(node *rot,int x){ int d = (rot->val > x)?0:1; if(rot->ch[d]) inser(rot->ch[d],x); else rot->ch[d]=newnode(x); } void out(node *s,int d,int k){ if(s->l) out(s->l,d+1,-1); for(int i =0;i<d;i++) printf(" "); if(k!=0){ printf(" "); if(k==1) printf("\\"); else printf("/"); } else{ printf("-"); } printf("%d\n",s->val); if(s->r) out(s->r,d+1,1); } void print(node *s){ puts("-----"); out(s,0,0); puts("====="); } node *root = newnode(0); void zg(node* &o,int d){ node * k = o->ch[d]; o->ch[d] = k->ch[1^d]; k->ch[1^d] = o; o = k; } int splay(int x,node *& rot){ if(!rot) return -1; if(rot->val == x) return 2; else{ int d = rot->val > x?0:1; int k = splay(x,rot->ch[d]); if(k==2) return d; if(k==-1) return -1; if(k==d){ zg(rot,k); zg(rot,k); } else{ zg(rot->ch[d],k); zg(rot,d); } return 2; } } bool fnd(node* &root,int x){ int k = splay(x,root); if(k==-1) return false; if(k!=2){ zg(root,k); } return true; } int n =16; int main(){ for(int i = 1;i<n;i++){ inser(root,i); } print(root); int x; while(~scanf("%d",&x)){ if(x>=n){ for(int i = 0;i<n;i++){ fnd(root,i); print(root); } continue; } if(x < 0){ for(int i =n-1;i>=0;i--){ fnd(root,i); print(root); } continue; } printf("after find %d",x); fnd(root,x); print(root); } return 0; }
相关文章推荐
- InstallShield错误解决方案
- mysql 连接url中useUnicode=true&characterEncoding=UTF-8 的作用
- Android的TextView/EditText使用CharacterStyle&SpannableString来处理图片显示、字体样式、超链接等
- LeetCode H-Index II
- 体验为王 2015年10月在线视频网站性能评测
- Fragment的checkStateLoss IllegalStateException: Can not perform this action after onSaveInstanceStat
- 记录个小问题:解决SSH中的Host key verification failed
- window.open() 父子页面的传参&传值问题
- 摇一摇 怎么实现
- Android的TextView使用Html来处理图片显示、字体样式、超链接等
- 线段树练习之——分块解法
- Material Design - Touch feedback , Reveal effect
- 认识Jquery easyui 使用Easyui-layout 布局
- 8.5.2 Optimizing InnoDB Transaction Management
- mdev 自动创建设备结点
- MySql学习笔记----一些小知识点
- JAVA写入Mysql中文乱码解决方法
- TFS2015源代码管理器无法建立团队项目的问题
- Windows API 之 CreateThread、GetExitCodeThread(未完)
- Android学习笔记:实现下拉刷新的ListView