(1)单值二叉树
整体思路是遍历比较,可比较的固定值在递归中,如何保存?
我们采用构建新函数,将根节点的值传给它作参数的方法。
代码实现:
bool _isUnivalTree(struct TreeNode* root,int x)
{
if(root == NULL)
return true;
if(root->val != x)
return false;
//一错就错
return _isUnivalTree(root->left,x) && _isUnivalTree(root->right,x);
}
bool isUnivalTree(struct TreeNode* root) {
return _isUnivalTree(root,root->val);
}
(2)对称二叉树

左右子树同时向下深入,左子树的左孩子节点和右子树的右孩子节点相比,左子树的右孩子节点和右子树的左孩子相比,很显然,想让两棵树同时向下,仅仅只有一个参数的函数不能完成。
代码实现:
bool _isSymmetric(struct TreeNode* left,struct TreeNode* right)
{
if(left == NULL && right == NULL)
return true;
if((left == NULL && right != NULL) || (left != NULL && right == NULL))
//if(left == NULL || right == NULL 也是可以的
return false;
if(left->val != right->val)
return false;
return _isSymmetric(left->left,right->right) && _isSymmetric(left->right,right->left);
}
bool isSymmetric(struct TreeNode* root) {
return _isSymmetric(root->left,root->right);
}
if(left == NULL || right == NULL)
可以这样写,因为在前一条语句就判断了会不会两个节点都为NULL,到该语句的时候,只剩下左空右不空、左不空右空和左右都不空三种情况,而只要一方为空,就代表绝不可能为对称二叉树。
(3)相同的树

代码实现:
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
if(p == NULL && q == NULL)
return true;
if(p == NULL || q == NULL)
return false;
if(p->val != q->val )
return false;
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
思路和上一题有点像。
(4)另一棵树的子树

首先先弄懂:什么叫判断A树是不是B的子树,下面这种情况是吗?

不是,因为root树的子树是蓝色框,并不是红色框。
代码实现:
bool isSametree(struct TreeNode* root,struct TreeNode* subRoot)
{
if(subRoot == NULL && root == NULL)
return true;
if(subRoot == NULL || root == NULL)
return false;
if(root->val != subRoot->val)
return false;
return isSametree(root->left,subRoot->left) && isSametree(root->right,subRoot->right);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {
if( root == NULL )
//root树都向下走到空节点了,还没找到和subroot树的值相同的节点
return false;
if(root->val == subRoot->val && isSametree(root,subRoot))
return true;
else
//节点值不同就换root树的其他节点
//有过相同的节点值但判断过程中出错,那就换其他节点值继续判断
return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);
}
(5)二叉树的前中后序遍历
三者的思路极其相似,此处我就写前序遍历了。

函数只能返回一个值,在此处,要求返回数组的首地址,但想打印数组,仅仅只知道数组的首地址是不够的,还需要知道数组的长度,可长度不能再返回了,所以有了指针returnSize。
输出型参数:
returnSize相当于在调用preorderTraversal时,传了个&size的参数(数组长度的指针),这样在preorderTraversal函数中就能通过returnSize指针访问到size,也就能改变size,那么就能知道数组的长度了。
代码实现:
int BTreeSize(struct TreeNode* root)
{
return root == NULL?0:BTreeSize(root->left)+BTreeSize(root->right)+1;
}
void _preorderTraversal (struct TreeNode* root,int*arr,int* i)
{
if(root == NULL)
return ;
arr[*i] = root->val;
(*i)++;
_preorderTraversal(root->left,arr,i);
_preorderTraversal(root->right,arr,i);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
//遍历二叉树求出数组的准确长度
*returnSize = BTreeSize(root);
int* arr = (int*)malloc(sizeof(int)*(*returnSize));
int i = 0;
//下标
_preorderTraversal(root,arr,&i);
//在递归中,i一旦改变就需要保留改变后的值,所以是传指针,而不是传临时变量
return arr;
}
(6)二叉树遍历

代码实现:
#include <stdio.h>
#include <stdlib.h>
typedef struct BTreeNode
{
int val;
struct BTreeNode* left;
struct BTreeNode* right;
}BTNode;
//根据中序遍历数组构建链式二叉树
BTNode* CreateBTree(char* arr,int* i)
{
if(arr[*i] == '#')
{
(*i)++;
return NULL;
}
BTNode* root = (BTNode*)malloc(sizeof(BTNode));
root->val = arr[*i];
(*i)++;
root->left = CreateBTree(arr,i);
root->right = CreateBTree(arr,i);
return root;
}
//中序遍历
void InOrder(BTNode* root)
{
if(root == NULL)
return;
InOrder(root->left);
printf("%c ",root->val);
InOrder(root->right);
}
int main()
{
int i = 0;
char arr[100];
scanf("%s",arr);
BTNode* root = CreateBTree(arr,&i);
InOrder(root);
return 0;
}

------end------