【数据结构】二叉树——前中后序遍历
一、如何遍历二叉树
以图上这个二叉树作为例子,我们若想要访问二叉树中每一个元素
我们一般是采用递归的方式
比如我们要访问完整个二叉树,我们进行递归先访问根的左子树,然后因为递归再次调用,我们会先一直访问二叉树左子树,直到为空时返回,再访问右子树进行递归直到将整棵二叉树访问完毕
以上图为例:
• 我们若想访问整个二叉树
•
• 从 B 开始,我们访问左子树,访问到 D
• 从 D 开始,我们访问左子树,访问到 NULL
• 返回
• 从 D 开始,我们访问右子树,访问到 NULL
• 返回
•
• D 的左右两子树都以访问完毕,返回
•
• 对于 B 来说左子树已经访问完毕,接下来访问 B 的右子树
•• 从 B 开始,我们访问右子树,访问到 E
• 从 E 开始,我们访问左子树,访问到 NULL
• 返回
• 从 E 开始,我们访问右子树,访问到 H
• 从 H 开始,我们访问左子树,访问到 NULL
• 返回
• 从 H 开始,我们访问右子树,访问到 NULL
• 返回
• H 的左右子树已经访问完毕,返回
• E 的左右子树已经访问完毕,返回
• B 的左右子树已经访问完毕
• 至此整个二叉树访问完毕
二、什么是二叉树的前中后序遍历
所谓的前中后序遍历其实就是我们访问二叉树时读取数据的顺序
我们在访问数据时我们可以选择将该节点的数据取出来,或者接着向下遍历,我们取出节点数据在遍历过程的顺序就是前中后序
我们先手搓一个如上图的二叉树
1、二叉树节点
一个二叉树节点中存储三个信息
val : 用于存储节点的数据,可以是不同的数据类型
left : 用于存储左子树节点的地址
right : 用于存储右子树节点的地址
2、二叉树节点初始化
3、手搓二叉树
接下来我们按照下图二叉树,手搓一个二叉树
BTNode* node1 = BTInit('A');
BTNode* node2 = BTInit('B');
BTNode* node3 = BTInit('C');
BTNode* node4 = BTInit('D');
BTNode* node5 = BTInit('E');
BTNode* node6 = BTInit('F');
BTNode* node7 = BTInit('G');
BTNode* node8 = BTInit('H');
//BTNode* node9 = BTInit('t');node1->left = node2;
node1->right = node3;
node2->left = node4;
node2->right = node5;
node3->left = node6;
node3->right = node7;
node5->right = node8;
//node8->left = node9;
4、前序遍历
//遍历二叉树(前序遍历)
void BTPrevOrder(BTNode* pbt)
{if (pbt == NULL){printf("# ");return;}printf("%c ", pbt->val);BTPrevOrder(pbt->left);BTPrevOrder(pbt->right);
}
前序遍历,我们每次访问到一个节点就将它打印出来,然后先向左子树递归,再向右子树递归
5、中序遍历
//遍历二叉树(中序遍历)
void BTInOrder(BTNode* pbt)
{if (pbt == NULL){printf("# ");return;}BTInOrder(pbt->left);printf("%c ", pbt->val);BTInOrder(pbt->right);
}
我们发现中序遍历与前序遍历的不同就只在打印的数值的位置不同,中序遍历就相当于先向左一直递归,但是不打印数据,当节点的左子树被访问完后,再访问根节点,然后再访问右子树
6、后序遍历
//遍历二叉树(后序遍历)
void BTPostOrder(BTNode* pbt)
{if (pbt == NULL){printf("# ");return;}BTPostOrder(pbt->left);BTPostOrder(pbt->right);printf("%c ", pbt->val);
}
后序遍历就是再左右子树都访问完后再打印数据