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 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 初阶数据结构之二叉树 -> 正文阅读

[数据结构与算法]初阶数据结构之二叉树


前言

在前一篇数据结构博文中,我们已经了解了基本的二叉树只是,今天就来详细讲解链式二叉树的遍历,以及各方面的操作。
链式二叉树的学习能很好锻炼我们递归思想以及分治思想。

链式二叉树的定义

怎么定义链式二叉树呢?
我们用一个结构体来表示二叉树的一个节点,其中有一个变量存放二叉树节点的值,再来两个此结构体指针存放它的左右节点的地址。代码如下:

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

链式二叉树的遍历

前序遍历

前序遍历的口诀就是“根左右”,它的思想就是先访问树的根,再访问数的左孩子,最后访问树的右节点。例如如图这个二叉树:

在这里插入图片描述

遍历的过程:
我们是先访问它的根也就是4,然后再访问它的左孩子2,左孩子2从新作为根后先从自己2开始再访问2的左孩子1,左孩子1作为根,先访问自己1然后访问左孩子为NULL就返回到1,然后再访问1的右孩子为NULL返回到1,依次类推。就能得到遍历的顺序为:

4, 2, 1, 3, 6, 5
代码:

void PrevOrder(BTNode* root)
{
	if(root == NULL)
	{
		printf("NULL");
		return;
	}
	printf("%d ",root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

中序遍历

中序遍历和前序遍历类似只是先遍历数的左子树然后遍历根最后遍历右子树,口诀就是左根右。代码如下

void InOrder(BTNode* root)
{
	if(root == NULL)
	{
		printf("NULL");
		return;
	}
	InOrder(root->left);
	printf("%d ",root->data);
	InOrder(root->right);
}

后序遍历

后序遍历是先遍历树的左子树然后是右子树,最后是根,口诀就是左右根。代码如下:

void PostOrder(BTNode* root)
{
	if(root == NULL)
	{
		printf("NULL");
		return;
	}
	PostOrder(root->left);
	PostOrder(root->right);
	printf("%d ",root->data);
}

层序遍历

层序遍历就是从第一层的第一个节点然后到第二层一次每层从左到右遍历。
在这里插入图片描述
以这个树为例,他的层序遍历结果就是:
4 2 6 1 3 5
那要怎么实现这个代码呢?
这里我们就要借助一种数据结构队列了。
我们的方法是从根节点开始,先把根节点入队,然后遍历一个节点就把它的左子树入队然后再把他的右子树入队,NULL不入队,直到队列为空为止。代码如下:

void LevelOrder(BTNode* root)
{
	if(root == NULL)
	{
		return;
	}
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while(!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		printf("%d ",front->data);
		if(front->left != NULL)
		{
			QueuePush(&q,root->left);
		}
		if(front->right!= NULL)
		{
			QueuePush(&q,root->right);
		}
	}
	QueueDestroy(&q);
}

求二叉树的节点个数

求节点个数直接分治就行了
如果父亲节点不为空加一为空加0;
代码如下:

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

求二叉树的叶子节点个数

首先我们的得知道怎么去判断叶子节点:
左右子树都为空的节点就是叶子节点。所以按照这个性质我们就可以判断了,代码如下:

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

求二叉树第K层的节点个数

思想就是:如果当前节点是第k层就加一,如果不是,就递归到下一层让k - 1.

int BinTreeLevelKSize(BTNode* root, int k)
{
	if(root == NULL)
	{
		return 0;
	}
	if(k == 1)
	{
		return 1;
	}
	return BinTreeLevelKSize(root->left, k-1) + BinTreeLevelKSize(root->right, k-1);
}

求二叉树的最大深度

将这个问题简化就是把求左右子树较大的深度然后加1.因为根节点本身也是占用一个深度的。
代码如下:

int BinTreeDepth(BTNode* root)
{
	if(root == NULL)
	{
		return 0;
	}
	int leftDepth = BinTreeDepth(root->left);
	int rightDepth = BinTreeDepth(root->right);
	return leftDepth > rightDepth ? leftDepth + 1 : rigthDepth + 1;
}

给一个数让给返回该节点

这个思想就是节点不是然后就从它的左子树和右子树找,直到找到为止。
代码如下:

BTNode* BinTreeNodeFint(BTNode* root, BTNDataType x)
{
	if(root == NULL)
	{
		return NULL;
	}
	if(root->data == x)
	{
		return root;
	}
	BTNode* Left = BinTreeNodeFint(root->left, x);
	if(Left != NULL)
	{
		return Left;
	}
	BTNode* Right = BinTreeNodeFint(root->right, x);
	if(Left != NULL)
	{
		return Right ;
	}
	return NULL;
}

判断该数是不是完全二叉树

完全二叉树的判断就是层序遍历过程中,直到数结束为止中间不能有空节点的产生,就是完全二叉树。
代码如下:

bool BinTreeComplete(BTNode* root)
{
	if(root == NULL)
	{
		return true;
	}
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while(!QueueEmpty(&q))
	{
		BTNode* Front = QueueFront(&q);
		QueuePop(&q);
		if(Front == NULL)
		{
			break;
		}
		else
		{
			QueuePush(&q, front->left);
			QueuePush(&q, front->right);
		}
	}
	while(!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&a);
		QueuePop(&q);
		if(front == NULL)
		{
			QueueDestroy(&q);
			return false;
		}
	}
	QueueDestroy(&q);
	return true;
}

二叉树的销毁

二叉树的销毁必须以后序遍历,不然先把根销毁了就找不到左右节点了
代码如下:

void BinTreeDestroy(BTNode* root)
{
	if(root == NULL)
	{
		return;
	}
	BinTreeDestroy(root->left);
	BinTreeDestroy(root->right);
	free(root);
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-25 10:49:54  更:2022-01-25 10:50:20 
 
开发: 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 19:26:00-

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