• 二叉排序树


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

    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("
    Enter key to be deleted: ");
    23     scanf("%c", &key);
    24     BST_Delete(&root, key);
    25     BST_Traverse(root, visit);
    26 
    27     return 0;
    28 }

     运行结果如下:

  • 相关阅读:
    Codeforces Round #192 (Div. 2)
    STL删除vector或list的方法及注意的问题
    HDU 4614 (13年多校第二场1004)裸线段树
    将汇编的指令画在图片上==可以贴图法操作==动动图片图案指示就行了。(堆积木编译器)
    MySQL Connector/Python 安装、测试
    crtmpserver的架构简介
    hi3531的i2c部分 分类: HI3531 2014-03-18 14:41 948人阅读 评论(0) 收藏
    bootrom的构成 分类: vxWorks 2014-03-14 08:48 315人阅读 评论(0) 收藏
    bootrom脚本的创建 分类: vxWorks 2014-03-14 08:47 307人阅读 评论(0) 收藏
    ROM型启动方式概述 分类: vxWorks 2014-03-14 08:47 297人阅读 评论(0) 收藏
  • 原文地址:https://www.cnblogs.com/xiaomanon/p/4500869.html
Copyright © 2020-2023  润新知