1.二叉树的遍历
二叉树遍历时按照某种特定的规则,一次对二叉树中的节点进行相应操作,并且每个节点值操作一次。
按照规则,二叉树的遍历有:前序,中序,后序的递归结构遍历。
1.前序遍历:访问根节点操作发生再遍历其左右子树之前,按照根左右的顺序。
2.中序遍历:访问根节点的操作发生在遍历其左右子树之间,按照左根右的顺序。
3.后序遍历:访问根节点的操作发生在遍历其左右子树之后,按照左右根的顺序。
例如下面二叉树:
前序遍历逻辑图:
中序遍历逻辑图:
后序遍历逻辑图:
2.计算二叉树节点数量
1.计算二叉树节点数量:
//计算节点数量
int TreeSize(Node* node)
{
if (node == NULL)
{
return 0;
}
return TreeSize(node->left) + TreeSize(node->right) + 1;
}
思路:
判断的作用有两个:一是为了判断是不是空树,二是为了终止递归。返回的是二叉树的左右子树的所有节点加上当前根节点。
2.计算叶子节点数量:
//计算叶子节点数量
int LeafSize(Node* node)
{
if (node == NULL)
{
return 0;
}
if (node->left == NULL && node->right == NULL)
{
return 1;
}
return LeafSize(node->left) + LeafSize(node->right);
}
思路:
第一个判断作用如上,第二个判断是若当前节点的左右子树都为NULL的话说明当前节点为叶子节点返回1,如果不是则继续递归。
3.计算二叉树的层数:
//计算二叉树的层数
int TreeHeight(Node* node)
{
if (node == NULL)
{
return 0;
}
int left = TreeHeight(node->left);
int right = TreeHeight(node->right);
return left > right ? left + 1 : right + 1;
}
思路:
判断的作用如上,创建两个变量是为了提高递归效率,存储返回值结果。因为层数是按照最高层数计算,则判断左右层数哪个更高,返回更高的子树加上当前节点所在的层数。
4.计算第K层的节点个数:
//计算第K层的节点个数
int TreeLevelSize(Node* node, int k)
{
assert(k > 0);
if (node == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return TreeLevelSize(node->left, k - 1) + TreeLevelSize(node->right, k - 1);
}
思路:
将此问题转换成左子树的第k-1层和右子树的k-1层,假设需要找的是第3层,访问第1层传参k的值为3,第二层则传参k=k-1,以此类推,当访问到第3层时k的值为1,也就是计算左右子树当k=1时的节点之和。那么终止条件就是当k=1时或者节点为NULL时。
5.找出值为x的节点:
//找值为x的节点
Node* TreeFind(Node* node, datatype x)
{
if (node == NULL)
{
return NULL;
}
if (node->data == x)
{
return node;
}
Node* result1 = TreeFind(node->left, x);
Node* result2 = TreeFind(node->right, x);
return result1 != NULL ? result1 : result2;
}
思路:
通过递归遍历二叉树,当节点的值等于x时返回改节点的地址,如果不满足则创建两个变量分别接收左右子树的返回结果,递归结束的条件为当节点为NULL时。
6.层序遍历二叉树:
void Levelorder(Node* node)
{
Queue q;
QueueInit(&q);
if (node != NULL)
{
QueuePush(&q,node);
}
while (!QueueEmpty(&q))
{
Node* front = QueueFront(&q);
QueuePop(&q);
printf("%d ", front->data);
if (front->left != NULL)
{
QueuePush(&q, front->left);
}
if (front->right != NULL)
{
QueuePush(&q, front->right);
}
}
QueueDestory(&q);
}
思路:
利用了栈的先进先出的原则,上一层带入下一层的原理实现层序遍历,其余代码利用之前栈的增删查改的实现。
3.判断是否为完全二叉树
代码:
bool TreeComplete(Node* root)
{
Queue q;
QueueInit(&q);
if (root == NULL)
{
return false;
}
QueuePush(&q,root);
while (!QueueEmpty(&q))
{
Node* front = QueueFront(&q);
QueuePop(&q);
if (front == NULL)
{
break;
}
QueuePush(&q, front->left);
QueuePush(&q, front->right);
}
while (!QueueEmpty(&q))
{
Node* front = QueueFront(&q);
QueuePop(&q);
if (front != NULL)
{
QueueDestory(&q);
return false;
}
}
QueueDestory(&q);
return true;
}
思路:
整体思路是借助层序遍历判断当遇到空时判断队列中剩余的元素是否存在非空元素,若是存在则说明不是完全二叉树,不存在则说明是完全二叉树。