文章目录
前言
二叉树的顺序结构就是用数组来存储,而「数组」一般只适合表示「满二叉树」或「完全二叉树」,因为不是完全二叉树会有「空间的浪费」。
普通二叉树的增删查改没有意义,主要学习它的结构,要加上搜索树的规则,才有价值。
一、二叉树的链式结构
在学习二叉树的基本操作前,需先要创建一棵二叉树,此处我们手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研究二叉树真正的创建方式。
#include<stdio.h> // perror, printf
#include<stdlib.h> // malloc
typedef char BTDataType;
// 定义二叉树的节点
typedef struct BinaryTreeNode
{
BTDataType data;
struct BinaryTreeNode* left;
struct BinaryTreeNode* right;
}BTNode;
// 动态申请一个新节点
BTNode* BuyNode(BTDataType x)
{
//
BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
if (newnode == NULL)
{
perror("malloc");
exit(-1);
}
newnode->data = x;
newnode->left = newnode->right = NULL;
return newnode;
}
// 二叉树的链式结构
BTNode* CreatBinaryTree()
{
// 创建多个节点
BTNode* node_A = BuyNode('A');
BTNode* node_B = BuyNode('B');
BTNode* node_C = BuyNode('C');
BTNode* node_D = BuyNode('D');
BTNode* node_E = BuyNode('E');
BTNode* node_F = BuyNode('F');
// 用链来指示节点间的逻辑关系
node_A->left = node_B;
node_A->right = node_C;
node_B->left = node_D;
node_C->left = node_E;
node_C->right = node_F;
return node_A;
}
注意:上述代码并不是创建二叉树的方式,真正创建二叉树方式后续讲解。
二、二叉树的遍历方式
1.1 遍历方式的规则
学习二叉树结构,最简单的方式就是遍历。所谓二叉树遍历(Traversal)是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。访问结点所做的操作依赖于具体的应用问题。 遍历是二叉树上最重要的运算之一,也是二叉树上进行其它运算的基础。
按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历 和 层序遍历:
-
前序遍历(Preorder Traversal) :访问根结点的操作发生在遍历其左右子树之前。
根 --> 左子树 --> 右子树
(比如上图中,访问的路径为:A B D NULL NULL NULL C E NULL NULL F NULL NULL)
-
中序遍历(Inorder Traversal) :访问根结点的操作发生在遍历其左右子树之中(间)。
左子树 --> 根 --> 右子树
(比如上图中,访问的路径为:NULL D NULL B NULL A NULL E NULL C NULL F NULL)
计算中序遍历访问路径可以用简单直观的投影法:
-
后序遍历(Postorder Traversal):访问根结点的操作发生在遍历其左右子树之后。
左子树 --> 右子树 --> 根
(比如上图中,访问的路径为:NULL NULL D NULL B NULL NULL E NULL NULL F C A)
-
层序遍历(LevelOrder traversal):一层一层的走
(比如上图中,访问的路径为:A B C D NULL E F NULL NULL NULL NULL NULL NULL)
由于被访问的结点必是「某子树的根」,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。
深度优先遍历:前序、中序、后序
广度优先遍历:层序
【理解前/中/后序遍历的思路】
前中后序遍历中,每一颗