二叉树的相关题目及解析

🦍单值二叉树🦍

💗题目描述

如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。
只有给定的树是单值二叉树时,才返回 true;否则返回 false。
示例
在这里插入图片描述

💗题解

思路
1、当根节点为空时,返回true;
2、如果左孩子不为空且左孩子的值不等于根节点的值,返回false;
3、如果右孩子不为空且右孩子的值不等于根节点的值,返回false;
4、如果根节点和左右孩子 的值都相等,就进行递归转换成子问题,继续判断左右子树是否为单值二叉树;

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
bool isUnivalTree(struct TreeNode* root)

{
	//如果根节点为空就返回true
   if (root == NULL)

      return true;
	
	//如果左孩子与根节点的值不相等,返回false
   if (root->left != NULL && root->left->val != root->val)

      return false;

	//如果右孩子与根节点的值不相等,返回false
   if (root->right != NULL && root->right->val != root->val)

      return false;

	//如果根节点的值和左右孩子都相等,进行递归,继续判断左右孩子是不是单值二叉树
   return isUnivalTree(root->left) && isUnivalTree(root->right);

}

🦍二叉树的最大深度🦍

💗题目描述

给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
示例
在这里插入图片描述

💗题解

思路
1、如果我们知道了左子树和右子树的最大深度 lr,那么该二叉树的最大深度即为左子树和右子树的最大深度+1,即:max⁡(l,r) + 1;
2、而左子树和右子树的最大深度又可以以同样的方式进行计算;
3、在计算当前二叉树的最大深度时,可以先递归计算出其左子树和右子树的最大深度;
4、然后计算出当前二叉树的最大深度。递归在访问到空节点时退出。

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int maxDepth(struct TreeNode* root){
    if (root == NULL)
		return 0;
	else
	{
		if (root->left != NULL || root->right != NULL)
		{
			struct TreeNode* left = root->left;
			struct TreeNode* right = root->right;
			return (maxDepth(left) > maxDepth(right) ? maxDepth(left) : maxDepth(right)) + 1;
		}
		return 1;
	}
	
}

🦍检查两棵二叉树是否相同🦍

💗题目描述

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例
在这里插入图片描述

💗题解

思路
1、当两棵树的根节点都为空时,返回true;
2、当一棵树的根节点为空,另一棵树的根节点不为空时,返回false;
3、当两棵树的根节点不为空,且两棵树的根节点的值不相等,返回false;
4、前面的情况讨论完,最后转换成子问题进行递归求解,继续判断左右子树是否是相同的树。

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
	//一个为空一个不为空,返回false
    if (p == NULL && q != NULL)
	{
		return false;
	}
	//一个为空一个不为空,返回false
	if (q == NULL && p != NULL)
	{
		return false;
	}
	
	//根节点相等且为空,返回true
	if (q == NULL && p == NULL)
	{
		return true;
	}
	//同一位置的值不相等,返回false
	if (p->val != q->val)
	{
		return false;
	}
	//如果前面的条件都不成立,转化成子问题进行迭代求解,判断左右子树是否为相同的树
	return (isSameTree(p->left, q->left) && isSameTree(p->right,q->right));

}

🦍判断一棵二叉树是否为一棵二叉树的子树🦍

💗题目描述

给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
示例
在这里插入图片描述

💗题解

思路
😃 Subroot 和 root 的每一棵子树都比较一下,如果有相等,就是子树,关键是如何找到root的每一棵子树。
1、当 root 根节点为空时,返回false;
2、当 root 的根节点不为空时,需要判断 root 整棵树和二叉树 subRoot 是否为相同的树,如果是,返回true;
3、如果不是,转换成 root 左右子树判断与二叉树 subRoot 是否为相同的树。

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
	if (p == NULL && q != NULL)
	{
		return false;
	}
	if (q == NULL && p != NULL)
	{
		return false;
	}

	if (q == NULL && p == NULL)
	{
		return true;
	}

	if (p->val != q->val)
	{
		return false;
	}
	return (isSameTree(p->left, q->left) && isSameTree(p->right, q->right));
}


bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot)
{
	//如果root和subroot都为空,返回true
	if (root == NULL && subRoot == NULL)
	{
		return true;
	}
	//如果root为空,subroot不为空,返回false
	if (root == NULL && subRoot != NULL)
	{
		return false;
	}
	//root不为空,subroot为空,返回true,因为空节点可以看作任何一棵树的子树
	if (root != NULL && subRoot == NULL)
	{
		return true;
	}
	//root不为空同时root的值等于subroot的值,说明他们的根节点相同
	//需要判断他们是不是相同的树,如果是相同的树,就返回true
	if (root != NULL && root->val == subRoot->val)
	{
	  bool ret = isSameTree(root, subRoot);
	  if (ret == true)
	  {
		  return ret;
	  }
	}
	//如果不是相同的树,就判断根节点的左右子树,是否和subtree有相同的子树
	return (isSubtree(root->left, subRoot) || isSubtree(root->right, subRoot));

}

🦍判断一棵二叉树是否为对称二叉树🦍

💗题目描述

给你一个二叉树的根节点 root , 检查它是否轴对称。
示例
在这里插入图片描述

💗题解

思路
思路:
😃 如果二叉树是对称二叉树,那么根节点的左右子树呈轴对称,此时反转其中一个子树,如果翻转后的子树和另一棵子树相同,就说明这棵树是完全二叉树,如果反转后的子树与另一棵子树不相同,这棵树就不是对称二叉树。
1、写一个翻转二叉树的子函数 invertTree,传入需要判断二叉树的一棵子树;
2、写一个判断两棵树是否相同的子函数,将翻转后的子树,和另一棵没有翻转的子树进行比较;
3、如果比较后两棵树相同,这棵二叉树就为对称二叉树;
4、如果比较厚两棵树不相同,这棵树就不是对称二叉树;

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
//翻转树的代码
struct TreeNode* invertTree(struct TreeNode* root) {
	//如果传入节点为空,返回空
	if (root == NULL)
	{
		return NULL;
	}
	//传入节点不为空,就交换它的左右子树
	struct TreeNode* tmp = root->left;
	root->left = root->right;
	root->right = tmp;
	//迭代直到所有节点的左右子树都被翻转
	invertTree(root->left);
	invertTree(root->right);
	//返回翻转后树的根节点
	return root;
}

//判断两棵树是否相同
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
	//一个为空一个不为空,返回false
    if (p == NULL && q != NULL)
	{
		return false;
	}
	//一个为空一个不为空,返回false
	if (q == NULL && p != NULL)
	{
		return false;
	}
	
	//根节点相等且为空,返回true
	if (q == NULL && p == NULL)
	{
		return true;
	}
	//同一位置的值不相等,返回false
	if (p->val != q->val)
	{
		return false;
	}
	//如果前面的条件都不成立,转化成子问题进行迭代求解,判断左右子树是否为相同的树
	return (isSameTree(p->left, q->left) && isSameTree(p->right,q->right));

}


//判断二叉树是否为对称二叉树
bool isSymmetric(struct TreeNode* root)
{
	//如果根节点为空,默认空树为对称二叉树,返回true
	if (root == NULL)
	{
		return true;
	}
	//根节点不为空,对右树进行翻转
	struct TreeNode* newright = invertTree(root->right);
	//判断左树,和翻转后的右树是否相同
	//相同为对称二叉树,返回true
	//不同就不是对称二叉树,返回false
	return isSameTree(root->left, newright);

}

🦍判断一棵树是否为平衡二叉树🦍

💗题目描述

给定一个二叉树,判断它是否是高度平衡的二叉树。
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
示例


在这里插入图片描述

💗题解

思路::)判断一颗树是否为平衡二叉树的关键就是左右子树的高度差绝对值是否小于1并且左右子树是否也为平衡二叉树。
1、写一个求二叉树高度的子函数;
2、判断左右子树高度是否相差小于1;
3、如果小于1就返回true;
4、大于1就返回false;

代码如下:

// 二叉树的高度
int TreeHeight(struct TreeNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	int leftHeight = TreeHeight(root->left); // 左子树高度
	int rightHeight = TreeHeight(root->right); // 右子树高度

	return (leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1);
}
//判断二叉树是否为平衡二叉树
bool isBalanced(struct TreeNode* root)
{
	if (root == NULL)
	{
		return true;
	}
	//求左子树的高度
	int left = TreeHeight(root->left);
	//求右子树的高度
	int right = TreeHeight(root->right);
	//如果两棵子树高度差大于1就返回false
	if (abs(left - right) > 1)
	{
		return false;
	}
	//如果两棵子树高度差小于等于1,继续递归判断左右子树的子树是否为平衡二叉树
	else
	{
		return isBalanced(root->left) && isBalanced(root->right);
	}
}

🦍翻转一棵二叉树🦍

💗题目描述

给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。
示例
在这里插入图片描述

💗题解

思路😃 判断一颗树是否为平衡二叉树的关键就是左右子树的高度差绝对值是否小于 1 并且左右子树是否也为平衡二叉树。
1、

代码如下:

在这里插入代码片

💗题解

思路
1、判断是否为空,为空返回空;
2、改变左右子树的指针;
3、递归迭代,直到所有子树都被翻转;

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
struct TreeNode* invertTree(struct TreeNode* root){
//如果根节点为空,返回空
if (root == NULL)
	{
		return NULL;
	}
	//改变左右节点指针
	struct TreeNode* tmp = root->left;
	root->left = root->right;
	root->right = tmp;
	//传入root的左子树继续翻转直到左子树全部翻转完成返回
	invertTree(root->left);
	//传入root的右子树继续翻转直到右子树全部翻转完成返回
	invertTree(root->right);
	//最后迭代翻转完成,返回根节点root
	return root;
}

🦍二叉树的前序遍历🦍

💗题目描述

给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例
在这里插入图片描述

💗题解

思路
😃 本道题目是要求把前序遍历的结果放到一个数组中,所以我们要先求出二叉树节点的个数,然后通过前序遍历将数据依次放到数组中。
1、写一个子函数,求树一共有多少节点
2、写一个子函数,将树的节点放入数组中
3、开辟一块树节点大小的空间,接下来遍历树,然后往数组里面放节点值

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
//由于不知道数组应该开辟多大,即不知道树有多少个节点,需要另外写一个求节点个数的函数
int TreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

//传入头节点,前序遍历结果放入数组a中,再给一个下标 i
//由于需要进行递归,所以下标应该传入下标的地址,这里用int *i进行接收
void preorder(struct TreeNode* root, int* a, int* i)
{
	//如果root为空,就返回
	if (root == NULL)
	{
		return;
	}
	//root不为空,就将root的值放入数组i中
	//再将i+1,让其表示数组的下一个位置
	a[(*i)++] = root->val;
	//先走root的左子树
	preorder(root->left, a, i);
	//再走root的右子树
	preorder(root->right, a, i);
}

//把前序遍历的结果放到数组里面,int* returnSize 是返回数组的大小
//实参传入地址,形参接收再解引用就可以改变实参大小,所以要传入地址,然后用指针接收
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
	//用 TreeSize 函数求树中的节点个数,返回值放入 *returnSize 中
	*returnSize = TreeSize(root);
	//开辟一块 *returnSize 大小的空间
	int* a = (int*)malloc(*returnSize * sizeof(int));
	if (a == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	int i = 0;
	//接下来遍历树,然后往数组里面放节点值,由于不能用此函数进行递归
	//所以再写一个子函数遍历这棵树,将树的节点放到数组中
	preorder(root, a, &i);
    return a;
}

🦍二叉树的中序遍历🦍

💗题目描述

给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。
示例
在这里插入图片描述

💗题解

思路:😃 本道题目与前序遍历类似,只需要把要求把前序遍历的preorder 函数放入数组的顺序改变一下,即先走左子树,再根节点,再右子树

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


//由于不知道数组应该开辟多大,即不知道树有多少个节点,需要另外写一个求节点个数的函数
int TreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

//传入头节点,中序遍历结果放入数组a中,再给一个下标 i
//由于需要进行递归,所以下标应该传入下标的地址,这里用int *i进行接收
void inorder(struct TreeNode* root, int* a, int* i)
{
	//如果root为空,就返回
	if (root == NULL)
	{
		return;
	}
	//root不为空,就将root的值放入数组i中
	//先走root的左子树
	inorder(root->left, a, i);
    //再将i+1,让其表示数组的下一个位置
	a[(*i)++] = root->val;
	//再走root的右子树
	inorder(root->right, a, i);
}

//把中序遍历的结果放到数组里面,int* returnSize 是返回数组的大小
//实参传入地址,形参接收再解引用就可以改变实参大小,所以要传入地址,然后用指针接收
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
	//用 TreeSize 函数求树中的节点个数,返回值放入 *returnSize 中
	*returnSize = TreeSize(root);
	//开辟一块 *returnSize 大小的空间
	int* a = (int*)malloc(*returnSize * sizeof(int));
	if (a == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	int i = 0;
	//接下来遍历树,然后往数组里面放节点值,由于不能用此函数进行递归
	//所以再写一个子函数遍历这棵树,将树的节点放到数组中
	inorder(root, a, &i);
    return a;
}

🦍二叉树的后序遍历🦍

💗题目描述

给你一棵二叉树的根节点 root ,返回其节点值的 后序遍历
示例
在这里插入图片描述

💗题解

思路:😃 本道题目与前序遍历、中序遍历类似,需要先走左子树,再右子树,再根节点

代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


//由于不知道数组应该开辟多大,即不知道树有多少个节点,需要另外写一个求节点个数的函数
int TreeSize(struct TreeNode* root)
{
	return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}

//传入头节点,后序遍历结果放入数组a中,再给一个下标 i
//由于需要进行递归,所以下标应该传入下标的地址,这里用int *i进行接收
void postorder(struct TreeNode* root, int* a, int* i)
{
	//如果root为空,就返回
	if (root == NULL)
	{
		return;
	}
	//root不为空,就将root的值放入数组i中
	//先走root的左子树
	postorder(root->left, a, i);
	//再走root的右子树
	postorder(root->right, a, i);
    //再将i+1,让其表示数组的下一个位置
	a[(*i)++] = root->val;
}

//把后序遍历的结果放到数组里面,int* returnSize 是返回数组的大小
//实参传入地址,形参接收再解引用就可以改变实参大小,所以要传入地址,然后用指针接收
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
	//用 TreeSize 函数求树中的节点个数,返回值放入 *returnSize 中
	*returnSize = TreeSize(root);
	//开辟一块 *returnSize 大小的空间
	int* a = (int*)malloc(*returnSize * sizeof(int));
	if (a == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	int i = 0;
	//接下来遍历树,然后往数组里面放节点值,由于不能用此函数进行递归
	//所以再写一个子函数遍历这棵树,将树的节点放到数组中
	postorder(root, a, &i);
    return a;
}

🦍二叉树遍历🦍

💗题目描述

编一个程序,读入用户输入的一串先序遍历字符串,并建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串:“ ABC##DE#G##F### ” 其中“ # ”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
示例
在这里插入图片描述
图示
在这里插入图片描述

💗题解

思路:😃 构建二叉树是先构建根,然后构建左子树和右子树,那么这个顺序就是前序遍历的顺序,那么我们可以采取前序遍历递归的方式来构建二叉树。
1、取读入数组的位置变量为 i,判断位置 i 字符是否为 ‘ # ’ ,如果是就更新位置并返回空;
2、如果 i 位置不是 ‘ # ’,就创建一个二叉树新节点储存输入的值,在更新 i 的值,此时根节点已经构建完了
3、继续判断 i 位置是否符合要求,如果不是 ‘ # ’,按照上述规则继续构建左子树;
4、继续判断 i 位置是否符合要求,如果不是 ‘ # ’,按照上述规则继续构建右子树;

递归图解如下:
在这里插入图片描述

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

struct TreeNode
{
	char val;
	struct TreeNode* left;
	struct TreeNode* right;
};

struct TreeNode* rebuildTree(char* arr, int *i)
{
	//传过来的数组如果遇到了‘#’就返回 NULL
	if (arr[*i] == '#')
	{
		(*i)++;
		return NULL;
	}
	//如果不是‘#’就创建一个新的节点
	struct TreeNode* newnode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	//节点的值为传进来的字符
	newnode->val = arr[*i];
	//字符用过后,下一次用的就是下一个字符,所以更新i
	(*i)++;
	//构建左树+6
	newnode->left = rebuildTree(arr, i);
	//构建右树
	newnode->right = rebuildTree(arr, i);
	//返回newnode
	return newnode;
}
//用构建完的树进行中序遍历
void InOrder(struct TreeNode* root)
{
	if (root == NULL)
	{
		return;
	}
	InOrder(root->left);
	printf("%c ", root->val);
	InOrder(root->right);
}

int main()
{
    char arr[100];
    scanf("%s",arr);
    int i = 0;
    struct TreeNode* ret = rebuildTree(arr, &i);
    InOrder(ret);
}

🦍二叉树的销毁🦍

因为根和左右子树有链接关系,所以我们不能先销毁根。如果先销毁根我们就找不到左右子树了,所以我们采取后序遍历销毁二叉树。

代码如下:

// 二叉树销毁
void BinaryTreeDestroy(BTNode** root)
{
	if (*root == NULL)
	{
		return;
	}
	BinaryTreeDestroy(&(*root)->_left);
	BinaryTreeDestroy(&(*root)->_right);
	free(*root);
	*root = NULL;
}

🦍二叉树的层序遍历🦍

💗原理描述

原理
设二叉树的根节点所在层数为 1,层序遍历就是从所在二叉树的根节点出发,首先访问第 1 层的树根节点,然后从左到右访问第 2 层上的节点,接着是第 3 层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
在这里插入图片描述

💗题解

思路:😃 利用队列先入先出的原则,树的第一层先进去,队列不为空,第一层出来,第二层进去,以此类推,出一层进一层。

过程图解

在这里插入图片描述

代码如下:

// 初始化队列 
//因为Queue里面是两个QList类型的指针,指向队列QList的头和尾,所以初始化只需要创建Queue变量,将其头尾置为NULL即可
void QueueInit(Queue* q)
{
	assert(q);
	q->_front = NULL;
	q->_rear = NULL;
}

//销毁队列
//销毁队列只需要利用头指针和尾指针的结构体进行操作,所以传值只传结构体Queue变量即可
void QueueDestroy(Queue* q)
{
	assert(q);
	//定义一个QNode* 类型的变量cur,QNode为一个队列节点的大小,cur每增加一次,cur就到达下一个队列节点的位置
	QNode* cur = q->_front;
	//当cur等于队列的最后一个节点之后的空的地址时,跳出循环,否则cur就一直走
	while (cur != NULL)
	{
		//第一次cur为第一个队列节点位置,定义del变量记录此时cur的位置
		QNode* del = cur;
		//释放第一个队列节点,cur走到下一个队列节点的位置
		cur = cur->_next;
		free(del);
		del = NULL;
	}
	q->_front = q->_rear = NULL;

}
//插入需要知道队列的首地址和尾地址,所以传Queue,里面有队列的首地址和尾地址
void QueuePush(Queue* q, QDataType data)
{
	//因为带有队列头尾指针的结构体已经创建出来并传值给QueuePush函数,所以q一定不为NULL,在此需要断言
	assert(q);
	//开辟空间,创建一个QListNode节点
	//因为只有插入函数需要创建新节点,所以可以不用单独写一个BuyNode函数来创建新节点,直接在QueuePush里创建即可
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}
	newnode->_data = data;
	newnode->_next = NULL;
	//判断如果队列刚被创建没有节点,newnode就是第一个元素
	if (q->_front == NULL)
	{
		q->_front = q->_rear = newnode;
	}
	//如果队列已经被创建且有值,那么newnode就是q->_rear之后的节点
	//将newnode链接到q->_rear之后
	//更新q->_rear的位置
	else
	{
		q->_rear->_next = newnode;
		q->_rear = newnode;
	}
}

// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	if (q->_front->_next == NULL)
	{
		free(q->_front);
		q->_front = q->_rear = NULL;
	}
	else
	{
		QNode* cur = q->_front;
		cur = cur->_next;
		free(q->_front);
		q->_front = cur;
	}
}

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));
	return q->_front->_data;
}


// 手动构建二叉树
BTNode* CreateTree()
{
	BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
	assert(n1);
	BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
	assert(n2);
	BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
	assert(n3);
	BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
	assert(n4);
	BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
	assert(n5);
	BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
	assert(n6);

	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;
	n5->data = 5;
	n6->data = 6;

	n1->left = n2;
	n1->right = n4;
	n2->left = n3;
	n2->right = NULL;
	n3->left = NULL;
	n3->right = NULL;
	n4->left = n5;
	n4->right = n6;
	n5->left = NULL;
	n5->right = NULL;
	n6->left = NULL;
	n6->right = NULL;

	return n1;
}

// 二叉树销毁
void BinaryTreeDestroy(BTNode* root)
{
	if (root == NULL)
		return;
	BinaryTreeDestroy(root->left);
	BinaryTreeDestroy(root->right);
	free(root);
}

// 层序遍历
// 用队列来实现层序遍历
// Queue要存二叉树结点的指针,才能找到左右孩子,只存数据找不到二叉树的左右孩子
void BinaryTreeLevelOrder(BTNode* root)
{
	Queue q1;
	QueueInit(&q1);
	if (root != NULL)
	{
		QueuePush(&q1,root);
	}
	//如果队列不为空就取队列头部数据,然后将队列头部数据pop掉
	//pop掉的是父节点,pop掉父节点之后,如果左右孩子不为空,就入队列
	//直到队列为空说明遍历完了整个二叉树
	while (!QueueEmpty(&q1))
	{
		BTNode* front = QueueFront(&q1);
		printf("%c ", front->_data);
		QueuePop(&q1);
		if (front->_left != NULL)
		{
			QueuePush(&q1, front->_left);
		}
		if (front->_right != NULL)
		{
			QueuePush(&q1, front->_right);
		}
		
	}
	printf("\n");
	QueueDestroy(&q1);

int main()
{
	BTNode* root = CreateTree();
	// 层序遍历
	BinaryTreeLevelOrder(root);
	// 销毁二叉树
	BinaryTreeDestroy(root);
	root = NULL;
	return 0;
}
}

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

💗题解

思路:因为层序遍历是一层一层遍历的,所以可以利用层序遍历来判断二叉树是否为完全二叉树。一层一层走,遇到空以后,后续的层序遍历不能有非空,有非空就不是完全二叉树。

代码如下:

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root)

{
   Queue q1;
   QueueInit(&q1);
   if (root != NULL)
   {
      QueuePush(&q1, root);
   }
   //如果队头数据为空就检查判断是否为完全二叉树
   //如果front为NULL,说明front以后的数据应该全部为空
   //如果有非空,则说明该二叉树不是完全二叉树
   while (!QueueEmpty(&q1))
   {
      //front记录队列头部数据
      BTNode* front = QueueFront(&q1);
      if (front == NULL)
      {
         break;
      }
      printf("%c ", front->_data);
      //数据出队列
      QueuePop(&q1);
      //如果队列为空就退出循环判断
      //队列不为空就进左右孩子
         QueuePush(&q1, front->_left);
         QueuePush(&q1, front->_right);
   }
   //检查,break出来进行检查,如果后面全是空就是完全二叉树,否则就不是完全二叉树
   while (!QueueEmpty(&q1))
   {
      BTNode* front = QueueFront(&q1);
      //如果front不为空说明再空之后还有非空的数,说明二叉树不是完全二叉树,返回1

      if (front != NULL)
      {
         QueueDestroy(&q1);
         return 1;
      }
      QueuePop(&q1);
   }
   //如果数据全部出完,说明该树是完全二叉树
   printf("\n");
   QueueDestroy(&q1);
   return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值