标签:
看了这么久的平衡树,是时候做个总结了。
以poj 3481为例,敲了四份代码,分别是Treap ,Size Balance Tree,Avl Tree,splay tree。
唯独少了红黑树T_T。。。
总的来说每种平衡树各有各的优点吧:
Treap写起来简单上手也快如果熟练的话不到十分种可以敲完。
SBT速度快名不虚传。。。
Avl树高度平衡吧,不过实际的效果不尽如人意,可能是我实现的姿势不对吧/(ㄒoㄒ)/~~
splay tree各方面比较均衡,特别的伸展树在维护序列方面相对其它几种树优势明显。
可持久化的Treap除外(因为没比较过故不好妄下结论)。
总之,只要理解了旋转操作和建树的思想,每种树实现起来都很方便。。。
好了少扯淡了代码如下:
Treap:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define Max_N 110000 #define size(_) ((_)==NULL ? 0 : (_)->size) typedef struct _trp{ int client, key, size, fix; struct _trp *ch[2]; }treap, *Treap; treap stack[Max_N]; int sz = 0; int run(){ static int x = 1840828537; x += (x << 2) | 1; return x; } void update(Treap x){ if (x == NULL) return; x->size = size(x->ch[0]) + size(x->ch[1]) + 1; } void rotate(Treap *x, int d){ Treap k = (*x)->ch[!d]; (*x)->ch[!d] = k->ch[d]; k->ch[d] = *x; k->size = (*x)->size; update(*x); *x = k; } void insert(Treap *x, int client, int key){ if (*x == NULL){ *x = &stack[sz++]; (*x)->ch[0] = (*x)->ch[1] = NULL; (*x)->key = key, (*x)->size = 1, (*x)->client = client, (*x)->fix = run(); } else { int d = key > (*x)->key; insert(&((*x)->ch[d]), client, key); update(*x); if ((*x)->ch[d]->fix < (*x)->fix) rotate(x, !d); } } void _delete(Treap *x, int key){ if (*x == NULL) return; if ((*x)->key == key){ if (!(*x)->ch[0] || !(*x)->ch[1]){ *x = (*x)->ch[0] ? (*x)->ch[0] : (*x)->ch[1]; } else { int d = (*x)->ch[0]->fix < (*x)->ch[1]->fix; rotate(x, d); _delete(&((*x)->ch[d]), key); } } else { _delete(&((*x)->ch[key>(*x)->key]), key); } if (*x != NULL) update(*x); } Treap find_kth(Treap x, int k){ int t = 0; for (; x != NULL;){ t = size(x->ch[0]); if (k == t + 1) break; else if (k <= t) x = x->ch[0]; else k -= t + 1, x = x->ch[1]; } return x; } int main(){ #ifdef LOCAL freopen("in.txt", "r", stdin); freopen("out.txt", "w+", stdout); #endif int n, a, b; Treap root = NULL, ret = NULL; while (~scanf("%d", &n) && n){ ret = NULL; if (2 == n || 3 == n){ if (2 == n && root) ret = find_kth(root, root->size); else if (3 == n && root) ret = find_kth(root, 1); if (!ret || !root) printf("0\n"); else printf("%d\n", ret->client), _delete(&root, ret->key); } else { scanf("%d %d", &a, &b); insert(&root, a, b); } } return 0; }SBT:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define Max_N 110000 #define size(_) ((_)==NULL ? 0 : (_)->size) typedef struct _sbt{ int client, key, size; struct _sbt *ch[2]; }SBTNode, *SBT; SBTNode stack[Max_N]; int sz = 0; void rotate(SBT *x, int d){ SBT k = (*x)->ch[!d]; (*x)->ch[!d] = k->ch[d]; k->ch[d] = *x; k->size = (*x)->size; (*x)->size = size((*x)->ch[0]) + size((*x)->ch[1]) + 1; *x = k; } void Maintain(SBT *x, int d){ if ((*x)->ch[d] == NULL) return; if (size((*x)->ch[d]->ch[d]) > size((*x)->ch[!d])) rotate(x, !d); else if (size((*x)->ch[d]->ch[!d]) > size((*x)->ch[!d])) rotate(&((*x)->ch[d]), d), rotate(x, !d); else return; Maintain(&((*x)->ch[d]), 0); Maintain(&((*x)->ch[!d]), 1); Maintain(x, 0), Maintain(x, 1); } void insert(SBT *x, int client, int key){ if (*x == NULL){ *x = &stack[sz++]; (*x)->ch[0] = (*x)->ch[1] = NULL; (*x)->key = key, (*x)->size = 1, (*x)->client = client; } else { (*x)->size++; insert(&((*x)->ch[key > (*x)->key]), client, key); Maintain(x, key >= (*x)->key); } } void _delete(SBT *x, int key){ if (*x == NULL) return; (*x)->size--; if ((*x)->key == key){ if (!(*x)->ch[0] || !(*x)->ch[1]){ *x = (*x)->ch[0] ? (*x)->ch[0] : (*x)->ch[1]; } else { SBT ret = (*x)->ch[1]; for (; ret->ch[0] != NULL; ret = ret->ch[0]); _delete(&((*x)->ch[1]), (*x)->key = ret->key); } } else { _delete(&((*x)->ch[key > (*x)->key]), key); } } SBT find_kth(SBT x, int k){ int t = 0; for (; x != NULL;){ t = size(x->ch[0]); if (k == t + 1) break; else if (k <= t) x = x->ch[0]; else k -= t + 1, x = x->ch[1]; } return x; } int main(){ #ifdef LOCAL freopen("in.txt", "r", stdin); freopen("out.txt", "w+", stdout); #endif int n, a, b; SBT root = NULL, ret = NULL; while (~scanf("%d", &n) && n){ ret = NULL; if (2 == n || 3 == n){ if (2 == n && root) ret = find_kth(root, root->size); else if (3 == n && root) ret = find_kth(root, 1); if (!ret || !root) printf("0\n"); else printf("%d\n", ret->client), _delete(&root, ret->key); } else { scanf("%d %d", &a, &b); insert(&root, a, b); } } return 0; }Avl:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define Max_N 200000 #define _max(a,b) ((a)>(b)?(a):(b)) #define size(_) ((_)==NULL ? 0 : (_)->size) #define Height(_) ((_)==NULL ? -1 : (_)->Height) typedef struct _avl{ int client, key, size, Height; struct _avl *ch[2]; }AvlTree, *Avl; AvlTree stack[Max_N]; int sz = 0; void update(Avl x){ if (x == NULL) return; x->size = size(x->ch[0]) + size(x->ch[1]) + 1; x->Height = _max(Height(x->ch[0]), Height(x->ch[1])) + 1; } void rotate(Avl *x, int d){ Avl k = (*x)->ch[!d]; (*x)->ch[!d] = k->ch[d]; k->ch[d] = *x; update(*x); update(k); *x = k; } void Maintain(Avl *x, int d){ if (Height((*x)->ch[d]) - Height((*x)->ch[!d]) == 2){ if (Height((*x)->ch[d]->ch[d]) - Height((*x)->ch[d]->ch[!d]) == 1) rotate(x, !d); else if (Height((*x)->ch[d]->ch[d]) - Height((*x)->ch[d]->ch[!d]) == -1){ rotate(&((*x)->ch[d]), d), rotate(x, !d); } } } void insert(Avl *x, int client, int key){ if (*x == NULL){ *x = &stack[sz++]; (*x)->ch[0] = (*x)->ch[1] = NULL; (*x)->key = key, (*x)->Height = 0, (*x)->size = 1, (*x)->client = client; } else { int d = key > (*x)->key; insert(&((*x)->ch[d]), client, key); update(*x); Maintain(x, d); } } void _delete(Avl *x, int key){ if (*x == NULL) return; if ((*x)->key == key){ if (!(*x)->ch[0] || !(*x)->ch[1]){ *x = (*x)->ch[0] ? (*x)->ch[0] : (*x)->ch[1]; } else { Avl ret = (*x)->ch[1]; for (; ret->ch[0] != NULL; ret = ret->ch[0]); _delete(&((*x)->ch[1]), (*x)->key = ret->key); } } else { _delete(&((*x)->ch[key > (*x)->key]), key); } if (*x != NULL){ update(*x); Maintain(x, 0), Maintain(x, 1); } } Avl find_kth(Avl x, int k){ int t = 0; for (; x != NULL;){ t = size(x->ch[0]); if (k == t + 1) break; else if (k <= t) x = x->ch[0]; else k -= t + 1, x = x->ch[1]; } return x; } int main(){ #ifdef LOCAL freopen("in.txt", "r", stdin); freopen("out.txt", "w+", stdout); #endif int n, a, b; Avl root = NULL, ret = NULL; while (~scanf("%d", &n) && n){ ret = NULL; if (2 == n || 3 == n){ if (2 == n && root) ret = find_kth(root, root->size); else if (3 == n && root) ret = find_kth(root, 1); if (!ret || !root) printf("0\n"); else printf("%d\n", ret->client), _delete(&root, ret->key); } else { scanf("%d %d", &a, &b); insert(&root, a, b); } } return 0; }
splay tree:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define Max_N 200000 #define size(_) ((_)==null ? 0 : (_)->size) typedef struct _spt{ int client, key, size; struct _spt *pre, *ch[2]; }splay; splay *null, *root, stack[Max_N]; int sz = 0; splay *_calloc(int client, int key){ splay *p = &stack[sz++]; p->pre = p->ch[0] = p->ch[1] = null; p->size = 1, p->key = key, p->client = client; return p; } void push_up(splay *x){ if (x == null) return; x->size = size(x->ch[0]) + size(x->ch[1]) + 1; } void rotate(splay *x, int d){ splay *y = x->pre; y->ch[!d] = x->ch[d]; if (x->ch[d] != null) x->ch[d]->pre = y; x->pre = y->pre; if (y->pre != null) y->pre->ch[y->pre->ch[0] != y] = x; x->ch[d] = y; y->pre = x; push_up(y); if (y == root) root = x; } void splay_splay(splay *x, splay *f){ for (; x->pre != f;){ if (x->pre->pre == f){ rotate(x, x->pre->ch[0] == x); } else { splay *y = x->pre, *z = y->pre; if (z->ch[0] == y){ if (y->ch[0] == x) rotate(y, 1), rotate(x, 1); else rotate(x, 0), rotate(x, 1); } else { if (y->ch[1] == x) rotate(y, 0), rotate(x, 0); else rotate(x, 1), rotate(x, 0); } } } push_up(x); } void insert(int client, int key){ splay *fp = null, *p = root; if (root == null){ root = _calloc(client, key); return; } for (; p != null;){ fp = p; if (key > p->key) p = p->ch[1]; else p = p->ch[0]; } p = _calloc(client, key); if (fp->key > key) fp->ch[0] = p; else fp->ch[1] = p; p->pre = fp; splay_splay(p, null); push_up(p); } void _delete(int key){ splay *p = root, *rt = null; while (p != null && p->key != key) p = p->ch[key > p->key]; if (p == null) return; splay_splay(p, null); rt = root->ch[0]; if (rt == null){ rt = root->ch[1]; } else { splay *tmp = rt->ch[1]; while (tmp != null && tmp->ch[1] != null) tmp = tmp->ch[1]; if (tmp != null) splay_splay(tmp, root); rt = root->ch[0]; rt->ch[1] = root->ch[1]; root->ch[1]->pre = rt; } root = rt; root->pre = null; if (root != null) push_up(root); } void initialize(){ null = _calloc(-1, -1); null->size = 0; root = null; } splay *find_kth(splay *x, int k){ int t = 0; for (; x != null;){ t = size(x->ch[0]); if (k == t + 1) break; else if (k <= t) x = x->ch[0]; else k -= t + 1, x = x->ch[1]; } if (x == null){ return null; } else { splay_splay(x, null); return root; } } int main(){ #ifdef LOCAL freopen("in.txt", "r", stdin); freopen("out.txt", "w+", stdout); #endif int n, a, b; initialize(); splay *ret = NULL; while (~scanf("%d", &n) && n){ ret = NULL; if (2 == n || 3 == n){ if (2 == n && root) ret = find_kth(root, root->size); else if (3 == n && root) ret = find_kth(root, 1); if (ret == null || root == null) printf("0\n"); else printf("%d\n", ret->client), _delete(ret->key); } else { scanf("%d %d", &a, &b); insert(a, b); } } return 0; }
最后上对比结果:从上到下依次是,splay tree, treap,sbt,avl。
其实蒟蒻只会用c语言不会c++,但提交代码的时候选了c++和gcc两种o(╯□╰)o。。。
标签:
原文地址:http://blog.csdn.net/u012077152/article/details/44944499