伸展树 模板(指针+数组)
来源:互联网 发布:js如何获取对象的长度 编辑:程序博客网 时间:2024/05/29 17:55
转载自:http://blog.csdn.net/leolin_/article/details/6436037
#include <iostream>using namespace std;#define MAXN 100010struct Node{ int key, sz, cnt; Node *ch[2], *pnt;//左右儿子和父亲 Node(){} Node(int x, int y, int z){ key = x, sz = y, cnt = z; } void rs(){ sz = ch[0]->sz + ch[1]->sz + cnt; }}nil(0, 0, 0), *NIL = &nil;struct Splay{//伸展树结构体类型 Node *root; int ncnt;//计算key值不同的结点数,注意已经去重了 Node nod[MAXN]; void init(){// 首先要初始化 root = NIL; ncnt = 0; } void rotate(Node *x, bool d){//旋转操作,d为true表示右旋 Node *y = x->pnt; y->ch[!d] = x->ch[d]; if (x->ch[d] != NIL) x->ch[d]->pnt = y; x->pnt = y->pnt; if (y->pnt != NIL){ if (y == y->pnt->ch[d]) y->pnt->ch[d] = x; else y->pnt->ch[!d] = x; } x->ch[d] = y; y->pnt = x; y->rs(); x->rs(); } void splay(Node *x, Node *target){//将x伸展到target的儿子位置处 Node *y; while (x->pnt != target){ y = x->pnt; if (x == y->ch[0]){ if (y->pnt != target && y == y->pnt->ch[0]) rotate(y, true); rotate(x, true); } else{ if (y->pnt != target && y == y->pnt->ch[1]) rotate(y, false); rotate(x, false); } } if (target == NIL) root = x; } /************************以上一般不用修改************************/ void insert(int key){//插入一个值 if (root == NIL){ ncnt = 0; root = &nod[++ncnt]; root->ch[0] = root->ch[1] = root->pnt = NIL; root->key = key; root->sz = root->cnt = 1; return; } Node *x = root, *y; while (1){ x->sz++; if (key == x->key){ x->cnt++; x->rs(); y = x; break; } else if (key < x->key){ if (x->ch[0] != NIL) x = x->ch[0]; else{ x->ch[0] = &nod[++ncnt]; y = x->ch[0]; y->key = key; y->sz = y->cnt = 1; y->ch[0] = y->ch[1] = NIL; y->pnt = x; break; } } else{ if (x->ch[1] != NIL) x = x->ch[1]; else{ x->ch[1] = &nod[++ncnt]; y = x->ch[1]; y->key = key; y->sz = y->cnt = 1; y->ch[0] = y->ch[1] = NIL; y->pnt = x; break; } } } splay(y, NIL); } Node* search(int key){//查找一个值,返回指针 if (root == NIL) return NIL; Node *x = root, *y = NIL; while (1){ if (key == x->key){ y = x; break; } else if (key > x->key){ if (x->ch[1] != NIL) x = x->ch[1]; else break; } else{ if (x->ch[0] != NIL) x = x->ch[0]; else break; } } splay(x, NIL); return y; } Node* searchmin(Node *x){//查找最小值,返回指针 Node *y = x->pnt; while (x->ch[0] != NIL){//遍历到最左的儿子就是最小值 x = x->ch[0]; } splay(x, y); return x; } void del(int key){//删除一个值 if (root == NIL) return; Node *x = search(key), *y; if (x == NIL) return; if (x->cnt > 1){ x->cnt--; x->rs(); return; } else if (x->ch[0] == NIL && x->ch[1] == NIL){ init(); return; } else if (x->ch[0] == NIL){ root = x->ch[1]; x->ch[1]->pnt = NIL; return; } else if (x->ch[1] == NIL){ root = x->ch[0]; x->ch[0]->pnt = NIL; return; } y = searchmin(x->ch[1]); y->pnt = NIL; y->ch[0] = x->ch[0]; x->ch[0]->pnt = y; y->rs(); root = y; } int rank(int key){//求结点高度 Node *x = search(key); if (x == NIL) return 0; return x->ch[0]->sz + 1/* or x->cnt*/; } Node* findk(int kth){//查找第k小的值 if (root == NIL || kth > root->sz) return NIL; Node *x = root; while (1){ if (x->ch[0]->sz +1 <= kth && kth <= x->ch[0]->sz + x->cnt) break; else if (kth <= x->ch[0]->sz) x = x->ch[0]; else{ kth -= x->ch[0]->sz + x->cnt; x = x->ch[1]; } } splay(x, NIL); return x; }}sp;int main(){ sp.init(); sp.insert(10); sp.insert(2); sp.insert(2); sp.insert(2); sp.insert(3); sp.insert(3); sp.insert(10); for (int i = 1; i <= 7; i++) cout << sp.findk(i)->key << endl; cout<<sp.searchmin(sp.root)->key<<endl; sp.del(2); sp.del(3); sp.del(1); return 0;}突然发现这种指针形模板有他的局限性,所以这面这是数组模拟#include<iostream>#include<cstring>#include<cstdio>using namespace std;#define MAXN 1000000struct Spaly{ int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN]; int sz,root; void init() { sz=root=0; } inline void clear(int x) { ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=0; } inline bool get(int x) { return ch[f[x]][1]==x; } inline void update(int x) { if (x) { size[x]=cnt[x]; if (ch[x][0]) size[x]+=size[ch[x][0]]; if (ch[x][1]) size[x]+=size[ch[x][1]]; } } inline void rotate(int x) { int old=f[x],oldf=f[old],whichx=get(x); ch[old][whichx]=ch[x][whichx^1]; f[ch[old][whichx]]=old; ch[x][whichx^1]=old; f[old]=x; f[x]=oldf; if (oldf) ch[oldf][ch[oldf][1]==old]=x; update(old); update(x); } inline void splay(int o, int aim)/// { while(f[o] != aim) { int fa=f[o], g = f[fa]; if(g != aim) rotate(fa); rotate(o); } update(o); if(!aim) root = o; } inline void insert(int x) { if (root==0) { sz++; ch[sz][0]=ch[sz][1]=f[sz]=0; root=sz; size[sz]=cnt[sz]=1; key[sz]=x; return; } int now=root,fa=0; while(1) { if (x==key[now]) { cnt[now]++; update(now); update(fa); splay(now); break; } fa=now; now=ch[now][key[now]<x]; if (now==0) { sz++; ch[sz][0]=ch[sz][1]=0; f[sz]=fa; size[sz]=cnt[sz]=1; ch[fa][key[fa]<x]=sz; key[sz]=x; update(fa); splay(sz); break; } } } inline int find(int x) { int now=root,ans=0; while(1) { if (x<key[now]) now=ch[now][0]; else { ans+=(ch[now][0]?size[ch[now][0]]:0); if (x==key[now]) { splay(now); return ans+1; } ans+=cnt[now]; now=ch[now][1]; } } } inline int findx(int x) { int now=root; while(1) { if (ch[now][0]&&x<=size[ch[now][0]]) now=ch[now][0]; else { int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now]; if (x<=temp) return key[now]; x-=temp; now=ch[now][1]; } } } inline int pre() { int now=ch[root][0]; while (ch[now][1]) now=ch[now][1]; return now; } inline int next() { int now=ch[root][1]; while (ch[now][0]) now=ch[now][0]; return now; } inline void del(int x) { int whatever=find(x); if (cnt[root]>1) { cnt[root]--; update(root); return; } if (!ch[root][0]&&!ch[root][1]) { clear(root); root=0; return; } if (!ch[root][0]) { int oldroot=root; root=ch[root][1]; f[root]=0; clear(oldroot); return; } else if (!ch[root][1]) { int oldroot=root; root=ch[root][0]; f[root]=0; clear(oldroot); return; } int leftbig=pre(),oldroot=root; splay(leftbig); ch[root][1]=ch[oldroot][1]; f[ch[oldroot][1]]=root; clear(oldroot); update(root); }} sp;int main(){ sp.init(); sp.insert(5); sp.insert(7); sp.insert(9); sp.del(5); sp.del(9); sp.insert(9); printf("%d %d\n",sp.size[sp.root],sp.root);}
阅读全文
0 0
- 伸展树 模板(指针+数组)
- wikioi 1396 伸展树(两个模板)
- Splay伸展树&模板
- 伸展树(splay)模板
- 伸展树模板
- 伸展树模板题
- 伸展树模板
- 伸展树模板
- 伸展树(指针版本实现排序)
- Splay伸展树模板总结
- HDU 3487(伸展树模板)
- HDU4453(伸展树模板题)
- Splay tree 伸展树 (不含区间操作)模板
- 【模板篇】伸展树Splay Tree(此坑待填)
- 字典树模板(数组实现和指针实现)
- HNOI2002营业额统计 (伸展树---模板题)
- ACM常用模板——伸展树
- bzoj 1014伸展树 模板题
- 类似SCSF中EventBroker解耦事件调用方和接受方,打破"+="带来的耦合
- 【知识】UML类图与类的关系详解
- js调试技巧 实用
- CF C. Classroom Watch【枚举】
- Docker容器实战-容器的网络及数据
- 伸展树 模板(指针+数组)
- WebRequestInterceptor WebRequestInterceptor的应用
- iOS将状态栏设置成白色
- IIS停止服务 报错Connections_Refused
- C++ STL replace()函数常用用法详解
- 纯CSS实现瀑布流布局
- HTTP协议请求响应过程和HTTPS工作原理
- java读取文件方法大全(转)
- 文件导入测试的测试点