二叉排序树介绍

我们知道二叉树,每个结点最多有2棵子树,被称为左子树 和 右子树。
二叉排序树,显然也是一颗二叉树,它有更突出的特性在数据域上呈现排序的特性
二叉排序树中,每个树的左子树的数据域均小于它的根结点值,每个树的右子树的数据域均大于它的根结点值,每棵树的左、右子树 均为二叉排序树。从它特性很容易得到,对二叉排序树 进行中序遍历一定是升序序列

代码实现思路

二叉排序树,相关算法主要有:

  • 创建二叉排序树
  • 结点的查询
  • 结点的插入
  • 结点的删除

查询?很好实现吧,递归结点查询key的值是否相等 ,不相等就递归查询呗,递归出口 node==NULL,查询到结点通过传出参数返回,没有查询到返回离key值最近的结点

插入?根据二叉排序的特性进行插入呗,可以调用查询接口,如果二叉排序树没有该结点,则允许插入,将插入结点挂到返回的结点上呗

删除?删除就要分情况了,第3种情况有点绕,初学者要好好结合代码理解。

  1. 待删除结点,只有左子树,可以直接用其左子树替换删除结点,因为它的左子树上的所以结点都比它值小,仍然符合二叉排序的特性
  2. 待删除结点,只有右子树,同理可以直接使用其右子树替换删除结点,因为它的右子树上
  3. 待删除结点,左右子树都存在,如何是好呢?因为我们删除结点之后,仍然要满足二叉排序树的特性,每个树结点的左子树比都比它小,右子树都比它大!现在就要想到前面提到的特性了,二叉排排序树的中序遍历一定是升序序列,删除结点的数据域可以使用 中序遍历的前驱结点 或者后驱结点数据域替换?有木有,注意这里只替换数据域,因为原来的逻辑关系还要保留所以不能释放删除结点的内存,而释放的是替换的前驱结点或者后驱结点

创建二叉排序树?利用插入算法直接实现呗,刚开始为空二叉树,利用插入算法,可以生成二叉排序树。

实现代码

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>//二叉树节点
typedef struct BiNode
{int data;struct BiNode* lchild, *rchild;
}BiNode,*BiTree;typedef enum bool{ false,true }bool;//二叉树 中序遍历
void TraverseMid(BiTree root)
{if (root == NULL){return;}TraverseMid(root->lchild);printf("%d ", root->data);TraverseMid(root->rchild);
}
/*
二叉排序树的查询tree    查找的二叉树根结点parent  tree的双亲结点node    传出参数,查找到的结点指针,没找到为最接近key的结点的指针key     查找关键字
*/
bool SearchBST(BiTree root,BiTree parent,BiNode** node,int key )
{if (root == NULL)               //已经找到头了,还没有找到,返回最接近key的结点的指针{*node = parent;return false;}else{if (key < root->data)       //key 比root 小,搜索root的左子树{return SearchBST(root->lchild, root, node, key);}else if(key > root->data)   //key 比root 大,搜索root的右子树{return SearchBST(root->rchild, root, node, key);}else                        //key == root->data,找到key 返回{*node = root;return true;}}
}
//插入
bool InsertBST(BiTree root, int data)
{BiNode* node = NULL;if (SearchBST(root, NULL, &node, data)) //在树上有相同的结点,不允许插入{return false;}else{BiNode * newNode = (BiNode*)malloc(sizeof(BiNode));newNode->lchild = newNode->rchild = NULL;newNode->data = data;if (data < node->data){node->lchild = newNode;}else{node->rchild = newNode;}return true;}
}
//具体删除结点动作
bool DeleteNode(BiTree* node)
{BiTree tmp, pre, pre_parent;if ((*node)->lchild == NULL)                    //删除结点的左子树为NULL,将右子树顶替,释放删除结点内存{tmp = *node;*node = (*node)->rchild;                                free(tmp);}else if ((*node)->rchild == NULL)               //删除结点的右子树为NULL,将左子树顶替,释放删除结点内存{tmp = *node;*node = (*node)->lchild;free(tmp);}else                                            //删除结点的左右子树均不为空,删除结点数据换成其前驱或者后继的数据 结点并不释放,这里换成前驱{pre_parent = *node;pre = pre_parent->lchild;                   //pre 删除结点的中序遍历前驱结点while (pre->rchild != NULL)                 //while循环 寻找左子树中最大结点{pre_parent = pre;pre = pre->rchild;}if (pre == (*node)->lchild){(*node)->data = pre->data;(*node)->lchild = pre->lchild;}else{(*node)->data = pre->data;pre_parent->rchild = pre->lchild;}free(pre);}return true;
}
//删除
bool DeleteBST(BiTree *root, int key)
{if (root == NULL)return false;if (key == (*root)->data){return DeleteNode(root);}else if (key < (*root)->data){return DeleteBST(&(*root)->lchild, key);}else{return DeleteBST(&(*root)->rchild, key);}
}
//利用二叉树插入操作,创建二叉排序树
void CreateBST(BiTree *tree)
{int num;printf("请输入根节点数据:");scanf("%d", &num);*tree = malloc(sizeof(BiNode));(*tree)->data = num;(*tree)->lchild = (*tree)->rchild = NULL;while (1){printf("请输入结点数据(-1结束):");scanf("%d", &num);if (num == -1){break;}InsertBST(*tree, num);}
}int main(int argc, char *argv[])
{BiTree binarySortTree;//二叉排序树CreateBST(&binarySortTree);int menu, key,ret;BiNode* node;while (1){printf("----菜单----------------\n");printf("----1.中序遍历二叉排序树\n");printf("----2.查找结点\n");printf("----3.插入结点\n");printf("----4.删除结点\n");printf("----5.退出\n");scanf("%d", &menu);switch (menu){case 1:TraverseMid(binarySortTree);printf("\n");break;case 2:printf("请输入key:");scanf("%d", &key);ret = SearchBST(binarySortTree, NULL, &node, key);ret == true ? printf("%d存在\n",key) : printf("%d不存在\n", key);break;case 3:printf("请输入插入data:");scanf("%d", &key);ret = InsertBST(binarySortTree,key);ret == true ? printf("%d插入成功\n", key) : printf("%d插入失败\n", key);break;case 4:printf("请输入删除data:");scanf("%d", &key);ret = DeleteBST(&binarySortTree,key);ret == true ? printf("%d删除成功\n", key) : printf("%d删除失败\n", key);break;case 5:exit(0);}}return 0;
}

运行检测


数据结构与算法——二叉排序树详解以及代码实现相关推荐

  1. 【数据结构与算法】详解什么是图结构,并用代码手动实现一个图结构

    本系列文章[数据结构与算法]所有完整代码已上传 github,想要完整代码的小伙伴可以直接去那获取,可以的话欢迎点个Star哦~下面放上跳转链接 https://github.com/Lpyexplo ...

  2. JavaScript数据结构与算法——链表详解(下)

    在JavaScript数据结构与算法--链表详解(上)中,我们探讨了一下链表的定义.实现原理以及单链表的实现.接下来我们进一步了解一下链表的其他内容. 1.双向链表 双向链表实现原理图: 与单向链表不 ...

  3. JavaScript数据结构与算法——链表详解(上)

    注:与之前JavaScript数据结构与算法系列博客不同的是,从这篇开始,此系列博客采用es6语法编写,这样在学数据结构的同时还能对ECMAScript6有进一步的认识,如需先了解es6语法请浏览ht ...

  4. JavaScript数据结构与算法——队列详解(下)

    接下来会借助本人另一篇文章JavaScript数据结构与算法--队列详解(上)中实现的队列类及其方法实现一个应用. 配对问题 需求分析:在一个文件中保存着一份男女混合的数据,名称前以B开头表示男士,以 ...

  5. JavaScript数据结构与算法——列表详解(下),基于Nodejs实现一个列表应用

    1.上篇回顾: 上篇我们实现了一个列表类,并添加了一些属性,实现了比较多的方法,本文章将与大家一起使用列表实现一个图书借阅查询系统.需要使用JavaScript数据结构与算法--列表详解(上)中写好的 ...

  6. JavaScript数据结构与算法——数组详解(下)

    1.二维与多维数组 JavaScript只支持一维数组,但是通过在数组里保存数组元素的方式,可以轻松创建多维数组. 1.1 创建二维数组 二维数组类似一种由行和列构成的数组表格,在JavaScript ...

  7. TOPSIS(逼近理想解)算法原理详解与代码实现

    写在前面: 个人理解:针对存在多项指标,多个方案的方案评价分析方法,也就是根据已存在的一份数据,判断数据中各个方案的优劣.中心思想是首先确定各项指标的最优理想值(正理想值)和最劣理想值(负理想解),所 ...

  8. JavaScript数据结构与算法——列表详解(上)

    列表是一组有序的数据,每个数组中的数据项称为元素.数组相关知识不够了解的伙伴可以阅读本人上篇博客在JavaScript中,列表的元素可以是任意数据类型.列表中可以保存不定数量的元素,实际使用时元素的数 ...

  9. c++数据结构中 顺序队列的队首队尾_数据结构与算法—队列详解

    前言 栈和队列是一对好兄弟,前面我们介绍过数据结构与算法-栈详解,那么栈的机制相对简单,后入先出,就像进入一个狭小的山洞,山洞只有一个出口,只能后进先出(在外面的先出去).而队列就好比是一个隧道,后面 ...

最新文章

  1. MPB:农科院牧医所赵圣国组-微生物超高分子量DNA提取方法
  2. 微众WeCross 跨链平台(5)“UBI通用区块链接口”设计
  3. layui 单独使用日期组件
  4. 前端学习(1086):构造函数 原型 实例的关系
  5. 奥格斯堡大学计算机系,奥格斯堡大学七大科系设置简介
  6. 网易游戏java_2019秋招|网易游戏一面面经(Java开发)
  7. Kaggle Human Protein Atlas 比赛总结—如何闯入Top1%拿到金牌
  8. 怎么将layui导入php中,layui怎么导入Excel
  9. Bailian2701 Bailian3864 POJ NOI0105-39 与7无关的数【进制】
  10. servlet请求转发
  11. sicily 1282. Computer Game
  12. 自动驾驶 6-4 高级转向控制 - MPC Advanced Steering Control - MPC
  13. 抖音抖加是什么?dou+怎么投放?豆荚什么时候投最好?
  14. 从消费互联网到产业互联网:平台思维始终是主导
  15. R语言在图上标出点坐标_R语言做图plot参数
  16. spring BeanUtils.copyProperties只拷贝不为null的属性
  17. 【苹果家庭相册群发】CSR邮箱必须与证书所属的AppID相同
  18. java生成pdf方法_详解Java生成PDF文档方法|chu
  19. MPEG4和DivX的问题解答荟萃
  20. 使用PS快速抠图:(磁锁套抠图,快速工具,)

热门文章

  1. python raise_python raise 使用方法
  2. 蓝桥杯青少创意编程python组
  3. P2181 对角线(python3实现)
  4. 【ES6(2015)】新的声明方式 let、const
  5. python大作业爬虫_爬虫大作业
  6. Python笔记-Can’t reconnect until invalid transaction is rolled back
  7. Qt文档阅读笔记-Button QML Type官方解析及实例
  8. C++ opengl GL_LINE_LOOP的绘制
  9. 奥拉星插件flash下载手机版下载安装_奥拉星游戏插件
  10. linux磁盘权限 /srv,Linux学习笔记之解压压缩,磁盘分区,软件包管理,权限