二叉排序树

首先定义二叉树的存储结构

1 /* 二叉树的二叉链表结点结构定义 */
2 typedef char TreeElemType;
3 typedef struct tagBiTreeNode {
4     TreeElemType data;//结点数据
5     struct tagBiTreeNode *lchild, *rchild;//结点左右孩子指针
6 }BiTrNode, *BiTrNodePtr;

 

二叉排序树的查找函数实现如下:

 1 /*
 2 ** @brief 二叉排序树查找的递归实现
 3 ** @param 
 4 **     @arg root  : 根结点
 5 **     @arg key   : 待查找的关键字
 6 **     @arg parent: root节点的双亲结点,初始值为NULL
 7 **     @arg result: 查找结果中找到的结点指针
 8 ** @retval 如果查找成功,则result指向该元素结点并返回1;
 9 **        如果失败,则result指向查找路径上访问的最后一个节点。
10 */
11 int BST_Search(BiTrNodePtr root, TreeElemType key, BiTrNodePtr parent, BiTrNodePtr *result)
12 {
13     if (root == NULL){//查找不成功
14         *result = parent;
15         return 0;
16     }
17     if (key == root->data){//查找成功
18         *result = root;
19         return 1;
20     }else if (key < root->data){//被查找元素小于根结点元素
21         return BST_Search(root->lchild, key, root, result);//在左子树继续查找
22     }else{//被查找元素大于根结点元素
23         return BST_Search(root->rchild, key, root, result);//在右子树继续查找
24     }
25 }

在实现了查找的基础上,我们可以实现二叉查找树的插入(构造)函数:

 1 /*
 2 ** @brief  二叉排序树的插入
 3 ** @retval 当二叉树root中不存在关键字等于key的数据元素时,
 4 **         插入key并返回1;否则直接返回0
 5 */
 6 int BST_Insert(BiTrNodePtr *root, TreeElemType key)
 7 {
 8     BiTrNodePtr result = NULL, s = NULL;
 9     if (!BST_Search(*root, key, NULL, &result)){//查找不成功
10         s = (BiTrNodePtr)malloc(sizeof(BiTrNode));
11         s->data = key;
12         s->lchild = s->rchild = NULL;
13 
14         if (result == NULL){
15             *root = s;//插入节点s为新的根结点
16         }else if (key < result->data){
17             result->lchild = s;//插入结点s为左孩子
18         }else{
19             result->rchild = s;//插入结点s为右孩子
20         }
21 
22         return 1;//插入成功
23     }else{//树中已经存在关键字相同的结点,不再插入
24         return 0;//插入失败
25     }
26 }

为了验证,我们可以实现二叉树的中序遍历:

 1 /*
 2 ** 中序遍历二叉排序树
 3 */
 4 void BST_Traverse(BiTrNodePtr root, void (*visit)(BiTrNodePtr))
 5 {
 6     if (root == NULL) return;
 7     BST_Traverse(root->lchild, visit);
 8     visit(root);
 9     BST_Traverse(root->rchild, visit);
10 }

二叉排序树的删除操作相对复杂一点,代码如下:

 1 /*
 2 ** 从二叉排序树中删除结点p,并重接它的左子树或右子树
 3 */
 4 int DeleteNode(BiTrNodePtr *p)
 5 {
 6     BiTrNodePtr q = NULL, s = NULL;
 7     if ((*p)->rchild == NULL){//右子树为空,则只需要重接它的左子树
 8         q = *p;
 9         *p = (*p)->lchild;
10         free(q);
11     }else if ((*p)->lchild == NULL){//左子树为空,只需要重接它的右子树
12         q = *p;
13         *p = (*p)->rchild;
14         free(q);
15     }else{//左右子树均不为空
16         q = *p;
17         s = (*p)->lchild;//s指向待删除结点的左孩子
18         while (s->rchild){
19             q = s;//q存储s的双亲结点
20             s = s->rchild;//一直向右子树查找,指导右子树的尽头(找到待删除结点的前驱)
21         }
22         //找到p的直接前驱s
23         (*p)->data = s->data;//用s的值替代待删除结点的值
24         if (q != (*p)){//如果待删除结点的直接前驱不是其左孩子
25             q->rchild = s->lchild;//将s的左子树重新接到其双亲结点的右子树
26         }else{//如果待删除结点的直接前驱是其左孩子
27             q->lchild = s->lchild;//重接q的左子树
28         }
29         free(s);//删除前驱结点
30     }
31     return 1;
32 }
33 
34 /*
35 ** 若二叉排序树root中存在关键字等于key的数据元素,则删除该结点
36 ** 并返回1;如果不存在,则返回0
37 */
38 int BST_Delete(BiTrNodePtr *root, TreeElemType key)
39 {
40     if (NULL == *root){//没有找到关键字等于key的结点
41         return 0;
42     }
43 
44     if ( key == (*root)->data ){//找到关键字等于key的结点
45         return DeleteNode(root);
46     }else if ( key < (*root)->data ){//如果关键字小于根结点元素值
47         return BST_Delete(&(*root)->lchild, key);//在左子树删除
48     }else{//如果关键字大于根结点元素值
49         return BST_Delete(&(*root)->rchild, key);//在右子树删除
50     }
51 }

最后给一段测试代码:

 1 #include <stdio.h>
 2 #include "search.h"
 3 
 4 void visit(BiTrNodePtr e)
 5 {
 6     printf(" %c ", e->data);
 7 }
 8 
 9 int main(void)
10 {
11     BiTrNodePtr root = NULL;
12     TreeElemType key;
13 
14     scanf("%c", &key);
15     while (key != '#'){
16         BST_Insert(&root, key);
17         scanf("%c", &key);
18     }
19     BST_Traverse(root, visit);
20     
21     fflush(stdin);//刷新输入缓冲区
22     printf("\nEnter key to be deleted: ");
23     scanf("%c", &key);
24     BST_Delete(&root, key);
25     BST_Traverse(root, visit);
26 
27     return 0;
28 }

 运行结果如下:

posted @ 2015-05-13 16:38  XiaoManon  阅读(191)  评论(0编辑  收藏  举报