二叉排序树的创建

二叉排序树就是节点经过排序构建起的二叉树,其有以下性质:

  1. 若它的左子树不为空,则左子树上所有节点的值均小于它的根节点的值。

  2. 若它的右子树不为空,则右子树上所有节点的值均大于它的根节点的值。

  3. 它的左、右子树也分别为二叉排序树。

画个图方便理解:

第一张图是一个简单的排序二叉树,5<10<15,所以顺序应该是 10 作为根节点,小于10的在左子树,大于10的在右子树。

如果现在又要加入一个节点呢?比如说:6,它应该放在哪里?因为 6 比 10 小,所以 6 应该放在 10 的左子树,又因为 6 比 5 大所以放在 5 的右子树。如图:

那么如果是 16 呢?16 先和 10 进行比较,16>10 进入10的右子树,16 再和 15 比较,16>15,进入 15 的右子树。如图:

现在如果给一个数组:**int array[6] = { 6,3,12,5,20,1 },**如何构建一个二叉排序树呢?

我们可以回想我们在构建树的时候代码思路:

cpp 复制代码
void CreatTree(TreeNode** T, int data) {
    
	if (data == "#") {
        孩子置空停止递归
        *T=NULL;
	}
	else {
            *T = (TreeNode*)malloc(sizeof(TreeNode));
		    (*T)->val = data;
		    (*T)->lchild = NULL;
		    (*T)->rchild = NULL;
            递归左子树,递归右子树
			Creat_BST(&((*T)->rchild), data);
			Creat_BST(&((*T)->lchild), data);
		}
	}
}

我这里写的不完整,主要看 else部分,创建节点,然后递归创建左右孩子节点,那么二叉排序树的特殊条件就是小的放在左孩子,大的放在右孩子,只不过加了个判断条件,而不是左右孩子都创建。

所以我们可以这样创建排序二叉树:

cpp 复制代码
void Creat_BST(TreeNode** T, int data) {
	if (*T == NULL) {
		*T = (TreeNode*)malloc(sizeof(TreeNode));
		(*T)->val = data;
		(*T)->lchild = NULL;
		(*T)->rchild = NULL;
	}
	else {
		if (data> (*T)->val){
			Creat_BST(&((*T)->rchild), data);
		}
		else {
			Creat_BST(&((*T)->lchild), data);
		}
	}
}

我的函数是只创建一个二叉排序树的节点,首先传进的 *T 是空,说明树为空,所以创建节点。第二个数据进入时,因为根不为空进入 else,如果小于根节点数据,则进入左孩子遍历(因为左孩子在在创建根节点时置空,所以这时就会创建左孩子存放第二个数据。),如果大于根节点数据,则进入右孩子遍历。

下面是用循环创建二叉排序树的主函数代码:

cpp 复制代码
int main() {
	TreeNode* T = NULL;
	int array[6] = { 6,3,12,5,20,1 };
	for (int i = 0; i < 6; i++) {
		Creat_BST(&T, array[i]);
	}
	return 0;
}

最后写一个寻找树中是否有目标值的函数,逻辑很相似:

cpp 复制代码
TreeNode* BST_search(TreeNode* T, int val) {
	if (T) {
		if (T->val == val) {
			return T;
		}
		else
		{
			if (val < T->val) {
				return BST_search(T->lchild, val);
			}
			if (val > T->val) {
				return BST_search(T->rchild, val);
			}
		}
	}
	else {
		return NULL;
	}
}

如果相等就返回地址,如果小于树节点的值,利用二叉排序树的性质,就一定在左子树,继而进入左子树递归,如果大于树节点的值,就一定在右子树,进入右子树进行递归。如果都没有,最后一定会找到末端节点的左右孩子,末端节点的左右孩子是空,所以进入最后一个 else 返回NULL。

这就是文章的全部内容了,希望对你有所帮助,如有错误欢迎评论。

相关推荐
naruto_lnq14 小时前
分布式系统安全通信
开发语言·c++·算法
Jasmine_llq14 小时前
《P3157 [CQOI2011] 动态逆序对》
算法·cdq 分治·动态问题静态化+双向偏序统计·树状数组(高效统计元素大小关系·排序算法(预处理偏序和时间戳)·前缀和(合并单个贡献为总逆序对·动态问题静态化
学嵌入式的小杨同学15 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
爱吃rabbit的mq15 小时前
第09章:随机森林:集成学习的威力
算法·随机森林·集成学习
精彩极了吧15 小时前
C语言基本语法-自定义类型:结构体&联合体&枚举
c语言·开发语言·枚举·结构体·内存对齐·位段·联合
(❁´◡`❁)Jimmy(❁´◡`❁)16 小时前
Exgcd 学习笔记
笔记·学习·算法
YYuCChi16 小时前
代码随想录算法训练营第三十七天 | 52.携带研究材料(卡码网)、518.零钱兑换||、377.组合总和IV、57.爬楼梯(卡码网)
算法·动态规划
不能隔夜的咖喱17 小时前
牛客网刷题(2)
java·开发语言·算法
VT.馒头17 小时前
【力扣】2721. 并行执行异步函数
前端·javascript·算法·leetcode·typescript
进击的小头17 小时前
实战案例:51单片机低功耗场景下的简易滤波实现
c语言·单片机·算法·51单片机