【数据结构】二叉树详解(3)

⭐️ 前言

往期链接:【数据结构】二叉树详解(1)
在第一篇二叉树文章中,我们探讨了二叉树的链式结构定义与实现。二叉的遍历包含( 前序/中序/后序遍历 )及代码实现和递归流程图的详细讲解。还有一些二叉树的其他接口定义与实现,包含 BinaryTreeSize ( 计算二叉树结点的数量 )、BinaryTreeLeafSize( 计算二叉树叶子结点的数量 )、BinaryTreeKLevelSize( 计算二叉树第 k k k 层节点的个数 )、BinaryTreeFind( 二叉树中查找某个元素 )。
在这里插入图片描述


在这里插入图片描述


往期链接:【数据结构】二叉树详解(2)
在第二篇二叉树文章中,又是在第一篇的基础上又补充了一个接口的实现BinaryTreeDepth( 计算二叉树的深度 )
在这里插入图片描述


本期我们在前两篇的基础上,继续补充一些关于二叉树的其他接口实现。

⭐️ 二叉树的其他接口

// 二叉树的销毁
void BinaryTreeDestroy(BinaryTreeNode* root);
// 二叉树层序遍历(需要队列)
void LevelOrder(BinaryTreeNode* root);
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BinaryTreeNode* root);

BinaryTreeDestroy 实现:

// 二叉树的销毁
// 后序遍历最优
void BinaryTreeDestroy(BinaryTreeNode* root) {
    
    
	if (root == NULL) {
    
    
		return;
	}

	BinaryTreeDestroy(root->left);
	BinaryTreeDestroy(root->right);

	free(root);
}

解析: 二叉树的销毁采用后序遍历是最优的,先销毁左子树在销毁右子树最后销毁根节点。


LevelOrder 实现:

// 二叉树层序遍历(需要队列)
void LevelOrder(BinaryTreeNode* root) {
    
    
	Queue q;
	QueueInit(&q);

	// 把根节点入队列
	if (root) {
    
    
		QueuePush(&q , root);
	}

	// 依次遍历队列
	while (!QueueIsEmpty(&q)) {
    
    
		// 取出队头节点
		QueueDataType front = QueueFront(&q);
		// 出队头节点
		QueuePop(&q);
		// 打印
		printf("%d " , front->value);
		// 左节点不为空 入队列
		if (front->left) {
    
    
			QueuePush(&q , front->left);
		}
		// 右节点不为空 入队列
		if (front->right) {
    
    
			QueuePush(&q , front->right);
		}
	}

	QueueDestroy(&q);
}

解析: 层序遍历需要依靠队列来实现,思路是把根节点入队列,循环判断队列不为空,若队列不为空则把当前队头节点取出并把队头节点的左右孩子依次入队,再删除队头数据。队列的代码以及实现:往期文章:【数据结构】栈和队列实现

在这里插入图片描述


BinaryTreeComplete 实现:

// 判断二叉树是否是完全二叉树
// 用到层序遍历的思想
bool BinaryTreeComplete(BinaryTreeNode* root) {
    
    
	Queue q;
	QueueInit(&q);
	// 根节点不为空入队列
	if (root) {
    
    
		QueuePush(&q , root);
	}
	// 检查队列
	while (!QueueIsEmpty(&q)) {
    
    
		// 取出队头数据
		QueueDataType front = QueueFront(&q);
		// 删除队头数据
		QueuePop(&q);
		// 如果当前对头节点存在则让当前节点左右节点入队
		if (front) {
    
    
			QueuePush(&q , front->left);
			QueuePush(&q, front->right);
		}
		else {
    
    
			break;
		}
	}
	// 继续检查队列
	// 如果全为空 则是完全二叉树
	// 如果有一个不为空 则不是完全二叉树
	while (!QueueIsEmpty(&q)) {
    
    
		QueueDataType front = QueueFront(&q);
		QueuePop(&q);
		if (front) {
    
    
			QueueDestroy(&q);
			return false;
		}
	}

	QueueDestroy(&q);
	return true;
}

解析: 判断当前二叉树是否是完全二叉树,使用到了层序遍历的思想。层序遍历是把根节点入队列,再依次检查队列是否为空,若不为空则取出队头数据,再判断子孩子是否存在,当把当前根节点出队列时,再将子孩子节点入队列,直至队列为空。完全二叉树满足 k − 1 k - 1 k1 层节点是满的,最后一层节点最少只有一个,最多也是满的(这种情况也叫做满二叉树)。当然完全二叉树最后一层节点之间还需要是连续的。
在这里插入图片描述

扫描二维码关注公众号,回复: 15784592 查看本文章

从上图可知:如果不是完全二叉树,当遇到第一个 NULL 时队列后面还有非空节点则就不是完全二叉树。因为完全二叉树的层序遍历是使存在的节点都在左侧 NULL节点都在右侧。所以我们在层序遍历的基础上把空节点也依次入队, 当碰到第一个 NULL 节点结束循环,再依次检查队列剩余的节点中是否有不为 NULL 的节点,若都为 NULL 则当前二叉树就是完全二叉树,若有非 NULL 节点,则当前就不是完全二叉树。

猜你喜欢

转载自blog.csdn.net/cccyi7/article/details/131838394