一步一步写算法(之排序二叉树)[通俗易懂]

一步一步写算法(之排序二叉树)[通俗易懂]【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing@163.com】   前面我们讲过双向链表的数据结构。每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起。然而今天

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

    前面我们讲过双向链表的数据结构。每一个循环节点有两个指针,一个指向前面一个节点,一个指向后继节点,这样所有的节点像一颗颗珍珠一样被一根线穿在了一起。然而今天我们讨论的数据结构却有一点不同,它有三个节点。它是这样定义的:

typedef struct _TREE_NODE
{
	int data;
	struct _TREE_NODE* parent;
	struct _TREE_NODE* left_child;
	struct _TREE_NODE* right_child;
}TREE_NODE;

    根据上面的数据结构,我们看到每一个数据节点都有三个指针,分别是:指向父母的指针,指向左孩子的指针,指向右孩子的指针。每一个节点都是通过指针相互连接的。相连指针的关系都是父子关系。那么排序二叉树又是什么意思呢?其实很简单,只要在二叉树的基本定义上增加两个基本条件就可以了:(1)所有左子树的节点数值都小于此节点的数值;(2)所有右节点的数值都大于此节点的数值。

    既然看到了节点的定义,那么我们并可以得到,只要按照一定的顺序遍历,可以把二叉树中的节点按照某一个顺序打印出来。那么,节点的创建、查找、遍历是怎么进行的呢,二叉树的高度应该怎么计算呢?我们一一道来。

    1)创建二叉树节点

TREE_NODE* create_tree_node(int data)
{
	TREE_NODE* pTreeNode = NULL;
	pTreeNode = (TREE_NODE*)malloc(sizeof(TREE_NODE));
	assert(NULL != pTreeNode);

	memset(pTreeNode, 0, sizeof(TREE_NODE));
	pTreeNode->data = data;
	return pTreeNode;
}

    分析:我们看到,二叉树节点的创建和我们看到的链表节点、堆栈节点创建没有什么本质的区别。首先需要为节点创建内存,然后对内存进行初始化处理。最后将输入参数data输入到tree_node当中即可。

    2)数据的查找

TREE_NODE* find_data_in_tree_node(const TREE_NODE* pTreeNode, int data)
{
	if(NULL == pTreeNode)
		return NULL;

	if(data == pTreeNode->data)
		return (TREE_NODE*)pTreeNode;
	else if(data < pTreeNode->data)
		return find_data_in_tree_node(pTreeNode->left_child, data);
	else
		return find_data_in_tree_node(pTreeNode->right_child, data);
}

    分析:我们的查找是按照递归迭代进行的。因为整个二叉树是一个排序二叉树,所以我们的数据只需要和每一个节点依次比较就可以了,如果数值比节点数据小,那么向左继续遍历;反之向右继续遍历。如果遍历下去遇到了NULL指针,只能说明当前的数据在二叉树中还不存在。

    3)数据统计

int count_node_number_in_tree(const TREE_NODE* pTreeNode)
{
	if(NULL == pTreeNode)
		return 0;

	return 1 + count_node_number_in_tree(pTreeNode->left_child)
		+ count_node_number_in_tree(pTreeNode->right_child);
}

    分析:和上面查找数据一样,统计的工作也比较简单。如果是节点指针,那么直接返回0即可,否则就需要分别统计左节点树的节点个数、右节点树的节点个数,这样所有的节点总数加起来就可以了。

    4)按照从小到大的顺序打印节点的数据

void print_all_node_data(const TREE_NODE* pTreeNode)
{
	if(pTreeNode){
		print_all_node_data(pTreeNode->left_child);
		printf("%d\n", pTreeNode->data);
		print_all_node_data(pTreeNode->right_child);
	}
}

    分析:因为二叉树本身的特殊性,按顺序打印二叉树的函数本身也比较简单。首先打印左子树的节点,然后打印本节点的数值,最后打印右子树节点的数值,这样所有节点的数值就都可以打印出来了。

    5)统计树的高度

int calculate_height_of_tree(const TREE_NODE* pTreeNode)
{
	int left, right;
	if(NULL == pTreeNode)
		return 0;

	left = calculate_height_of_tree(pTreeNode->left_child);
	right = calculate_height_of_tree(pTreeNode->right_child);
	return (left > right) ? (left + 1) : (right + 1);
}

    分析:树的高度其实是指所有叶子节点中,从根节点到叶子节点的最大高度可以达到多少。当然,程序中表示得已经很明白了,如果节点为空,那么很遗憾,节点的高度为0;反之如果左子树的高度大于右子树的高度,那么整个二叉树的节点高度就是左子树的高度加上1;如果右子树的高度大于左子树的高度,那么整个二叉树的高度就是右子树的高度加上1。计算树的高度在我们设计平衡二叉树的时候非常有用,特别是测试的时候,希望大家多多理解,熟练掌握。

总结:

    1)二叉树是所有树的基础,后续的平衡二叉树、线性二叉树、红黑树、复合二叉树、b树、b+树都以此为基础,希望大家好好学习;

    2)二叉树很多的操作是和堆栈紧密联系在一起的,如果大家暂时理解不了递归,可以用循环或者堆栈代替;

    3)实践出真知,大家可以自己对排序二叉树的代码多多练习。不瞒大家说,我个人写平衡二叉树不下20多遍,即使这样也不能保证每次都正确;即使这样,我每次写代码的都有不同的感觉。

【预告: 下面一篇博客介绍平衡二叉树的插入和删除】


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/160036.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月25日 下午6:16
下一篇 2022年7月25日 下午6:16


相关推荐

  • 周刊第17期: 如何构建智能体(Agent)

    周刊第17期: 如何构建智能体(Agent)

    2026年3月16日
    2
  • 国产FPGA大盘点

    国产FPGA大盘点无论是采用更先进制程节点 还是创新产品的研发 生产等都要花费大量的资源跟金钱 不能回本的风险很大 产业链上与国外差距依然非常大 包括在技术积累 专利数量 人才储备 制程工艺 逻辑规模 性能指标 生产和供应链能力 研发投入 生态和行业整合能力等多个方面 角度来看 硬件产业链中目前自主可控程度较低 尤其在高端半导体设备和材料领域 未来产业链上下游国产替代进程的推进也将助力国产 因其可根据不同场景重新编程的特点 有灵活性高 开发周期短 小批量成本低的优势 能更快的应用市场需求变化

    2026年3月26日
    1
  • origin绘图过程的一些经验

    origin绘图过程的一些经验1.在“帮助->learningcenter”选项卡中可以查找教程及下载APP2.如果不小心将工具栏拖到了屏幕中间或者不小心删除了某个工具栏,可以在“查看->工具栏->重新初始化”里边进行重置工具栏。3.图像数字化(Digitize从图上扣点):工具栏上的位置在“查看(V)”的V字右下边,点击之后选择需要扣点的图片位置,即可打开图片进行扣点或者扣线。需要旋转的可以点击“旋转图像”再点下边出现的微旋按钮将图片旋转,然后移动刚刚打开的图片上的四条线使其对齐坐标轴上下边界,输入坐标轴

    2022年5月31日
    110
  • VS中添加lib与dll

    VS中添加lib与dll参考与拓展阅读:https://blog.csdn.net/u012043391/article/details/54972127lib:1.附加包含目录—添加工程的头文件目录:项目->属性->配置属性->C/C++->常规->附加包含目录:加上头文件的存放目录;2.附加库目录—添加文件引用的lib静态库路径:项目->属…

    2022年7月26日
    10
  • 智谱AI发布GLM-5:代码能力对标Claude Opus,国产芯片加持

    智谱AI发布GLM-5:代码能力对标Claude Opus,国产芯片加持

    2026年3月12日
    1
  • 大数运算的算法设计和C++实现[通俗易懂]

    大数运算的算法设计和C++实现[通俗易懂]1、背景工作中遇到过需要进行极大数据的存储和运算的场景,当时使用Python解决了这个问题,在Python中,整数没有位数限制,使用起来很方便。但是当程序主体使用C/C++实现时,就比较麻烦。所以考

    2022年7月3日
    28

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号