以下用大O表示节点,ABC表示三个集合。
仅分析左子树的情况,因为对称,右子树的情况一样。
插入节点前
O
/ \
O A
/ \
B C
插入节点后:
O
/ \
O A
/ \
B C
/
O
此时造成了最高节点的不平衡,说明了B+2 - A = 2;另外可以知道B = C,考虑B<C,那么在插入节点前最高点就已经不平衡了,考虑B > C,那么最高的左子树就已经不平衡了,而不应该考虑最高点。所以此时可以知道A = B = C。
左子树单旋转之后:
O
/ \
B O
/ / \
O C A
对于最高点来说,左子树深度为B+1,右子树深度为A+1,即B + 1。
对比插入后的树,可以知道只有原最高节点的深度发生变化,所以只需更新该节点的深度。
另外一种情况:
插入后:
O
/ \
O A
/ \
B C
/
O
此时如果单旋转,结果为:
O
/ \
B O
/ \
C A
/
O
明显这个情况并没有得到解决。
所以首先要单右旋转最高节点的左子树,结果为:
O
/ \
C A
/ \
O O
/
B
此时可以知道C集合的深度发生了变化,需要更新C的深度,而之前更新的是最高点的深度,所以在旋转时需要更新原最高点和现最高点的深度。
第二次左旋转原最高点,结果为
C
/ \
O O
/ / \
B O A
这里面的正确有一些缺陷,应该把ABC集合多展开几层,否则在双旋转时的证明有些怪异,反正就是这个思路,因为画图实在是太麻烦了。
最后是代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> typedef struct _node { int element; int high; struct _node *lefttree; struct _node *righttree; }node; int gethigh(node *t) { if(t == 0) return -1; return t->high; } node *singlerotatewithleft(node *t) { node *tmp = t->lefttree; t->lefttree = tmp->righttree; tmp->righttree = t; tmp->high = ((gethigh(tmp->lefttree) > gethigh(tmp->righttree))?gethigh(tmp->lefttree):gethigh(tmp->righttree)) + 1; t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + 1; return tmp; } node *singlerotatewithright(node *t) { node *tmp = t->righttree; t->righttree = tmp->lefttree; tmp->lefttree = t; tmp->high = ((gethigh(tmp->lefttree) > gethigh(tmp->righttree))?gethigh(tmp->lefttree):gethigh(tmp->righttree)) + 1; t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + 1; return tmp; } node *doubleroratewithleft(node *t) { t->lefttree = singlerotatewithright(t->lefttree); return singlerotatewithleft(t); } node *doubleroratewithright(node *t) { t->righttree = singlerotatewithleft(t->righttree); return singlerotatewithright(t); } node *insert(node *t,int element) { if (t == 0) { t = (node *)malloc(sizeof(node)); t->element = element; t->lefttree = t->righttree = 0; } else if(t->element > element){ t->lefttree = insert(t->lefttree,element); if(gethigh(t->lefttree) - gethigh(t->righttree) == 2) if(element < t->lefttree->element) t= singlerotatewithleft(t); else t= doubleroratewithleft(t); } else if(t->element < element){ t->righttree = insert(t->righttree,element); if(gethigh(t->righttree) - gethigh(t->lefttree) == 2) if(element > t->righttree->element) t= singlerotatewithright(t); else t= doubleroratewithright(t); } t->high = ((gethigh(t->lefttree) > gethigh(t->righttree))?gethigh(t->lefttree):gethigh(t->righttree)) + 1; return t; } node *find(node *t,int element) { if(t == 0) return 0; else if(t->element > element) return find(t->lefttree,element); else if(t->element < element) return find(t->righttree,element); else return t; } node* findmin(node *t) { if(t == 0) return 0; if(t->lefttree == 0) return t; else return findmin(t->lefttree); } node *delele(node *t,int element) { if(t == 0) return 0; else if(t->element > element) t->lefttree = delele(t->lefttree,element); else if(t->element < element) t->righttree = delele(t->righttree,element); else { if(t->lefttree && t->righttree) { node *tmp; tmp = findmin(t->righttree); t->element = tmp->element; t->righttree = delele(t->righttree,tmp->element); } else { node *tmp; tmp = t->lefttree?t->lefttree:t->righttree; free(t); t = tmp; } } return t; } void printtree(node *t) { if(t == 0) return; printtree(t->lefttree); printf("%d\t",t->element); printf("high = %d\n",t->high); printtree(t->righttree); } int main() { int a[10] = {1,2,3,4,5,6,7,8,9}; node *t; int i = 1; t = insert(0,1); for(;i<7;i++){ t = insert(t,a[i]); //printtree(t); //sleep(1); } //t = delele(t,6); printtree(t); printf("\n"); //while(1); return 0; }