数据结构学习篇(10)--- 二叉树基础oj练习

1. 单值二叉树

单值二叉树指的是二叉树中存储的数据都是同一个值,那么该如何判断一个二叉树是否为单值二叉树呢?

利用递归的思想,将左子树和右子树中的数据分别与根节点中的数据进行比较,相同返回true,不同返回false,以此递归循环便可进行判断。

代码实现:

cpp 复制代码
//判断是否为单值二叉树
bool isUnivalTree(BTNode* root)
{
	if (root == NULL)
		return true;//默认空树返回true
	if (root->Left != NULL && root->Left->data != root->data)
		return false;
	if (root->Right != NULL && root->Right->data != root->data)
		return false;
	return isUnivalTree(root->Left) && isUnivalTree(root->Right);
}

2. 检查两棵树是否相

这个方法通过递归比较两棵二叉树的结构和节点值来判断是否相同,其核心思路如下:

  1. 终止条件

    • 若两节点均为空(p == NULL && q == NULL),说明当前分支结构一致,返回 true
    • 若仅一节点为空(p == NULL || q == NULL),说明结构不一致,返回 false
  2. 节点值比较

    • 若当前节点值不同(p->data != q->data),直接返回 false
  3. 递归比较子树

    • 递归检查左子树(p->Leftq->Left)和右子树(p->Rightq->Right)是否相同,只有两者均相同才返回 true

代码实现:

cpp 复制代码
//检查两棵树是否相同
bool issameTree(BTNode* p, BTNode* q)
{
	if (p == NULL && q == NULL)
		return true;
	if (p == NULL || q == NULL)
		return false;
	if (p->data != q->data)
		return false;
	return issameTree(p->Left, q->Left) &&
		issameTree(p->Right, q->Right);
}

3. 对称二叉树

这题的思路和上一题的思路基本相同,只需要将这棵树的左右子树看作两棵树,然后对这两棵树的左子树和右子树进行比较即可。

算法思路

  1. 对称二叉树的定义

    • 一棵二叉树是对称的,当且仅当它的左子树和右子树互为镜像。
    • 两棵树互为镜像的条件:
      • 它们的根节点值相同。
      • 一棵树的左子树与另一棵树的右子树互为镜像。
      • 一棵树的右子树与另一棵树的左子树互为镜像。
  2. 递归实现

    • 定义一个辅助函数 _isSymmetric(p, q),用于递归比较两棵子树 pq 是否互为镜像。
    • 在主函数 isSymmetric(root) 中,调用 _isSymmetric(root->Left, root->Right) 比较根节点的左右子树。
  3. 递归终止条件

    • 如果两棵子树均为空(p == NULL && q == NULL),返回 true
    • 如果其中一棵子树为空而另一棵不为空(p == NULL || q == NULL),返回 false
    • 如果两棵子树的根节点值不同(p->data != q->data),返回 false
  4. 递归比较

    • 比较 p 的左子树和 q 的右子树(_isSymmetric(p->Left, q->Right))。
    • 比较 p 的右子树和 q 的左子树(_isSymmetric(p->Right, q->Left))。
    • 只有两者都为真时,才返回 true

代码实现:

cpp 复制代码
bool _isSymmtric(BTNode* p, BTNode* q)
{
	if (p == NULL && q == NULL)
		return true;
	if (p == NULL || q == NULL)
		return false;
	if (p->data != q->data)
		return false;
	return _isSymmtric(p->Left, q->Right)
		&& _isSymmtric(p->Right, q->Left);
}

//对称二叉树的判断
bool isSymmtric(BTNode* root)
{
	if (root == NULL)
		return true;
	return _isSymmtric(root->Left, root->Right);
}

4. 判断一颗树是否和另一棵树的子树相同

递归实现

  • 定义一个辅助函数 issameTree(p, q)(假设已实现),用于判断两棵树是否完全相同。
  • isSubTree 函数中:
    • 如果 root 为空(root == NULL),说明已经遍历完 root 但未找到匹配的子树,返回 false
    • 如果当前 root 的节点值与 subroot 的根节点值相同,并且 issameTree(root, subroot) 返回 true,则说明找到匹配的子树,返回 true
    • 否则,递归检查 subroot 是否是 root 的左子树或右子树的子树。代码实现:

代码实现:

cpp 复制代码
//判断一个树是否和另一棵树的子树相同
bool isSubTree(BTNode* root, BTNode* subroot)
{
	if (root = NULL)
		return false;
	if (root->data == subroot->data && issameTree(root, subroot))
		return true;
	return isSubTree(root->Left, subroot)
		|| isSubTree(root->Right, subroot);
}

5. 前序遍历

这里所指的前序遍历和上一节说的有所不同,这里是指通过前序遍历的方式将数据的值存放到一个数组中,并返回这个数组。

代码实现:

cpp 复制代码
//前序遍历二叉树,将数值存储到数组中并返回


//首先求得二叉树的总结点个数
int TreeSize(BTNode* root)
{
	return root == NULL ? 0 : TreeSize(root->Left) + TreeSize(root->Right) + 1;
}
//进行前序遍历及存储数据在数组中
void preOrder(BTNode* root,int* a,int* pi)
{
	if (root == NULL)
		return;
	a[(*pi)++] = root->data;
	preOrder(root->Left, a, pi);
	preOrder(root->Right, a, pi);
}
//这个算法的主函数
int preorderTraversal(BTNode* root, int* returnsize)
{
	*returnsize = Treesize(root);
	int* a = (int*)malloc(sizeof(*returnsize));
	int i = 0;
	preOrder(root, a, &i);
	return a;
}

该算法通过递归前序遍历二叉树:先计算节点总数分配数组空间,再按根→左→右顺序存储节点值到数组,最后返回数组及元素个数

6. 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树

代码实现:

cpp 复制代码
//通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* TreeCreat(char* a, int* pi)
{
	if (a[*pi] == '#')
		//错误写法:if(a[(*pi)++] == '#')
		//这种写法会导致代码走到这一步判断完条件语句之后自动加一,导致原来的字符被遗漏!
	{
		(*pi)++;
		return NULL;//代表空树
	}
	BTNode* root = (BTNode*)malloc(sizeof(BTNode));
	root->data = a[(*pi)++];
	root->Left = TreeCreat(a, pi);
	root->Right = TreeCreat(a, pi);
	return root;
}
int main()
{
	char a[100];
	scanf("%s ", a);
	int i = 0;
	BTNode* root = TreeCreat(a, &i);
	return 0;
}

这段代码通过前序遍历字符串 递归构建二叉树:遇到非 '#' 字符时创建节点并递归构建左右子树,遇到 '#' 时返回 NULL 表示空节点,索引指针 pi 随递归动态移动确保字符顺序处理。

**注:**千万不能够写代码中的错误示范,因为如果那样写的话,当一个字符在进行判断时,假如不满足判断的条件语句,那i就会自动加1到下一个字符,这就导致原先的字符还没有被正确操作就被略过了,这是一个经典的错误!

相关推荐
千谦阙听2 小时前
双链表:比单链表更高效的增删查改
数据结构·链表·visual studio
QiZhang | UESTC2 小时前
学习日记day58
学习
JeffDingAI2 小时前
【Datawhale学习笔记】基于Gensim的词向量实战
人工智能·笔记·学习
xie_pin_an2 小时前
从二叉搜索树到哈希表:四种常用数据结构的原理与实现
java·数据结构
好奇龙猫3 小时前
【大学院-筆記試験練習:线性代数和数据结构(11)】
学习
栈与堆4 小时前
LeetCode 21 - 合并两个有序链表
java·数据结构·python·算法·leetcode·链表·rust
viqjeee4 小时前
ALSA驱动开发流程
数据结构·驱动开发·b树
何以不说话4 小时前
mysql 的主从复制
运维·数据库·学习·mysql
wm10434 小时前
大模型学习day01 python基础
学习