文章目录
- 前言
- 一、 链式二叉树结构创建
- 二、 手动创建二叉树
- 三、遍历二叉树
- 1. 前序遍历
- 2. 中序遍历
- 3. 后序遍历
- 4. 层序遍历
- 四、二叉树的元素个数
- 五、二叉树的高度(深度)
- 六、第K层元素个数
- 总结
前言
堆结构的实现采用的是数组实现二叉树,可以达到很好的效果。但是这种情况是基于满二叉树或者完全二叉树的情况,遇到非完全二叉树的情况,无法很好的实现,因此我们采用链式二叉树。
一、 链式二叉树结构创建
链式二叉树结构的创建
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
- 每个节点都是由本节点的数据和左子树根元素的地址及右子树根元素的地址组成的。
因为普通链式二叉树的增删改查意义不大,所以我们只研究堆普通链式二叉树的遍历。
二、 手动创建二叉树
手动创建二叉树定义
- 创建一个申请节点的函数,每次申请节点的同时,初始化本节点。data为传入参数值,left 及 right 都置为空。
- 创建一个创建链式二叉树的函数,将每个节点的左右指针指向调整合适。
BTNode* BuyNode(BTDataType* x)
{
BTNode* node = (BTNode*)malloc(sizeof(BTNode));
if (node == NULL)
{
perror("BuyNode malloc");
return NULL;
}
node->data = x;
node->left = NULL;
node->right = NULL;
return node;
}
BTNode* CreateTree()
{
BTNode* node1 = BuyNode(1);
BTNode* node2 = BuyNode(2);
BTNode* node3 = BuyNode(3);
BTNode* node4 = BuyNode(4);
BTNode* node5 = BuyNode(5);
BTNode* node6 = BuyNode(6);
BTNode* node7 = BuyNode(7);
node1->left = node2;
node1->right = node4;
node2->left = node3;
node4->left = node5;
node4->right = node6;
node3->right = node7;
return node1;
}
int main()
{
BTNode* root = CreateTree();
return 0;
}
- 因为不研究普通链式二叉树的增删改查,所以手动创建一个链式二叉树。按下图创建。
三、遍历二叉树
- 遍历链式二叉树有4中方式(前序遍历,中序遍历,后序遍历,层序遍历),前三种均为递归遍历,第4种为非递归遍历。
1. 前序遍历
- 遍历顺序
- 前序遍历的顺序是 根元素 左子树 右子树。
前序遍历定义
// 前序遍历
void PreOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
printf("%d ", root->data);
PreOrder(root->left);
PreOrder(root->right);
}
- 递归的思想:
- 每个节点都是按照 根元素 左子树 右子树的顺序遍历。
- 每个函数内部都只打印本节点数据。
前序遍历测试
int main()
{
BTNode* root = CreateTree();
PreOrder(root);
printf("\n");
return 0;
}
效果如下
2. 中序遍历
- 遍历顺序:
- 中序遍历的顺序是 左子树 根元素 右子树。
中序遍历定义
// 中序遍历
void InOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
InOrder(root->left);
printf("%d ", root->data);
InOrder(root->right);
}
- 递归的思想:
- 每个节点都按照 左子树 根元素 右子树的顺序遍历。
- 每个函数内部都只打印本节点的数据。
中序遍历测试
int main()
{
BTNode* root = CreateTree();
InOrder(root);
printf("\n");
return 0;
}
效果如下:
3. 后序遍历
- 遍历的顺序:
- 后序遍历的顺序是 左子树 右子树 根元素
后序遍历定义
// 后序遍历
void PostOrder(BTNode* root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
PostOrder(root->left);
PostOrder(root->right);
printf("%d ", root->data);
}
递归的思想:
- 每个节点都是按照 左子树 右子树 根元素的顺序遍历。
- 每个函数内部都只打印本节点数据。
后序遍历测试
int main()
{
BTNode* root = CreateTree();
PostOrder(root);
printf("\n");
return 0;
}
效果如下:
4. 层序遍历
- 遍历的顺序:
- 一层一层遍历。
层序遍历定义
// 层序遍历
void LevelOrder(BTNode* root)
{
Queue q;
// 初始化队列
QInit(&q);
if (root)
QPush(&q, root);
while (!QEmpty(&q))
{
BTNode* front = QFront(&q);
QPop(&q);
printf("%d ", front->data);
if (front->left)
QPush(&q, front->left);
if (front->right)
QPush(&q, front->right);
}
// 销毁队列
QDestroy(&q);
}
- 思想:
- 使用队列,每个队列的节点数据类型都是二叉树节点(BTNode*);
- 如若不是空节点就入队列。
- 队列不为空,不断地出队列,若此节点的左右子树根节点都不是空,则将子树根节点入队列。
- 简单来说就是,出上一层,带入下一层。
层序遍历测试
int main()
{
BTNode* root = CreateTree();
LevelOrder(root);
return 0;
}
效果如下:
四、二叉树的元素个数
- 递归的思想:
- 每个二叉树节点都是 左子树的节点数量 + 右子树的节点数量 + 1。
- 如若节点为空,则返回0。
二叉树的元素个数定义
// 树的元素个数
int TreeSize(BTNode* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
二叉树的元素个数测试
int main()
{
BTNode* root = CreateTree();
int ret = TreeSize(root);
printf("TreeSize:%d\n", ret);
return 0;
}
效果如下:
五、二叉树的高度(深度)
二叉树的高度定义
- 递归的思想:
- 每个节点元素的高度等于本节点左右子树中高度较大的值 + 1。
- 若节点为空,则返回0。(相当于空树返回0)。
// 树的高度
int TreeHeight(BTNode* root)
{
if (root == NULL)
return 0;
int leftHeight = TreeHeight(root->left);
int rightHeight = TreeHeight(root->right);
return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
}
二叉树的高度测试
int main()
{
BTNode* root = CreateTree();
int ret = TreeHeight(root);
printf("TreeHeight: %d\n", ret);
return 0;
}
效果如下:
六、第K层元素个数
第K层元素个数定义
- 递归的思想:
- 一个节点K层元素的个数,相当于左右子树的的 k-1 层的元素个数的和。
- 若节点为空则返回0。(相当于空树,没有元素)。
- 若层数为 1 则返回1, (相当于根节点在1层,只有 1 个)。
// 第K层元素个数
int TreeKLevel(BTNode* root, int k)
{
assert(k > 0);
if (root == NULL)
{
return 0;
}
if (k == 1)
return 1;
int leftK = TreeKLevel(root->left, k - 1);
int rightK = TreeKLevel(root->right, k - 1);
return leftK + rightK;
}
第K层元素个数测试
int main()
{
BTNode* root = CreateTree();
ret = TreeKLevel(root, 3);
printf("TreeKLevel: %d\n", ret);
return 0;
}
效果如下:
总结
C语言链式二叉树、链式二叉树结构的创建、前序遍历、中序遍历、后序遍历、层序遍历来遍历二叉树、二叉树的元素个数、二叉树的高度、第K层元素的个数等的介绍