二叉树的遍历
所谓二叉树的遍历是直观的感受二叉树结构的最简单的方法。
利用某种规则对二叉树中的每一个结点都进行相应操作。
在此主要介绍四种遍历方式:
- 前序遍历
前序遍历就是由根开始的先左再右的循环结构。
具体可表现为:
其最终遍历结果为:A B D H I E J C F K G
- 中序遍历
中序遍历实际上就是一种树结构投影到一条线上的投影
最终遍历结果为:H D I B J E A F K C G
- 后序遍历
我们可以将后序遍历理解为摘果子,先摘矮的好摘的再摘高的。即先左右再根。
最终遍历结果为:H I D J E B K F G C A
- 层序遍历
顾名思义层序就是按层的顺序遍历。
最终遍历结果为:A B C D E F G H I J K
程序如下:
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root){
if (root == NULL){
return ;
}
printf("%c ", root->data);
BinaryTreePrevOrder(root->left);
BinaryTreePrevOrder(root->right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root){
if (root == NULL){
return ;
}
BinaryTreeInOrder(root->left);
printf("%c ", root->data);
BinaryTreeInOrder(root->right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root){
if (root == NULL){
return ;
}
BinaryTreePostOrder(root->left);
BinaryTreePostOrder(root->right);
printf("%c ", root->data);
}
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root){
if (root == NULL){
return ;
}
//利用队列实现遍历
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q)){
BTNode* tmp = QueueFront(&q);
printf("%c ", tmp->data);
QueuePop(&q);
if (tmp->left){
QueuePush(&q, tmp->left);
}
if (tmp->right){
QueuePush(&q, tmp->right);
}
}
QueueDestroy(&q);
}
二叉树链式结构的实现
在了解遍历后二叉树的实现也就水到渠成。
结点的定义以及函数声明:
typedef char BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, BTDataType x);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
节点的申请:
BTNode* BuyNode(BTDataType cur){
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
if (!newnode){
assert(0);
return NULL;
}
newnode->data = cur;
newnode->left = NULL;
newnode->right = NULL;
return newnode;
}
二叉树的构建
利用前序遍历来创建二叉树
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* _BinaryTreeCreate(BTDataType* a, int n, int* pi,BTDataType x){
BTNode* root = NULL;
if (a[*pi] == x){
return NULL;
}
if ((*pi) < n){
root = BuyNode(a[*pi]);//创建根节点
//创建左子树(通过递归)
(*pi)++;
root->left = _BinaryTreeCreate(a, n, pi, x);
//创建右子树
(*pi)++;
root->right = _BinaryTreeCreate(a, n, pi, x);
}
return root;
}
BTNode* BinaryTreeCreate(BTDataType* a, int n, BTDataType x){
int pi = 0;
return _BinaryTreeCreate(a, n, &pi, x);
}
二叉树实现部分操作的代码展示:
//申请结点
BTNode* BuyNode(BTDataType cur){
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
if (!newnode){
assert(0);
return NULL;
}
newnode->data = cur;
newnode->left = NULL;
newnode->right = NULL;
return newnode;
}
// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* _BinaryTreeCreate(BTDataType* a, int n, int* pi,BTDataType x){
BTNode* root = NULL;
if (a[*pi] == x){
return NULL;
}
if ((*pi) < n){
root = BuyNode(a[*pi]);//创建根节点
//创建左子树(通过递归)
(*pi)++;
root->left = _BinaryTreeCreate(a, n, pi, x);
//创建右子树
(*pi)++;
root->right = _BinaryTreeCreate(a, n, pi, x);
}
return root;
}
BTNode* BinaryTreeCreate(BTDataType* a, int n, BTDataType x){
int pi = 0;
return _BinaryTreeCreate(a, n, &pi, x);
}
// 二叉树销毁
void BinaryTreeDestory(BTNode** root){
if (*root == NULL)
return;
BinaryTreeDestory(&(*root)->left);
BinaryTreeDestory(&(*root)->right);
free(*root);
*root = NULL;
}
// 二叉树节点个数
int BinaryTreeSize(BTNode* root){
if (root == NULL)
return 0;
return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
// 二叉树叶子节点个数
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);
}
//树的高度
int BinaryHeight(BTNode* root){
if (root == NULL)
return 0;
return BinaryHeight(root->left) > BinaryHeight(root->right) ? BinaryHeight(root->left) + 1 : BinaryHeight(root->right) + 1;
}
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k){
assert(root);
assert(k);
if (k == 1){
return 1;
}
return BinaryTreeLevelKSize(root->left, k - 1) + BinaryTreeLevelKSize(root->right, k - 1);
}
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x){
if (root == NULL){
return NULL;
}
if (root->data == x){
return root;
}
if ( BinaryTreeFind(root->left, x)){
return BinaryTreeFind(root->left, x);
}
return BinaryTreeFind(root->right, x);
}
// 二叉树前序遍历
void BinaryTreePrevOrder(BTNode* root){
if (root == NULL){
return ;
}
printf("%c ", root->data);
BinaryTreePrevOrder(root->left);
BinaryTreePrevOrder(root->right);
}
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root){
if (root == NULL){
return ;
}
BinaryTreeInOrder(root->left);
printf("%c ", root->data);
BinaryTreeInOrder(root->right);
}
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root){
if (root == NULL){
return ;
}
BinaryTreePostOrder(root->left);
BinaryTreePostOrder(root->right);
printf("%c ", root->data);
}
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root){
if (root == NULL){
return ;
}
//利用队列实现遍历
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q)){
BTNode* tmp = QueueFront(&q);
printf("%c ", tmp->data);
QueuePop(&q);
if (tmp->left){
QueuePush(&q, tmp->left);
}
if (tmp->right){
QueuePush(&q, tmp->right);
}
}
QueueDestroy(&q);
}
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root){
Queue q;
QueueInit(&q);
QueuePush(&q,root);
int flag = 0;
while (QueueEmpty(&q)){
BTNode* tmp = QueueFront(&q);
QueuePop(&q);
if (tmp == NULL){
flag = 0;
}
if (flag&&tmp){
QueueDestroy(&q);
return false;
}
if (tmp){
QueuePush(&q, tmp->left);
QueuePush(&q, tmp->right);
}
}
QueueDestroy(&q);
return true;
}
本片中还用到了队列的代码下附队列篇的理解:队列