二叉树 概念
二叉树要么是空树,要么是非空树,即由根结点、根结点的左子树和根结点的右子树组成。
可以看出二叉树是递归定义的,后序操作都是基于这个结论实现的。
前序(先序)遍历
按照 根结点-左子树-右子树 的顺序遍历树。
void PreOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%c ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
对于上图二叉树,前序遍历的结果是 (下一行是程序运行结果)
中序遍历
按照 左子树-根结点-右子树 的顺序遍历树。
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%c ", root->data);
InOrder(root->right);
}
后序遍历
按照 左子树-右子树-根结点 的顺序遍历树。
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%c ", root->data);
}
层序遍历
借助队列实现层序遍历。 1、空树:直接返回 2、树不为空时,把根结点入队列。每次结点出队列,就把这个结点的左右孩子带进队列中。
void BinaryTreeLevelOrder(BTNode* root)
{
if (root == NULL)
{
return NULL;
}
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
QDataType front = QueueFront(&q);
QueuePop(&q);
printf("%c ", front->data);
if (front->left)
{
QueuePush(&q, front->left);
}
if (front->right)
{
QueuePush(&q, front->right);
}
}
QueueDestroy(&q);
}
二叉树结点个数
二叉树结点个数 = 根结点个数+左右子树结点总数
int BinaryTreeSize(BTNode* root)
{
return root == NULL ? 0 :
BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
二叉树叶子节点个数
叶子节点左右孩子都是NULL。 二叉树叶子节点 = 左子树叶子节点 + 右子树叶子节点
int BinaryTreeLeafSize(BTNode* root)
{
if (root == NULL)
{
return 0;
}
if (root->left == NULL && root->right == NULL)
{
return 1;
}
return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}
二叉树第k层结点个数
二叉树第k层结点个数等于左右子树第k-1层结点个数。
int BinaryTreeLevelKSize(BTNode* root, int k)
{
assert(k >= 1);
if (root == NULL)
{
return 0;
}
if (k == 1)
{
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1) +
BinaryTreeLevelKSize(root->right, k - 1);
}
二叉树深度/高度
二叉树深度/高度是左右子树最大高度加一。
int BinaryTreeDepth(BTNode* root)
{
if (root == NULL)
{
return 0;
}
int leftDepth = BinaryTreeDepth(root->left);
int rightDepth = BinaryTreeDepth(root->right);
return fmax(leftDepth, rightDepth) + 1;
}
二叉树查找值为x的节点
先判断根结点是不是值为x的结点,如果不是,去左右子树中查找。
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
if (root == NULL)
return NULL;
if (root->data == x)
return root;
BTNode* leftret = BinaryTreeFind(root->left, x);
if (leftret)
return leftret;
BTNode* rightret = BinaryTreeFind(root->right, x);
if (rightret)
return rightret;
return NULL;
}
判断二叉树是否是完全二叉树
首先要分析得出完全二叉树和一般二叉树的区别。本题基于层序遍历的知识更好理解。
可以得出,完全二叉树在找到NULL时,后面没有元素。 一般二叉树在找到NULL后,后面还会有元素。
bool BinaryTreeComplete(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
QDataType tmp = QueueFront(&q);
QueuePop(&q);
if (tmp == NULL)
{
break;
}
else
{
QueuePush(&q, tmp->left);
QueuePush(&q, tmp->right);
}
}
while (!QueueEmpty(&q))
{
QDataType front = QueueFront(&q);
QueuePop(&q);
if (front)
{
QueueDestroy(&q);
return false;
}
}
QueueDestroy(&q);
return true;
}
二叉树销毁
后序遍历进行销毁。使用前序遍历销毁还要保留root结点,用后序遍历更加遍历。
void BinaryTreeDestory(BTNode* root)
{
if (root == NULL)
return;
BinaryTreeDestory(root->left);
BinaryTreeDestory(root->right);
free(root);
}
|