IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【数据结构】链式二叉树 - 前中后层序遍历+基本操作 -> 正文阅读

[数据结构与算法]【数据结构】链式二叉树 - 前中后层序遍历+基本操作

二叉树 概念

二叉树要么是空树,要么是非空树,即由根结点、根结点的左子树和根结点的右子树组成。

在这里插入图片描述

可以看出二叉树是递归定义的,后序操作都是基于这个结论实现的。

前序(先序)遍历

按照 根结点-左子树-右子树 的顺序遍历树。

void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	printf("%c ", root->data);
	PreOrder(root->left);
	PreOrder(root->right);
}

在这里插入图片描述
对于上图二叉树,前序遍历的结果是
(下一行是程序运行结果)
在这里插入图片描述

中序遍历

按照 左子树-根结点-右子树 的顺序遍历树。

void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	InOrder(root->left);
	printf("%c ", root->data);
	InOrder(root->right);
}

在这里插入图片描述

后序遍历

按照 左子树-右子树-根结点 的顺序遍历树。

void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("NULL ");
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%c ", root->data);
}

在这里插入图片描述

层序遍历

借助队列实现层序遍历。
1、空树:直接返回
2、树不为空时,把根结点入队列。每次结点出队列,就把这个结点的左右孩子带进队列中。

// 层序遍历
void BinaryTreeLevelOrder(BTNode* root)
{
	// 使用队列
	// 树空,直接返回
	// 树不为空,根结点入队列
	// 每次结点出队列,把左右孩子带进队列里
	if (root == NULL)
	{
		return NULL;
	}

	// 非空树
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		// 保存队头元素
		QDataType front = QueueFront(&q);
		// 出队头
		QueuePop(&q);
		printf("%c ", front->data);

		// 孩子结点入队
		if (front->left)
		{
			QueuePush(&q, front->left);
		}

		if (front->right)
		{
			QueuePush(&q, front->right);
		}
	}

	QueueDestroy(&q);
}

在这里插入图片描述

二叉树结点个数

二叉树结点个数 = 根结点个数+左右子树结点总数

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

二叉树叶子节点个数

叶子节点左右孩子都是NULL。
二叉树叶子节点 = 左子树叶子节点 + 右子树叶子节点

int BinaryTreeLeafSize(BTNode* root)
{
	// 左子树叶子节点+右子树叶子结点
	if (root == NULL)
	{
		return 0;
	}

	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}

	return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

二叉树第k层结点个数

二叉树第k层结点个数等于左右子树第k-1层结点个数。

int BinaryTreeLevelKSize(BTNode* root, int k)
{
	assert(k >= 1);
	if (root == NULL)
	{
		return 0;
	}

	if (k == 1)
	{
		return 1;
	}

	// root不为空,k不等于1,第k层存在在子树中
	// 统计左右子树第k-1层结点个数
	return BinaryTreeLevelKSize(root->left, k - 1) +
		BinaryTreeLevelKSize(root->right, k - 1);
}

二叉树深度/高度

二叉树深度/高度是左右子树最大高度加一。

int BinaryTreeDepth(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	// 非空树,左右子树最大高度+1
	int leftDepth = BinaryTreeDepth(root->left);
	int rightDepth = BinaryTreeDepth(root->right);

	return fmax(leftDepth, rightDepth) + 1;
	// return leftDepth > rightDepth ? leftDepth + 1 : rightDepth + 1;
}

二叉树查找值为x的节点

先判断根结点是不是值为x的结点,如果不是,去左右子树中查找。

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	// 根结点判断,不是,进入左右子树查找
	if (root == NULL)
		return NULL;

	if (root->data == x)
		return root;

	BTNode* leftret = BinaryTreeFind(root->left, x);
	if (leftret)
		return leftret;

	BTNode* rightret = BinaryTreeFind(root->right, x);
	if (rightret)
		return rightret;

	return NULL;
}

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

首先要分析得出完全二叉树和一般二叉树的区别。本题基于层序遍历的知识更好理解。

在这里插入图片描述
在这里插入图片描述

可以得出,完全二叉树在找到NULL时,后面没有元素。
一般二叉树在找到NULL后,后面还会有元素。

bool BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	// 根结点入队列
	QueuePush(&q, root);
	// 队列非空
	while (!QueueEmpty(&q))
	{
		// 获得队顶元素
		QDataType tmp = QueueFront(&q);
		// 队顶出队
		QueuePop(&q);
		// 如果tmp是NULL,跳出进行判断
		if (tmp == NULL)
		{
			break;
		}
		else
		{
			// tmp 非空
			// 带入孩子结点
			QueuePush(&q, tmp->left);
			QueuePush(&q, tmp->right);
		}
	}

	// 遇到NULL,检查队列剩下的结点
	// 全是NULL,完全二叉树
	// 存在非空,不是完全二叉树
	while (!QueueEmpty(&q))
	{
		// 依次取队头元素进行判断
		QDataType front = QueueFront(&q);
		QueuePop(&q);

		if (front)
		{
			QueueDestroy(&q);
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}

二叉树销毁

后序遍历进行销毁。使用前序遍历销毁还要保留root结点,用后序遍历更加遍历。

void BinaryTreeDestory(BTNode* root)
{
	if (root == NULL)
		return;

	// 后序销毁
	BinaryTreeDestory(root->left);
	BinaryTreeDestory(root->right);
	free(root);
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-11-18 11:25:30  更:2021-11-18 11:25:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:43:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码