二叉树的递归遍历实现起来比较简单,而且代码简洁;而非递归遍历则不那么简单,我们需要借助另一种数据结构---栈来实现。二叉树的遍历又可以分为前序、中序和后序三种,它们是按照根结点在遍历时的位置划分的,前序遍历则根结点先被遍历,中序则根结点在左右叶子节点之间被遍历,后序则是根结点最后被遍历。三种非递归遍历中,前序和中序都不是太复杂,而后序遍历则相对较难。
一、前序遍历
我们这里前序遍历按照“根-左-右”的顺序来遍历。这里按照”递归--非递归“的次序来研究,之后的几种亦是如此。
1、递归的实现:
void travel_3(node* r) {
if (r != NULL) {
cout << r->key << ' ';
travel_3(r->left);
travel_3(r->right);
}
}
2、非递归的实现:
非递归的实现中肯定是需要用到循环结构的,前序遍历又要求先根后左然后右,所以我们肯定是首先需要遍历左节点的,但是遍历左节点之后还需要我们继续遍历右节点,而且右节点也有可能还有左子树需要先遍历。于是乎,这里我们需要一个栈来保存我们已经遍历完的节点,在遍历完左右的左节点之后,再将栈里保存的节点出栈,然后再遍历节点的右子树,然后将右子树的节点带入循环中,这样比较底层的节点会靠近栈顶,也会被先出栈,如此就可以实现非递归的前序遍历。具体步骤如下:
①先输出节点的值,然后将节点入栈
②然后判断节点的左子节点是否为空,如果不为空,则继续循环①;如果为空,则证明这一条线路上的节点值已经被遍历完了,则跳出循环进行出栈操作,只要栈不为空,则节点出栈,并让节点等于他的右子节点,继续进行①号循环
③直到所有节点都已经出栈,且循环到节点为空,则遍历结束
void travel_4(node* r) {
if (r != NULL) {
stack<node*> s;
while (r != NULL || !s.empty()) {
while (