十二章:二叉查找树
一般来说操作时间跟高度成正比 O(lg n)
性质:对于任何节点x,其左子树关键字最大不超过key[x],右子树关键字最小不小于key[x]
遍历;
INORDER-TREE-WALK(x){
if(x != nil)
INORDER-TREE-WALK(left[x]);
print(x);
INORDER-TREE-WALK(right[ x] );
}
TREE-SEARCH(x, k){
if( x= NIL || key[x] == k)return x;
if( k < key [x])return TREE-SEARCH(left[x], k);
return TREE-SEARCH(right[x], k);
}
注意:像这种尾递归很容易修改成非递归形式,一般用一个while循环即可
最大元素与最小元素分别在树的最左与最右边
TREE-MINIMUM(x){
while( letf,[x] != nil) x = left[x];
return x;
}
前驱跟后继:
前驱:x没有左孩子,其前驱是祖先中作为右孩子的父亲,x有左孩子,前驱是其左孩子的TREE-MAXIMUM
TREE-PREDECESSOR(x){
if( left[x] != nil) return TREE-MAXIMUM(left[x]);
y = p[x]; z = x;
while( y != nil && left[y] = z){ x = y; y = p[y];}
return y;
}
TREE-SUCCESSOR(x)
二叉查找树的插入于删除
TREE-INSERT(T, z){
y = NIL
x= root[T];
while(x != NIL){
y = x;
if(key[z] < key[x])x = left[x];
else x = right[x];
}
p[z] = y;
if(y == NIL) root[T] \ z;
else if(key [z] < key [y])left[y] = z;
else right[y] = z;
}
TREE-DELETE(T,z){ //三种情况,z无孩子,z只有一个孩子,z有两个孩子
if( left[z] == NIL && right[z] == NIL){
if(p [z] == NIL)root[T] = NIL;
else if( left[ p[z] ] == z)left[ p[z] ] = NIL;
else right[ p[z] ] = NIL;
}
else if(left[z] == NIL || right[z] == NIL){
if(left[z] == NIL){
p[right[ z] = p[z];
if(left [p [z] ] == z)left[p [z] ] = right[z];
else right[p [z] ] = right[z];
}
else //
}
else{
y = TREE-SUCCESSOR(z);
if(right [y] != NIL) {p[right[ y] ] = p[y]; left[p [y] = right[y];}
key[z] = key[y];
}
}//注意树上是这三种情况的优化,比我写的简洁很多