二叉排序树(Binary Sort Tree,BST)又称为二叉查找树,二叉搜索树,具有以下性质:
- 如果左子树不为空,则左子树上所有结点的值都小于根结点的值.
- 如果右子树不为空,则右子树上所有结点的值均大于根结点的值.
- 左右子树也分别为二叉排序树.
- 树中没有相同的结点.
如果用中序遍历二叉排序树,则遍历结果是一个递增序列.
与二分查找类似,查找过程中和关键字比较的次数不超过树的深度。当二叉排序树形态比较对称,此时与折半查找相似,时间复杂度为$O(\log_{2}n)$,最坏情况下二叉排序树是一颗单树(只有左子树或只有右子树),时间复杂度为$O(n)$。
BST结点结构
1 2 3 4 5 6 7
| typedef int Type; typedef struct BSTreeNode{ Type key; struct BSTreeNode *left; struct BSTreeNode *right; struct BSTreeNode *parent; }Node, *BSTree;
|
查找
递归实现
1 2 3 4 5 6 7 8 9
| Node* bstree_search(BSTree x, Type key) { if (x==NULL || x->key==key) return x; if (key < x->key) return bstree_search(x->left, key); else return bstree_search(x->right, key); }
|
非递归实现
1 2 3 4 5 6 7 8 9 10 11
| Node* iterative_bstree_search(BSTree x, Type key) { while ((x!=NULL) && (x->key!=key)) { if (key < x->key) x = x->left; else x = x->right; } return x; }
|
查找最小结点:返回tree为根结点的二叉树的最小结点。
1 2 3 4 5 6 7 8
| Node* bstree_minimum(BSTree tree) { if (tree == NULL) return NULL; while(tree->left != NULL) tree = tree->left; return tree; }
|
查找最大结点:返回tree为根结点的二叉树的最大结点。
1 2 3 4 5 6 7 8
| Node* bstree_maximum(BSTree tree) { if (tree == NULL) return NULL; while(tree->right != NULL) tree = tree->right; return tree; }
|
找结点的后继结点。即,查找二叉树中数据值大于该结点的最小结点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Node* bstree_successor(Node *x) { if (x->right != NULL) return bstree_minimum(x->right);
Node* y = x->parent; while ((y!=NULL) && (x==y->right)) { x = y; y = y->parent; } return y; }
|
找结点的前驱结点。即,查找二叉树中数据值小于该结点的最大结点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| Node* bstree_predecessor(Node *x) { if (x->left != NULL) return bstree_maximum(x->left);
Node* y = x->parent; while ((y!=NULL) && (x==y->left)) { x = y; y = y->parent; } return y; }
|
插入
结点的插入具有递归性,最终结点将作为叶子结点(意味着结点的left,right指针为 null)插入到树中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| static Node* bstree_insert(BSTree tree, Node *z) { Node *y = NULL; Node *x = tree; while (x != NULL) { y = x; if (z->key < x->key) x = x->left; else x = x->right; } z->parent = y; if (y==NULL) tree = z; else if (z->key < y->key) y->left = z; else y->right = z; return tree; }
Node* insert_bstree(BSTree tree, Type key) { Node *z; if ((z=create_bstree_node(key, NULL, NULL, NULL)) == NULL) return tree; return bstree_insert(tree, z); }
|
删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| void DeleteBST(BitNode *T, int key) { BitNode *q,*s; BitNode *node=searchBST(T,key,NULL,&s); if(node==NULL) { printf("\n此树中没有此节点\n"); return ; } else { if(node->lchild==NULL && node->rchild==NULL) { printf("此节点是一个叶子节点\n"); node->parent->lchild=node->parent->rchild=NULL; free(node); } else if(node->rchild==NULL) { printf("此节点只有左子树\n"); q=node; node=node->lchild; if(q==q->parent->rchild) q->parent->rchild=node; else q->parent->lchild=node;
free(q); } else if(node->lchild==NULL) { printf("此结点只有右子树\n"); q=node; node=node->rchild; if(q==q->parent->rchild) q->parent->rchild=node; else q->parent->lchild=node;
free(q); } else { q=node; s=node->lchild; while(s->rchild) { q=s; s=s->rchild; } node->data=s->data; if(q!=node) q->rchild=s->lchild; else q->lchild=s->lchild; free(s); } } }
|
另一种写法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| static Node* bstree_delete(BSTree tree, Node *z) { Node *x=NULL; Node *y=NULL;
if ((z->left == NULL) || (z->right == NULL) ) y = z; else y = bstree_successor(z);
if (y->left != NULL) x = y->left; else x = y->right;
if (x != NULL) x->parent = y->parent;
if (y->parent == NULL) tree = x; else if (y == y->parent->left) y->parent->left = x; else y->parent->right = x;
if (y != z) z->key = y->key;
if (y!=NULL) free(y); return tree; }
Node* delete_bstree(BSTree tree, Type key) { Node *z, *node; if ((z = bstree_search(tree, key)) != NULL) tree = bstree_delete(tree, z); return tree; }
void destroy_bstree(BSTree tree) { if (tree==NULL) return ; if (tree->left != NULL) destroy_bstree(tree->left); if (tree->right != NULL) destroy_bstree(tree->right); free(tree); }
|