目录
1、判断二叉树是否是完全二叉树
思路:
以层序遍历的思路(利用队列,一层带一层),
当遇到NULL,break,再判断后面有没有非NULL的元素,
若有,则非完全二叉树,反之,是完全二叉树
bool BinaryTreeComplete(BTNode* root)// 判断二叉树是否是完全二叉树
{
if (root == NULL)
return false;
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
break;
QueuePush(&q, front->_left);
QueuePush(&q, front->_right);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
QueueDestroy(&q);//防止内存泄漏
return false;
}
}
return true;
}
2、单值二叉树
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树,
只有给定的树是单值二叉树时,才返回 true
;否则返回 false
示例:
输入:[1,1,1,1,1,null,1] 输出:true
思路1:传值
为NULL return true,因为NULL没有关系
不为k(相同的值),直接 return false,不用再向下遍历了
为k,再向下遍历,没有找到不相同的k,就 return true
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool _isUnivalTree(struct TreeNode* root,int k)
{
if(root == NULL)
return true;
if(root->val != k)
return false;
return _isUnivalTree(root->left,k)&&_isUnivalTree(root->right,k);
}
bool isUnivalTree(struct TreeNode* root) {
int k = root->val;
return _isUnivalTree(root,k);
}
思路2:不传值
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool isUnivalTree(struct TreeNode* root) {
if(root == NULL)
return true;
if(root->left&&root->left->val != root->val)
return false;
if(root->right&&root->right->val != root->val)
return false;
return isUnivalTree(root->left)&&isUnivalTree(root->right);
}
3、二叉树的前序遍历
给你二叉树的根节点 root
,返回它节点值的 前序 遍历
示例:
输入:root = [1,null,2,3]
输出:[1,2,3]
思路:
C语言返回数组时,要返回数组的大小,但函数只能返回一个值,于是用了指针(作为输出型参数,如果这个参数是用来做输入的,就叫输入型参数;如果这个参数的目的是用来做输出的,就叫输出型参数)
先递归算出树的大小
为什么用pi,直接用 *arr = root->val; arr++; 不行吗?
因为 _preorderTraversal(root->left,arr);
_preorderTraversal(root->right,arr);
当 return 回来时_preorderTraversal(root->right,arr);中的 arr 并没有改变
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int treeSize(struct TreeNode* root)
{
return root == NULL?0:treeSize(root->left)+treeSize(root->right)+1;
}
void _preorderTraversal(struct TreeNode* root, int* arr,int* pi) {
if(root == NULL)
return;
arr[(*pi)++] = root->val;
_preorderTraversal(root->left,arr,pi);
_preorderTraversal(root->right,arr,pi);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = treeSize(root);
int* arr = (int*)malloc(sizeof(int)*(*returnSize));
int i = 0;
_preorderTraversal(root,arr,&i);
return arr;
}
4、相同的树
给你两棵二叉树的根节点 p
和 q
,编写一个函数来检验这两棵树是否相同,
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的
示例:
输入:p = [1,2,3], q = [1,2,3] 输出:true
思路:
当都为NULL时,return true;
有一个为NULL,return false;
值不相等,return false;
再左右子树相互比较
/**
* 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 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);
}
5、对称二叉树
给你一个二叉树的根节点 root
, 检查它是否轴对称
示例:
输入:root = [1,2,2,3,4,4,3] 输出:true
思路:
利用isSameTree():,注意是轴对称,所以
isSameTree(p->left,q->right)&&isSameTree(p->right,q->left);
/**
* 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 true;
if(p== NULL||q == NULL)
return false;
if(p->val != q->val)
return false;
return isSameTree(p->left,q->right)&&isSameTree(p->right,q->left);
}
bool isSymmetric(struct TreeNode* root) {
return isSameTree(root->left,root->right);
}
6、另一颗树的子树
给你两棵二叉树 root
和 subRoot
。检验 root
中是否包含和 subRoot
具有相同结构和节点值的子树。如果存在,返回 true
;否则,返回 false
示例:
输入:root = [3,4,5,1,2], subRoot = [4,1,2] 输出:true
思路:
root为NULL,return false;
先判断root->val == subRoot->val; ,再利用isSameTree(root,subRoot); 成立 return true; 就找到了
反之,在从左右子树找,只要找到就行,所以用||
/**
* 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 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);
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot) {
if(root == NULL)
return false;
if(root->val == subRoot->val&&isSameTree(root,subRoot))
return true;
return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}
7、二叉树的遍历
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储),再对二叉树进行中序遍历,输出遍历结果
示例:
输入:
abc##de#g##f###
输出:
c b e g d f a
思路:
就算为'#',return NULL前 也要更新下标
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct TreeNode {
int val;
struct TreeNode* left;
struct TreeNode* right;
} TreeNode;
TreeNode* creeatTree(char* arr,int* pi) {
if(arr[*pi] == '#')
{
(*pi)++;
return NULL;
}
TreeNode* root = (TreeNode*)malloc(sizeof(TreeNode));
assert(root);
root->val = arr[(*pi)++];
root->left = creeatTree(arr,pi);
root->right = creeatTree(arr,pi);
return root;
}
void binaryTreeInOrder(TreeNode* root)
{
if(root == NULL)
return;
binaryTreeInOrder(root->left);
printf("%c ",root->val);
binaryTreeInOrder(root->right);
}
int main() {
char arr[100];
scanf("%s", arr);
int i = 0;
TreeNode* root = creeatTree(arr,&i);
binaryTreeInOrder(root);
return 0;
}
8、翻转二叉树
/**
* 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 = invertTree(root->left);
root->left = invertTree(root->right);
root->right = tmp;
return root;
}
9、平衡二叉树
思路:
利用之前的算高度的思想,这时返回类型是int,所以要新建一个子函数,
当发现左右子树高度差>1,这时就已经确定结果了,可我现在的阶段不知道怎么立即结束递归并返回,
所以就用了输出型参数int* px,记录 存在左右子树高度差>1,然后在原函数里再判断
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int _isBalanced(struct TreeNode* root,int* px)
{
if(root == NULL)
return 0;
int leftheight = _isBalanced(root->left,px);
int rightheight = _isBalanced(root->right,px);
int flag = leftheight>rightheight?leftheight-rightheight:rightheight-leftheight;
if(flag > 1)
*px = 0;
return leftheight>rightheight?leftheight+1:rightheight+1;
}
bool isBalanced(struct TreeNode* root) {
int x = 1;
_isBalanced(root,&x);
return x == 1?true:false;
}
总结:二叉树的遍历与数组扯上关系时,一般要传下标的地址,保持下标的更新