数据结构 | 二叉树的各种遍历

数据结构 | 二叉树的各种遍历

文章目录

  • 数据结构 | 二叉树的各种遍历
    • 创建节点 && 创建树
    • 二叉树的前中后序遍历
    • 二叉树节点个数
    • 二叉树叶子节点个数
    • 二叉树第k层节点个数
    • 二叉树查找值为x的节点
    • 二叉树求树的高度
    • 二叉树的层序遍历
    • 判断二叉树是否是完全二叉树

我们本章来实现二叉树的这些功能

Tree.h

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int BTDataType;

typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

//创建节点
BTNode* BuyTreeNode(int x);
//创建树
BTNode* CreateTree();
// 二叉树销毁
void BinaryTreeDestory(BTNode* root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
// 求树的高度
int TreeHeight(BTNode* root);
  • 我们先来几个简单的

创建节点 && 创建树

  • 直接手动个创建即可,很简单~~
//创建节点
BTNode* BuyTreeNode(int x)
{
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	if (root == NULL)
	{
		perror("malloc fail\n");
		exit(-1);
	}
	root->data = x;
	root->left = NULL;
	root->right = NULL;
	return root;
}
//创建树
BTNode* CreateTree()
{
	BTNode* node1 = BuyTreeNode(1);
	BTNode* node2 = BuyTreeNode(2);
	BTNode* node3 = BuyTreeNode(3);
	BTNode* node4 = BuyTreeNode(4);
	BTNode* node5 = BuyTreeNode(5);
	BTNode* node6 = BuyTreeNode(6);
	BTNode* node7 = BuyTreeNode(7);

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;
	node5->right = node7;

	return node1;
}

二叉树的前中后序遍历

  • 这里也是很简单,也可以看做下图这样遍历,或者画一下递归展开图

在这里插入图片描述

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	printf("%d ", root->data);
	BinaryTreePrevOrder(root->left);
	BinaryTreePrevOrder(root->right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	BinaryTreeInOrder(root->left);
	printf("%d ", root->data);
	BinaryTreeInOrder(root->right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	BinaryTreePostOrder(root->left);
	BinaryTreePostOrder(root->right);
	printf("%d ", root->data);
}

二叉树节点个数

  • 我们这里看一下递归展开图

在这里插入图片描述

int BinaryTreeSize(BTNode* root)
{
	return root == NULL ? 0 : BinaryTreeSize(root->left)
							+ BinaryTreeSize(root->right);
}

二叉树叶子节点个数

  • 为空就返回0
  • 不是空,是叶子,返回1
  • 不是空,也不是叶子,就递归左子树和右子树
int BinaryTreeLeafSize(BTNode* root)
{
	// 为空返回0
	if (root == NULL)
		return 0;
	//不是空,是叶子 返回1
	if (root->left == NULL && root->right == NULL)
		return 1;
	// 不是空 也不是叶子  分治=左右子树叶子之和
	return BinaryTreeLeafSize(root->left)
	   	 + BinaryTreeLeafSize(root->right);
}

二叉树第k层节点个数

  • k是1的时候就是一层,就返回1
  • 递归左子树加右子树,每次递归k-1
int BinaryTreeLevelKSize(BTNode* root, int k)
{
	if (root == NULL)
		return NULL;

	if (k == 1)
		return 1;

	//递归左子树加右子树,每次递归k-1
	return BinaryTreeLevelKSize(root->left, k - 1)
	 	 + BinaryTreeLevelKSize(root->right, k - 1);
}

二叉树查找值为x的节点

  • 先看根节点是不是要找的
  • 然后递归左子树和右子树
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
		return NULL;
	//根
	if (root->data == x)
		return root;

	//左子树
	BTNode* ret1 = BinaryTreeFind(root->left, x);
	if (ret1)
		return ret1;
	
	//右子树
	BTNode* ret2 = BinaryTreeFind(root->right, x);
	if (ret2)
		return ret2;

	return NULL;
}

二叉树求树的高度

  • 遍历左子树和右子树(每次遍历都要保存值)
  • 返回最高的那个子树然后加1(根)
int TreeHeight(BTNode* root)
{
	if (root == NULL)
		return NULL;

	//遍历左子树和右子树
	int left = TreeHeight(root->left);
	int right = TreeHeight(root->right);

	//返回最高的那个子树然后加1(根)
	return left > right ? left + 1 : right + 1;
}

二叉树的层序遍历

  • 这里的这个层序遍历就需要用到我们之前学过的队列了~~
  • 这里用法是入根(root),然后带孩子节点
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	//先入根
	if (root)
		QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		//取队头的数据
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		//打印数据
		printf("%d ", front->data);

		//将左子树和右子树代入进队列
		if (front->left)
			QueuePush(&q, front->left);

		if (front->right)
			QueuePush(&q, front->right);
	}
	printf("\n");

	QueueDestroy(&q);
}
  • 那如果要一层一层的打印,代码改怎么改呢?
  • 一层一层的带,一层一层的出
// 层序遍历(一层一层的打印)
void _BinaryTreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	//先入根
	if (root)
		QueuePush(&q, root);

	int leveSize = 1;
	while (!QueueEmpty(&q))
	{
		while (leveSize--)
		{
			//取队头的数据
			BTNode* front = QueueFront(&q);
			QueuePop(&q);

			printf("%d ", front->data);

			if (front->left)
				QueuePush(&q, front->left);

			if (front->right)
				QueuePush(&q, front->right);
		}
		printf("\n");
		leveSize = QueueSize(&q);
	}
	QueueDestroy(&q);
}

判断二叉树是否是完全二叉树

  • 和上面的代码基本一样,取数据如果遇到空就跳出
  • 如果前面遇到空以后,后面还有非空就不是完全二叉树
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	//先入根
	if (root)
		QueuePush(&q, root);

	while (!QueueEmpty(&q))
	{
		// 取队头的数据
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		//等于空了就跳出,然后检查后面还有节点没有
		if (front == NULL)
			break;

		// 将左子树和右子树代入进队列
		QueuePush(&q, front->left);
		QueuePush(&q, front->right);

	}

	// 前面遇到空以后,后面还有非空就不是完全二叉树
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		// 如果是不是空就 return false;
		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}

	QueueDestroy(&q);
	return true;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

易点易动设备管理系统--提升设备能耗管理效率的工具

在当今的节能环保意识日益增强的社会背景下&#xff0c;设备能耗管理成为了市场推广人员关注的焦点之一。为了帮助市场推广人员提升设备能耗管理效率&#xff0c;易点易动设备管理系统应运而生。本文将详细介绍易点易动设备管理系统的功能和优势&#xff0c;以及如何借助该系统…

Python 对中文名称逐字按字母表进行排序并输出

使用场景 代码适用于需要对中文名称进行排序并规范化输出的情景&#xff0c;具体为处理一个包含中文姓名的文本文件&#xff0c;按姓名的拼音首字母进行排序&#xff0c;并以规范的格式输出。 排序规则&#xff1a; 将名称按照姓氏首字母A-Z的次序&#xff0c;进行排序&#x…

微服务实战系列之J2Cache

前言 经过近几天陆续发布Cache系列博文&#xff0c;博主已对业界主流的缓存工具进行了基本介绍&#xff0c;当然也提到了一些基本技巧。相信各位盆友看见这么多Cache工具后&#xff0c;在选型上一定存在某些偏爱: A同学说&#xff1a;不管业务千变万化&#xff0c;我对Redis的…

STM32-新建工程(标准库)

目录 STM32F10x新建工程&#xff08;标准库&#xff09; 移植文件夹 新建工程 添加启动文件和必需文件 在工程中加载新添加的文件 在工程中添加文件路径 在工程中添加main函数 添加lib库 添加必需文件 添加宏定义 点亮LED&#xff08;标准库&#xff09; STM32F10x新…

小型洗衣机什么牌子好又便宜?小型洗衣机全自动

随着科技的快速发展&#xff0c;现在的人们越来越注重自己的卫生问题&#xff0c;不仅在吃上面会注重卫生问题&#xff0c;在用的上面也会更加严格要求&#xff0c;而衣服做为我们最贴身的东西&#xff0c;我们对它的要求也会更加高&#xff0c;所以最近这几年较火爆的无疑是内…

【银行测试】第三方支付功能测试点+贷款常问面试题(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、第三方支付功能…

k8s 安装 Longhorn

Longhorn 的 helm 模板官网地址&#xff1a;Longhorn 加入仓库 helm repo add longhorn https://charts.longhorn.iohelm repo update开始部署 helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace --version 1.5.3检查pod运行状态是…

12V转5V3A同步降压芯片WT6043

12V转5V3A同步降压芯片WT6043 WT6043是一款具有内部功率 MOSFET的同步整流降压转换器&#xff0c;它的工作输入范围为4V-18V&#xff0c;提供3A的连续输出电流&#xff0c;具有出色的负载和线路调节能力。WT6043采用SOT23-6封装&#xff0c;是一款高度集成的降压转换器&#x…

基于SSM框架的在线投票系统

基于SSM框架的在线投票系统 文章目录 基于SSM框架的在线投票系统 一.引言二.系统设计三.技术架构四.功能实现五.界面展示六.源码获取 一.引言 随着科技的不断发展&#xff0c;人们对于民主参与的需求也越来越高。在线投票系统应运而生&#xff0c;为人们提供了便捷、高效的投票…

使用dcmtk读取dicom Tag信息

dicom文件由导言、前缀和多个数据元素构成&#xff0c;一个.dcm文件可以形象的看成一本字典&#xff0c;而每个字都由特定的Tag作为检索。 Tag的值中存放有该图对应患者的姓名、年龄、性别等&#xff0c;还包括拍摄医院的名称、操作技师的名字等&#xff0c;以及每一张图的像素…

Vue学习笔记-<router-link>的replace的属性

router-link的replace属性 作用&#xff1a;控制路由跳转时操作浏览器历史记录的模式 浏览器的历史记录有两种写入方式&#xff1a;push和replace&#xff0c;其中push是追加历史记录&#xff08;将浏览的url请求入栈&#xff09;&#xff0c;replace则是替换当前记录&#x…

Python sorted函数及用法以及如何用json模块存储数据

Python sorted函数及用法 sorted() 函数与 reversed() 函数类似&#xff0c;该函数接收一个可迭代对象作为参数&#xff0c;返回一个对元素排序的列表。 在交互式解释器中测试该函数&#xff0c;可以看到如下运行过程&#xff1a; >>> a [20, 30, -1.2, 3.5, 90, 3.…

Vulnhub-DC-4 靶机复现完整过程

一、搭建环境 1.工具 kali:攻击机 IP地址&#xff1a;192.168.200.4 DC-4&#xff1a;靶机 IP地址&#xff1a;暂时未知 2.注意 这里搭建环境两台机器应该选用同类的网络连接方式&#xff1a;这里两台的连接方式为模式 二、信息收集 1.主机发现 找寻同网段下存活的主机&…

维修上门预约小程序源码系统 附带完整的搭建教程

随着互联网的普及和科技的不断发展&#xff0c;人们对维修服务的需求也在不断增加。为了满足这一需求&#xff0c;维修上门预约小程序应运而生。 以下是部分代码示例&#xff1a; 系统特色功能一览&#xff1a; 1.用户注册登录 用户可以通过手机号或微信号注册账号&#xff0…

【C++11】线程库/异常

一&#xff1a;线程库 1.1:线程库(thread) 1.1.1&#xff1a;为什么要有线程库 1.1.2&#xff1a;thread库中的成员函数 1.1.3&#xff1a;线程函数参数 1.2:互斥锁(mutex) 1.2.1&#xff1a;为什么要有互斥锁 1.2.2&#xff1a;C11中的互斥锁 1.3:原子操作(atomic) 1.4:条件变…

Web开发-问题-前后端交互数据不一致

0x01 问题描述 所用的技术&#xff1a;VueSpring Boot后端传给前端数据&#xff1a; [Student(studentId1, personorg.fatmansoft.teach.models.Person4abe6020, major软件工程, className一班, grade一年级), Student(studentId2, personorg.fatmansoft.teach.models.Person…

如何利用CentOS7+docker+jenkins+gitee部署springboot+vue前后端项目(保姆教程)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

纯CSS实现计时器

跟b站 小k师兄学习一手CSS的计时器 1. 基本样式 注意&#xff0c;这里开始按钮使用伪类进行标签名字的设定&#xff0c;因为开始按钮点击以后有一个暂停的功能&#xff0c;就先不写死了。 <!DOCTYPE html> <html lang"en"><head><meta charset&…

2024年CSC国际区域问题研究及外语高层次人才培养项目介绍

国家留学基金委&#xff08;CSC&#xff09;公布了2024年国际区域问题研究及外语高层次人才培养项目&#xff0c;申报时间均为3月中下旬。为帮助关注者了解项目申报情况&#xff0c;知识人网小编特整理本文。 近日&#xff0c;国家留学基金委&#xff08;CSC&#xff09;公布了…

在Linux上优化HTTP服务器的性能

在Linux上优化HTTP服务器的性能是一个涉及多个方面的任务&#xff0c;包括服务器硬件、网络设置、软件配置和内容优化。以下是一些关键的优化建议&#xff1a; 选择合适的HTTP服务器软件 Linux上有多种HTTP服务器软件&#xff0c;如Apache、Nginx、Lighttpd等。选择适合您需求…