一、树的层序遍历
层序遍历的实现:
1.依赖于队列的数据结构
2.核心怎么实现:
1)创建一个队列的容器对象。
2)判断根节点是否为空,不为空则添加根节点到队列中。
3)遍历是一个循环性的工作,写一个死循环,死循环的第一步就是跳出死循环的条件:当队列中没有东西时退出(换句话说,没东西可遍历了)。
4)每弹出一个元素,再访问(就是进行符合场景的操作),最后添加两边的左右子节点(如果不为空的话)。
代码实现:
队列的代码:
#pragma once
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
#include<stdbool.h>
typedef struct BinaryTreeNode* QDataType;
typedef struct QueueNode
{
struct QueueNode* _pNext;
QDataType _val;
}QNode;
typedef struct Queue
{
QNode* _front;
QNode* _rear;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
// 队尾插入
void QueuePush(Queue* pq, QDataType x);
// 队头删除
void QueuePop(Queue* pq);
// 取队头和队尾的数据
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
队尾插入
//void QueuePush(QNode** pphead, QNode** pptail, QDataType x);
队头删除
//void QueuePop(QNode** pphead, QNode** pptail);
#include"Queue.h"
// 初始化队列
void QueueInit(Queue* q)
{
assert(q);
q->_front = NULL;
q->_rear = NULL;
q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QNode* tmp = (QNode*)malloc(sizeof(QNode));
if (tmp == NULL)
{
perror("malloc fail");
return;
}
else
{
tmp->_data = data;
tmp->_pNext = NULL;
}
if (q->_rear == NULL)
{
q->_front = q->_rear = tmp;
}
else
{
q->_rear->_pNext = tmp;
q->_rear = tmp;
}
q->size++;
}
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(q->_front);
assert(q->size != 0);
if (q->_front->_pNext == NULL)//只有一个节点
{
free(q->_front);
q->_front = q->_rear = NULL;
}
else
{
QNode* next = q->_front->_pNext;
free(q->_front->_pNext);
q->_front = next;
}
q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
assert(q->_front);
return q->_front->_data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
assert(q->_rear);
return q->_rear->_data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
return q->size == 0;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
QNode* tmp = q->_front;
while (tmp != NULL)
{
QNode* next = tmp->_pNext;
free(tmp);
tmp = next;
}
q->_front = q->_rear = NULL;
q->size = 0;
}
void TreeLevelOrder(BTNode* root)//层序遍历
{
Queue pq;
QueueInit(&pq);
if (root)
QueuePush(&pq, root);
while (!QueueEmpty(&pq))
{
BTNode* front = QueueFront(&pq);
QueuePop(&pq);
printf("%d ", front->_data);
if (front->_left)
QueuePush(&pq, front->_left);
if (front->_right)
QueuePush(&pq, front->_right);
}
QueueDestroy(&pq);
}
二、平衡二叉树的判断
这道题中的平衡二叉树的定义是:二叉树的每个节点的左右子树的高度差的绝对值不超过 111,则二叉树是平衡二叉树。根据定义,一棵二叉树是平衡二叉树,当且仅当其所有子树也都是平衡二叉树,因此可以使用递归的方式判断二叉树是不是平衡二叉树,
int maxDepth(struct TreeNode* root){
return root ? 1 + fmax(maxDepth(root->left) , maxDepth(root->right)) : 0;
}
bool isBalanced(struct TreeNode* root){
if(root == NULL)
return true;
int left = maxDepth(root->left);
int right = maxDepth(root->right);
return abs(left - right) < 2
&& isBalanced(root->left)
&& isBalanced(root->right);
}
三、树的反转
这是一道很经典的二叉树问题。显然,我们从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root为根节点的整棵子树的翻转。
/**
* 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;
}