遍历:按照某种次序把所有的结点都访问一遍。
对于一个线性结构a1 a2 a3 a4 a5 对其进行遍历,很简单,可以从前往后遍历,也可以从后往前遍历。
对于树形结构,稍复杂,由于树的结构是一层一层的,所以可以一层一层地访问这些结点,此方法为层次遍历,即基于树的层次特性确定的次序规则。先、中、后序遍历,是基于树的地柜特性制定的遍历规则。(根结点,左子树,右子树)
二叉树的递归特性:①要么是空二叉树②要么是由“根结点+左子树+右子树”组成的二叉树(左右子树也可能是空二叉树)
由此可制定一种遍历规则:当我们要遍历的这个二叉树为空二叉树时,我们什么都不用做;若我们要遍历的是一个非空二叉树,可以根据根结点、左子树、右子树的访问次序来制定三种访问规则,分别是先序遍历、中序遍历、后序遍历。
- 先序遍历:根左右 NLR
- 中序遍历:左根右 LNR
- 后序遍历:左右根 LRN
但是,如果访问到左的时候,左子树又包含其本身的左、根、右,那么限制性玩左子树下一级的先中后遍历后,才能跳出来,当然,其下一级可能又包含下一级,总之要到最深处以及,执行完后,才可以慢慢往外跳转执行。
又称先、中、后根遍历。
分支结点逐层展开法。如果一个结点是分支结点而不是叶子结点,就要嵌套递归地按照特定序列遍历的规则,把它展开到下一级。
①用二叉树存放运算数、操作符等内容,例如算术表达式a+b*(c-d)-e/f的分析树如下:
- 先序遍历-根左右:-+a*b-cd/ef 前缀表达式
- 中序遍历-左根右:a+b*c-d-e/f 中缀表达式
- 后序遍历-左右根:abcd-*+ef/- 后缀表达式
通过例子可知,对某个算术表达式的分析树进行黔中后序遍历,可以得到其前缀、中缀、后缀表达式。
代码:
先序遍历(PreOrder)的操作过程如下:
1.若二叉树为空,则什么也不做;
2.若二叉树非空:
①访问根结点;
②先序遍历左子树
③先序遍历右子树
中序、后序同理。
#include <stdio.h>
#include <stdlib.h>
typedef struct TreeNode {
int val;
struct TreeNode *left, *right;
} TreeNode;
// 创建新节点
TreeNode* newNode(int item) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
node->val = item;
node->left = node->right = NULL;
return node;
}
// 先序遍历
void preorder(TreeNode *node) {
if (node == NULL)
return;
printf("%d ", node->val);
preorder(node->left);
preorder(node->right);
}
// 中序遍历
void inorder(TreeNode *node) {
if (node == NULL)
return;
inorder(node->left);
printf("%d ", node->val);
inorder(node->right);
}
// 后序遍历
void postorder(TreeNode *node) {
if (node == NULL)
return;
postorder(node->left);
postorder(node->right);
printf("%d ", node->val);
}
int main() {
// 构建一个简单的二叉树,形式如下:
// 1
// / \
// 2 3
// /
// 4
TreeNode *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
printf("先序遍历: ");
preorder(root);
printf("\n");
printf("中序遍历: ");
inorder(root);
printf("\n");
printf("后序遍历: ");
postorder(root);
printf("\n");
return 0;
}
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
//先序遍历
void PreOrder(BiTree T){
if (T!=NULL){
visit(T);//访问根结点
PreOrder(T->lchild);//递归调用左子树的先序遍历
PreOrder(T->rchild);//递归调用右子树的先序遍历
}
}
//中序遍历
void InOrder(BiTree T){
if (T!=NULL){
InOrder(T->lchild);
visit(T);//访问根结点
InOrder(T->rchild);
}
}
//后序遍历
void PostOrder(BiTree T){
if (T!=NULL){
PostOrder(T->lchild);
PostOrder(T->rchild);
visit(T);//访问根结点
}
}