数据结构排序二叉树(下)

哎,调了几天深度学习模型,今天来更新排序二叉树

文章目录

前言

一、排序二叉树的结构定义

二、在排序二叉树添加数据

三、定义创建排序二叉树函数

四、查找一棵二叉排序树中的结点x的所在层数

五、删除二叉排序树中T关键字x的节点

六、查找二叉排序树中的所有小于key的关键字

七、已知二叉排序中每个节点值为整形,采用二叉链表存储,编写算法删除二叉排序树中所有关键字小于x的

八.总结与验证


前言

排序二叉树就这几个习题了,但实际上还有更难得几道习题,因为实现起来真的难,而且在使用中也难用到所以就给大家几道简单的例子,帮助大家来熟悉.


一、排序二叉树的结构定义

typedef int ElemType;
//二叉排序树左>根>右,树中没有重复值
//二叉排序树的数据结构
typedef struct BSTNode {ElemType data;//数据节点类型为intstruct BSTNode* lchild;struct BSTNode* rchild;
}BSTNode,*BSTree;

其实就是二叉树的数据结构只是对树中节点数据有约束.

二、在排序二叉树添加数据

//插入节点函数
void insertNode(BSTree& T, ElemType e) {if (T == NULL) {//找到合适的位置插入节点BSTNode* pNode = (BSTNode*)malloc(sizeof(BSTNode));assert(pNode);pNode->data = e;pNode->lchild = NULL;pNode->rchild = NULL;T = pNode;//别忘了链接上}else if (T->data > e) {//插入左子树insertNode(T->lchild, e);}else if (T->data < e) {//插入右子树insertNode(T->rchild, e);}
}

由于二叉树左>根>右所以在构建二叉树使需要满足要求.

算法思想:运用递归思想,将待插入数据与当前节点比较如果小于当前节点数据表明插入数据应插在当前节点的左子树,反之当如果插入数据比当前的节点数据大,则表明插入数据应插到当前数据的右子树,直到遇到空节点表示找到插入位置,申请节点插入即可.

三、定义创建排序二叉树函数

//定义创建二叉排序树函数
BSTNode* creatBSTree() {BSTNode* T = NULL;ElemType enternum = 999999;//999999表示退出输入printf("请输入序列(以999999作为结束标志):");while (scanf("%d", &enternum) && enternum != 999999) {insertNode(T, enternum);}return T;
}

就依次插入节点就可以了.

四、查找一棵二叉排序树中的结点x的所在层数

//例1:查找一棵二叉排序树中的结点x的所在层数
int nodelevel(BSTree T, int level,ElemType x) {if (T == NULL) {//没找到返回0return 0;}else if (T->data > x) {//左子树寻找return nodelevel(T->lchild, level+1, x);}else if (T->data < x) {//右子树寻找return nodelevel(T->rchild, level+1, x);}else {return level;//返回层次}
}

算法思想:采用递归的形式,但传参时传入一个层数,找到返回即可,注意这里层数是值传递,不是址传递.

五、删除二叉排序树中T关键字x的节点

//例2:删除二叉排序树中T关键字x的节点
//算法思想:首先找到节点x此时就要分情况讨论(1)节点既没有左孩子又没有右孩子,直接删去节点并将指针制空;
//(2)节点只有左孩子(或只有右孩子),指针指向左孩子(右孩子)并删除节点;
//(3)节点既有左孩子又有右孩子,此时有两种处理方案1.找到左子树的最大节点将右孩子链接到最大节点的右指针
//2.找到右子树的最小节点,将左孩子链接到最小节点的左指针
void deleteOperation(BSTree& T) {if (T == NULL) return;if (T->lchild == NULL && T->rchild == NULL) {free(T);T = NULL;}else if (T->lchild != NULL && T->rchild == NULL) {BSTNode* tmp = T;T = T->lchild;free(tmp);tmp = NULL;}else if (T->lchild == NULL && T->rchild != NULL) {BSTNode* tmp = T;T = T->rchild;free(tmp);tmp = NULL;}else {//既有左孩子又有右孩子BSTNode* pMaxnode = T->lchild;while (pMaxnode->rchild != NULL) {pMaxnode = pMaxnode->rchild;}pMaxnode->rchild = T->rchild;BSTNode* tmp = T;T = T->lchild;free(tmp);tmp = NULL;}
}
//查找并删除节点
void deletenode(BSTree &T,ElemType x) {if (T != NULL) {if (T->data == x) {deleteOperation(T);}else if (T->data < x) {deletenode(T->rchild, x);}else {deletenode(T->lchild, x);}}}

这个算法还有一个思想就是找到左子树最大的节点复制到删除节点上,递归在左子树删除左子树最大节点.

字有点丑见谅.

六、查找二叉排序树中的所有小于key的关键字

//例3:查找二叉排序树中的所有小于key的关键字
void getSmallerkey(BSTree T, ElemType key) {if (T != NULL) {getSmallerkey(T->lchild, key);if (T->data < key) {printf("%d ", T->data);getSmallerkey(T->rchild, key);}}
}

七、已知二叉排序中每个节点值为整形,采用二叉链表存储,编写算法删除二叉排序树中所有关键字小于x的

//例4:已知二叉排序中每个节点值为整形,采用二叉链表存储,编写算法删除二叉排序树中所有关键字小于x的节点
//定义递归删除树函数
void deleteFunc(BSTree& T) {//递归删除树if (T != NULL) {deleteFunc(T->lchild);deleteFunc(T->rchild);free(T);T = NULL;}
}
//定义删除小于x节点的函数(采用先序遍历的思想)
void deleteSmallernode(BSTree &T,ElemType x) {if (T != NULL) {if (T->data == x) {//根节点等于x说明左子树都小于x递归删除deleteFunc(T->lchild);}else if (T->data < x) {//根节点小于x左子树均小于x,删除根节点在递归删除右子树小于x的节点deleteFunc(T->lchild);BSTNode* tmp = T;T = T->rchild;free(tmp);tmp = NULL;deleteSmallernode(T, x);}else {//根节点大于x递归删除左子树小于x的节点deleteSmallernode(T->lchild, x);}}
}

八.总结与验证

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<malloc.h>
#include<assert.h>
typedef int ElemType;
//二叉排序树左>根>右,树中没有重复值
//二叉排序树的数据结构
typedef struct BSTNode {ElemType data;//数据节点类型为intstruct BSTNode* lchild;struct BSTNode* rchild;
}BSTNode,*BSTree;
//插入节点函数
void insertNode(BSTree& T, ElemType e) {if (T == NULL) {//找到合适的位置插入节点BSTNode* pNode = (BSTNode*)malloc(sizeof(BSTNode));assert(pNode);pNode->data = e;pNode->lchild = NULL;pNode->rchild = NULL;T = pNode;//别忘了链接上}else if (T->data > e) {//插入左子树insertNode(T->lchild, e);}else if (T->data < e) {//插入右子树insertNode(T->rchild, e);}
}
//定义创建二叉排序树函数
BSTNode* creatBSTree() {BSTNode* T = NULL;ElemType enternum = 999999;//999999表示退出输入printf("请输入序列(以999999作为结束标志):");while (scanf("%d", &enternum) && enternum != 999999) {insertNode(T, enternum);}return T;
}
//中序遍历二叉排序树
void inorderTraverse(BSTree T) {if (T != NULL) {inorderTraverse(T->lchild);printf("%d ", T->data);inorderTraverse(T->rchild);}
}
//先序遍历二叉排序树
void preorderTraverse(BSTree T) {if (T != NULL) {printf("%d ", T->data);preorderTraverse(T->lchild);preorderTraverse(T->rchild);}
}
//遍历二叉排序树(先,中)
void Traverse(BSTree T) {//这函数主要是用来验证printf("中序遍历结果:");inorderTraverse(T);printf("\n");printf("先序遍历结果:");preorderTraverse(T);printf("\n");
}
//例1:查找一棵二叉排序树中的结点x的所在层数
int nodelevel(BSTree T, int level,ElemType x) {if (T == NULL) {//没找到返回0return 0;}else if (T->data > x) {//左子树寻找return nodelevel(T->lchild, level+1, x);}else if (T->data < x) {//右子树寻找return nodelevel(T->rchild, level+1, x);}else {return level;//返回层次}
}
//例2:删除二叉排序树中T关键字x的节点
//算法思想:首先找到节点x此时就要分情况讨论(1)节点既没有左孩子又没有右孩子,直接删去节点并将指针制空;
//(2)节点只有左孩子(或只有右孩子),指针指向左孩子(右孩子)并删除节点;
//(3)节点既有左孩子又有右孩子,此时有两种处理方案1.找到左子树的最大节点将右孩子链接到最大节点的右指针
//2.找到右子树的最小节点,将左孩子链接到最小节点的左指针
void deleteOperation(BSTree& T) {if (T == NULL) return;if (T->lchild == NULL && T->rchild == NULL) {free(T);T = NULL;}else if (T->lchild != NULL && T->rchild == NULL) {BSTNode* tmp = T;T = T->lchild;free(tmp);tmp = NULL;}else if (T->lchild == NULL && T->rchild != NULL) {BSTNode* tmp = T;T = T->rchild;free(tmp);tmp = NULL;}else {//既有左孩子又有右孩子BSTNode* pMaxnode = T->lchild;while (pMaxnode->rchild != NULL) {pMaxnode = pMaxnode->rchild;}pMaxnode->rchild = T->rchild;BSTNode* tmp = T;T = T->lchild;free(tmp);tmp = NULL;}
}
//查找并删除节点
void deletenode(BSTree &T,ElemType x) {if (T != NULL) {if (T->data == x) {deleteOperation(T);}else if (T->data < x) {deletenode(T->rchild, x);}else {deletenode(T->lchild, x);}}}
//例3:查找二叉排序树中的所有小于key的关键字
void getSmallerkey(BSTree T, ElemType key) {if (T != NULL) {getSmallerkey(T->lchild, key);if (T->data < key) {printf("%d ", T->data);getSmallerkey(T->rchild, key);}}
}
//例4:已知二叉排序中每个节点值为整形,采用二叉链表存储,编写算法删除二叉排序树中所有关键字小于x的节点
//定义递归删除树函数
void deleteFunc(BSTree& T) {//递归删除树if (T != NULL) {deleteFunc(T->lchild);deleteFunc(T->rchild);free(T);T = NULL;}
}
//定义删除小于x节点的函数(采用先序遍历的思想)
void deleteSmallernode(BSTree &T,ElemType x) {if (T != NULL) {if (T->data == x) {//根节点等于x说明左子树都小于x递归删除deleteFunc(T->lchild);}else if (T->data < x) {//根节点小于x左子树均小于x,删除根节点在递归删除右子树小于x的节点deleteFunc(T->lchild);BSTNode* tmp = T;T = T->rchild;free(tmp);tmp = NULL;deleteSmallernode(T, x);}else {//根节点大于x递归删除左子树小于x的节点deleteSmallernode(T->lchild, x);}}
}
int main() {//创建一棵二叉排序树//8 5 4 7 9 10 999999BSTree T = creatBSTree();Traverse(T);printf("\n");int a = 10;printf("数据节点为%d的节点所在层次:%d\n", a,nodelevel(T, 1, a));printf("删除数据节点前树的结构\n");Traverse(T);deletenode(T, 5);printf("删除数据节点后树的结构\n");Traverse(T);printf("比8小的数据节点有:");getSmallerkey(T, 8);printf("\n");int b = 8;printf("删除比%d小的所有节点前\n",b);Traverse(T);deleteSmallernode(T, b);printf("删除比%d小的所有节点后\n", b);Traverse(T);return 0;
}

兄弟们马上要到图啦,最有意思的一部分要到啦.加油哦

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/416801.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字化变革时代|打破瓶颈 海格里斯HEGERLS四向穿梭车系统技术的新突破

数字化转型是国内外市场环境的必然趋势, 从各大中小企业的创新驱动力来说&#xff0c;物联网、云计算、人工智能、大数据等等&#xff0c;都是创新的技术革命&#xff0c;也是当前大环境下所追寻的数字化变革。面对数字化制造时代的到来&#xff0c;河北沃克不失时机地布局了自…

【人工智能平台】ubuntu22.04.3部署cube-studio

简介&#xff1a;本次安装是在虚拟机上进行&#xff0c;需要给虚拟机至少分配16GB&#xff0c;分配8GB时系统会卡死。 一、环境&#xff1a; 主机环境&#xff1a;win11&#xff08;全程科学&#xff09;vm虚拟机 虚拟机&#xff1a;ubuntu22.04.3桌面版&#xff08;新装&…

Unity vs Godot :哪个游戏引擎更适合你?

Unity vs Godot &#xff1a;哪个游戏引擎更适合你&#xff1f; 游戏引擎的选择对开发过程和最终产品质量有着重大影响。近年来&#xff0c;Godot和Unity这两款引擎受到广泛关注。本文将从多个维度对两者进行比较&#xff0c;以期为开发者提供正确的选择建议。 Godot和Unity都有…

Spring的@Async使用防坑

很多人会直接只用Async来执行异步操作。但是这里面有一个问题&#xff0c;如果都是用spring的默认实现&#xff0c;是有坑的。 当我们开启 EnableAsync注解 就可以使用Async注解来执行异步操作了。 我们现在通过EnableAsync注解去打开spring异步世界的坑。 走JDK的动态代理&a…

力扣 | 11. 盛最多水的容器

双指针解法–对撞指针 暴力解法public int maxArea1(int[] height) {int n height.length;int ans 0;for (int i 0; i < n; i) {for (int j i 1; j < n; j) {int area Math.min(height[i], height[j]) * (j - i);ans Math.max(ans, area);}}return ans;}双指针解法…

探索curl的高级应用:HTTP请求的大师级技巧

探索curl的高级应用&#xff1a;HTTP请求的大师级技巧 引言高级用法概览1. HTTP请求与响应处理2. 身份验证与安全3. 进阶技巧4. Cookie管理与会话保持5. 脚本自动化 HTTP请求与响应处理1. 自定义请求头2. 发送数据3. 处理响应 身份验证与安全1. 基本认证2. 摘要认证3. HTTPS安全…

MyBatis框架基础到进阶

1、为什么要学习MyBatis 如果没有MyBatis框架&#xff0c;我们依靠JDBC和连接池已经能够很好的和数据库进行交互了&#xff0c;而学习MyBatis框架最核心的原因是为了减少SQL语句对代码的侵入性。 因为在过往不管是使用连接池还是JDBC Templete&#xff0c;所有的SQL语句都写在代…

Docker项目部署()

1.创建文件夹tools mkdir tools 配置阿里云 Docker Yum 源 : yum install - y yum - utils device - mapper - persistent - data lvm2 yum - config - manager -- add - repo http://mirrors.aliyun.com/docker- ce/linux/centos/docker - ce.repo 更新 yum 缓存 yum makec…

记录Qt和opencv 新环境配置过程

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、Qt是什么&#xff1f;二、Qt的版本三、安装步骤1.下载Qt2.双击安装包.exe开始安装3. 需要登陆才能继续安装&#xff0c;没有的就用邮箱注册账号4.注意安装路…

AOP的入门案例(登录时间记录)

导入坐标&#xff08;pom.xml&#xff09; <dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version><scope>provided</scope></depe…

细讲Labview条件结构用法及易错点

本文讲解Labview条件结构的常用情景及易错点注意事项。帮助大家深刻理解并使用该结构&#xff0c;欢迎点赞关注加评论&#xff0c;有问题可以私聊或在下方评论区留言。 本文程序均附在文章结尾&#xff0c;可自行下载学习。 博主之前讲过Labview事件结构、For循环等的基础知识介…

Visual Studio 设置编辑框(即代码编辑器)的背景颜色

在Visual Studio 中设置编辑框&#xff08;即代码编辑器&#xff09;的背景颜色&#xff0c;可以按照以下步骤进行&#xff1a; 打开Visual Studio。在菜单栏上找到并点击“工具”(Tools)选项。在下拉菜单中选择“选项”(Options)。在“选项”对话框中&#xff0c;导航至“环境…