目录
前言
通过前面关于二叉树的基础知识我们知道链式二叉树分为二叉链和三叉链,本篇主要讲的是二叉链的实现,在此之前,为了方便实现链式二叉树的各个功能,我们需要先手动快速创建一个链式二叉树。
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType _data;
struct BinaryTreeNode* _left;
struct BinaryTreeNode* _right;
}BTNode;
BTNode* CreatBinaryTree()
{
BTNode* node1 = BuyNode(1);
BTNode* node2 = BuyNode(2);
BTNode* node3 = BuyNode(3);
BTNode* node4 = BuyNode(4);
BTNode* node5 = BuyNode(5);
BTNode* node6 = BuyNode(6);
node1->_left = node2;
node1->_right = node4;
node2->_left = node3;
node4->_left = node5;
node4->_right = node6;
return node1;
}
注意:上述代码并不是创建二叉树的方式,这里只是图方便。
这里再把创建的链式二叉树的头文件放在这里,包含了链式二叉树所需的头文件以及需要实现的函数功能
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
// 构建一个简单的二叉树
BTNode* BinaryTreeCreate();
// 二叉树销毁
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);
// 判断二叉树是否是完全二叉树
bool BinaryTreeComplete(BTNode* root);
一、链式二叉树的遍历
学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历是按照某种特定的规则,依次对二叉 树中的结点进行相应的操作,并且每个结点只操作一次,访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:
1. 前序遍历(亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
2. 中序遍历——访问根结点的操作发生在遍历其左右子树之中。
3. 后序遍历——访问根结点的操作发生在遍历其左右子树之后。
1.1 前序遍历
void BinaryTreePrevOrder(BTNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
printf("%d ", root->data);
BinaryTreePrevOrder(root->left);
BinaryTreePrevOrder(root->right);
}
这里写了个打印N的代码是为了方便看到空节点,能更好的理解前序遍历。
图解
前序遍历的内核思想就是递归(准确来说二叉树遍历的思想都是基于递归),前序遍历的顺序是先从根节点开始遍历,找到根节点后开始向下寻找(先是找左子树的根节点再是右子树),左子树根节点找完后,接下来就是左子树中的左节点再就是右节点,找完左子树在以同样的顺序在右子树中进行一遍,总之就是 根->左子树->右子树 按照这样一个顺序来。
1.2 中序遍历
void BinaryTreeInOrder(BTNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
BinaryTreeInOrder(root->left);
printf("%d ", root->data);
BinaryTreeInOrder(root->right);
}
前面说了几个遍历的思想其实差不多,中序遍历就是按照 左子树->根->右子树 的顺序来遍历二叉树的,跟前面的前序遍历是一个逻辑,这里就不赘述了。
1.3 后序遍历
void BinaryTreePostOrder(BTNode* root)
{
if (root == NULL)
{
printf("N ");
return;
}
BinaryTreePostOrder(root->left);
BinaryTreePostOrder(root->right);
printf("%d ", root->data);
}
左子树->根->右子树
同一数据,各个遍历的结果
二、层序遍历
这里把层序遍历和前面三个遍历分开讲是因为,这个遍历和之前的不是同种遍历,前面三个遍历和层序遍历的底层思想是不一样的。
层序遍历:除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历。设二叉树的根结点所在 层数为1,层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后从左到右访问第2层 上的结点,接着是第三层的结点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。
层序遍历的实现需要用到前面队列的知识,忘了的可以看下这里(队列)
void BinaryTreeLevelOrder(BTNode* root)
{
Queue a;
QueueInit(&a);
if(root)
QueuePush(&a, root);
while (!QueueEmpty(&a))
{
BTNode* f = QueueFront(&a);
QueuePop(&a);
printf("%d ", f->data);
if (f->left)
QueuePush(&a, f->left);
if (f->right)
QueuePush(&a, f->right);
}
QueueDestroy(&a);
}
先以二叉树的最上层根节点创建一个队列, 用一个指针指向这个根节点,打印完后出队列,将这个根节点的左节点和右节点分别入队列,再先以左节点为新的根节点重复上述操作,再是右节点,这样一层遍历完了,再重复直到没有节点为止。
层序遍历的结果就是每层的数字按照顺序打印
本篇内容就先到这里,剩下的内容会在下一篇讲解。
标签:结点,遍历,BTNode,二叉树,链式,数据结构,root,节点 From: https://blog.csdn.net/2401_86551514/article/details/141136059