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