数据结构与算法——二叉排序树详解以及代码实现
二叉排序树介绍
我们知道二叉树,每个结点最多有2棵子树,被称为左子树 和 右子树。
二叉排序树,显然也是一颗二叉树,它有更突出的特性在数据域上呈现排序的特性。
在二叉排序树中,每个树的左子树的数据域均小于它的根结点值,每个树的右子树的数据域均大于它的根结点值,每棵树的左、右子树 均为二叉排序树。从它特性很容易得到,对二叉排序树 进行中序遍历一定是升序序列。
代码实现思路
二叉排序树,相关算法主要有:
- 创建二叉排序树
- 结点的查询
- 结点的插入
- 结点的删除
查询?很好实现吧,递归结点查询key的值是否相等 ,不相等就递归查询呗,递归出口 node==NULL,查询到结点通过传出参数返回,没有查询到返回离key值最近的结点。
插入?根据二叉排序的特性进行插入呗,可以调用查询接口,如果二叉排序树没有该结点,则允许插入,将插入结点挂到返回的结点上呗。
删除?删除就要分情况了,第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;
}
运行检测
数据结构与算法——二叉排序树详解以及代码实现相关推荐
- 【数据结构与算法】详解什么是图结构,并用代码手动实现一个图结构
本系列文章[数据结构与算法]所有完整代码已上传 github,想要完整代码的小伙伴可以直接去那获取,可以的话欢迎点个Star哦~下面放上跳转链接 https://github.com/Lpyexplo ...
- JavaScript数据结构与算法——链表详解(下)
在JavaScript数据结构与算法--链表详解(上)中,我们探讨了一下链表的定义.实现原理以及单链表的实现.接下来我们进一步了解一下链表的其他内容. 1.双向链表 双向链表实现原理图: 与单向链表不 ...
- JavaScript数据结构与算法——链表详解(上)
注:与之前JavaScript数据结构与算法系列博客不同的是,从这篇开始,此系列博客采用es6语法编写,这样在学数据结构的同时还能对ECMAScript6有进一步的认识,如需先了解es6语法请浏览ht ...
- JavaScript数据结构与算法——队列详解(下)
接下来会借助本人另一篇文章JavaScript数据结构与算法--队列详解(上)中实现的队列类及其方法实现一个应用. 配对问题 需求分析:在一个文件中保存着一份男女混合的数据,名称前以B开头表示男士,以 ...
- JavaScript数据结构与算法——列表详解(下),基于Nodejs实现一个列表应用
1.上篇回顾: 上篇我们实现了一个列表类,并添加了一些属性,实现了比较多的方法,本文章将与大家一起使用列表实现一个图书借阅查询系统.需要使用JavaScript数据结构与算法--列表详解(上)中写好的 ...
- JavaScript数据结构与算法——数组详解(下)
1.二维与多维数组 JavaScript只支持一维数组,但是通过在数组里保存数组元素的方式,可以轻松创建多维数组. 1.1 创建二维数组 二维数组类似一种由行和列构成的数组表格,在JavaScript ...
- TOPSIS(逼近理想解)算法原理详解与代码实现
写在前面: 个人理解:针对存在多项指标,多个方案的方案评价分析方法,也就是根据已存在的一份数据,判断数据中各个方案的优劣.中心思想是首先确定各项指标的最优理想值(正理想值)和最劣理想值(负理想解),所 ...
- JavaScript数据结构与算法——列表详解(上)
列表是一组有序的数据,每个数组中的数据项称为元素.数组相关知识不够了解的伙伴可以阅读本人上篇博客在JavaScript中,列表的元素可以是任意数据类型.列表中可以保存不定数量的元素,实际使用时元素的数 ...
- c++数据结构中 顺序队列的队首队尾_数据结构与算法—队列详解
前言 栈和队列是一对好兄弟,前面我们介绍过数据结构与算法-栈详解,那么栈的机制相对简单,后入先出,就像进入一个狭小的山洞,山洞只有一个出口,只能后进先出(在外面的先出去).而队列就好比是一个隧道,后面 ...
最新文章
- MPB:农科院牧医所赵圣国组-微生物超高分子量DNA提取方法
- 微众WeCross 跨链平台(5)“UBI通用区块链接口”设计
- layui 单独使用日期组件
- 前端学习(1086):构造函数 原型 实例的关系
- 奥格斯堡大学计算机系,奥格斯堡大学七大科系设置简介
- 网易游戏java_2019秋招|网易游戏一面面经(Java开发)
- Kaggle Human Protein Atlas 比赛总结—如何闯入Top1%拿到金牌
- 怎么将layui导入php中,layui怎么导入Excel
- Bailian2701 Bailian3864 POJ NOI0105-39 与7无关的数【进制】
- servlet请求转发
- sicily 1282. Computer Game
- 自动驾驶 6-4 高级转向控制 - MPC Advanced Steering Control - MPC
- 抖音抖加是什么?dou+怎么投放?豆荚什么时候投最好?
- 从消费互联网到产业互联网:平台思维始终是主导
- R语言在图上标出点坐标_R语言做图plot参数
- spring BeanUtils.copyProperties只拷贝不为null的属性
- 【苹果家庭相册群发】CSR邮箱必须与证书所属的AppID相同
- java生成pdf方法_详解Java生成PDF文档方法|chu
- MPEG4和DivX的问题解答荟萃
- 使用PS快速抠图:(磁锁套抠图,快速工具,)
热门文章
- python raise_python raise 使用方法
- 蓝桥杯青少创意编程python组
- P2181 对角线(python3实现)
- 【ES6(2015)】新的声明方式 let、const
- python大作业爬虫_爬虫大作业
- Python笔记-Can’t reconnect until invalid transaction is rolled back
- Qt文档阅读笔记-Button QML Type官方解析及实例
- C++ opengl GL_LINE_LOOP的绘制
- 奥拉星插件flash下载手机版下载安装_奥拉星游戏插件
- linux磁盘权限 /srv,Linux学习笔记之解压压缩,磁盘分区,软件包管理,权限