史上最简明易懂非递归遍历二叉树算法

巧若拙(欢迎转载,但请注明出处:http://blog.csdn.net/qiaoruozhuo)

遍历二叉树的递归函数是体现了算法之美的高妙算法,思路清晰,代码简洁,读之赏心悦目。代码例如以下:

程序代码:

void PreOrderTraverse_R(BiTree BT)//採用递归方式先序遍历二叉树BT

{

if(BT != NULL)

{

printf("%c", BT->data);//输出该结点(根结点)

PreOrderTraverse_R(BT->lchild);  //遍历左子树

PreOrderTraverse_R(BT->rchild);//遍历右子树

}

}

void InOrderTraverse_R(BiTree BT)//採用递归方式中序遍历二叉树BT

{

if(BT != NULL)

{

InOrderTraverse_R(BT->lchild);  //遍历左子树

printf("%c", BT->data);//输出该结点(根结点)

InOrderTraverse_R(BT->rchild);//遍历右子树

}

}

void PostOrderTraverse_R(BiTree BT)//採用递归方式后序遍历二叉树BT

{

if(BT != NULL)

{

PostOrderTraverse_R(BT->lchild);  //遍历左子树

PostOrderTraverse_R(BT->rchild);//遍历右子树

printf("%c", BT->data);//输出该结点(根结点)

}

}

相较之下,大部分流传的非递归遍历二叉树算法语言晦涩,面目可憎,尽管利用了栈数据结构来模拟递归遍历过程,但思路和表达形式上未能与递归算法相应起来,造成刚開始学习的人理解上的困惑。假设可以将非递归算法和递归算法相互相应,则可大慷慨便刚開始学习的人理解二者间的等效性。

我们知道,编译器在调用函数时会分配一个栈空间,以存储必要信息,假设该函数调用了别的函数,其栈空间会一直保留,直到该函数最后一条语句运行完成,才会释放其栈空间。在模拟非递归算法的时候,我们须要手工分配和释放栈空间。

三种不同的遍历方式差别在于栈空间的释放时机和输出结点信息时机的不同:先序和中序遍历是在訪问栈顶元素的右孩子(右子树)之前退栈,而后序遍历在訪问右子树之后退栈;先序遍历是在某结点入栈时输出其信息,而中序和后序遍历是在该结点退栈时输出其信息。

不管是递归算法还是非递归算法,都遵循上述规则,二者能够一一相应。图演示样例如以下:

附录:非递归算法代码例如以下:

void PreOrderTraverse_S(BiTree BT)//採用非递归方式先序遍历二叉树BT

{

BiTreep, stack[MAXSIZE];//p表示当前结点,栈stack[]用来存储结点

inttop = -1; //栈空

if(BT != NULL)//先推断是否为空树

{

p = BT;

while (p || top >= 0)

{

if (p != NULL) //先输出结点数据,再遍历左孩子

{

printf("%c",p->data);//输出该结点

stack[++top] = p;

p = p->lchild;

}

else

{

p = stack[top--]->rchild; //訪问栈顶元素右孩子,并退栈

}

}

}

}

void InOrderTraverse_S(BiTree BT)//採用非递归方式中序遍历二叉树BT

{

BiTreep, stack[MAXSIZE];//p表示当前结点,栈stack[]用来存储结点

inttop = -1; //栈空

if(BT != NULL)//先推断是否为空树

{

p = BT;

while (p || top >= 0)

{

if (p != NULL)//首先訪问左子树

{

stack[++top] = p;

p = p->lchild;

}

else

{

printf("%c",stack[top]->data);//输出栈顶元素

p = stack[top--]->rchild; //訪问栈顶元素右孩子,并退栈

}

}

}

}

void PostOrderTraverse_S(BiTree BT)//採用非递归方式后序遍历二叉树BT

{

BiTreep, stack[MAXSIZE];//p表示当前结点,栈stack[]用来存储结点

inttag[MAXSIZE] = {0}; //用来标志栈顶元素的右孩子是否被訪问过,0表示未訪问,1表示已訪问

inttop = -1; //栈空

if(BT != NULL)//先推断是否为空树

{

p = BT;

while (p || top >= 0)

{

if (p != NULL) //首先訪问左子树

{

stack[++top] = p;

tag[top] = 0;

p = p->lchild;

}

else if (tag[top] == 0) //若右子树尚未訪问,訪问栈顶元素右孩子,并做好标记

{

p= stack[top]->rchild;

tag[top]= 1;

}

else//否则输出栈顶元素并退栈

{

printf("%c",stack[top--]->data);

}

}

}

}

时间: 2025-01-14 23:10:47

史上最简明易懂非递归遍历二叉树算法的相关文章

【转】更简单的非递归遍历二叉树的方法

解决二叉树的很多问题的方案都是基于对二叉树的遍历.遍历二叉树的前序,中序,后序三大方法算是计算机科班学生必写代码了.其递归遍历是人人都能信手拈来,可是在手生时写出非递归遍历恐非易事.正因为并非易事,所以网上出现无数的介绍二叉树非递归遍历方法的文章.可是大家需要的真是那些非递归遍历代码和讲述吗?代码早在学数据结构时就看懂了,理解了,可为什么我们一而再再而三地忘记非递归遍历方法,却始终记住了递归遍历方法? 三种递归遍历对遍历的描述,思路非常简洁,最重要的是三种方法完全统一,大大减轻了我们理解的负担.

JAVA递归、非递归遍历二叉树(转)

原文链接: JAVA递归.非递归遍历二叉树 import java.util.Stack; import java.util.HashMap; public class BinTree { private char date; private BinTree lchild; private BinTree rchild; public BinTree(char c) { date = c; } // 先序遍历递归 public static void preOrder(BinTree t) {

重拾算法(1)——优雅地非递归遍历二叉树及其它

重拾算法(1)——优雅地非递归遍历二叉树及其它 本文中非递归遍历二叉树的思想和代码都来自这里(http://jianshu.io/p/49c8cfd07410#).我认为其思想和代码都足够优雅动人了,于是稍作整理,得到如下的程序. 前中后序遍历二叉树 1 public class BinaryTreeNode<T> 2 { 3 public T Value { get;set; } 4 public BinaryTreeNode<T> Parent { get;set; } 5 p

非递归遍历二叉树Java实现

2018-10-03 20:16:53 非递归遍历二叉树是使用堆栈来进行保存,个人推荐使用双while结构,完全按照遍历顺序来进行堆栈的操作,当然在前序和后序的遍历过程中还有其他的压栈流程. 一.Binary Tree Preorder Traversal 问题描述: 问题求解: 先序遍历就是在第一次访问到节点的时候将其值进行打印,然后递归打印其左子树,最后递归打印其右子树. 解法一.双while public List<Integer> preorderTraversal(TreeNode

非递归遍历二叉树的前序中序后序

/** * 二叉树先序遍历,非递归算法 * 1.申请一个新的栈,记为stack.然后将头节点head压入stack中. * 2.从stack弹出栈顶节点,记为cur,然后打印cur节点的值,再将cur右孩子(不为空) * 压入stack中,最后将cur的左孩子(不为空)压入stack中 * 3.不断重复步骤2,直到stack为空,全部过程结束. * @param head */ public void preOrderNoRecur(Node head){ System.out.print("非

非递归遍历二叉树之中序遍历

//中序遍历int inorder_tree_walk(BinTreeNode * root){ if(root == NULL){ return -1; } stack<BinTreeNode *> s; BinTreeNode * p = root; while(!s.empty() || p != NULL) { while(p != NULL){ s.push(p); p = p->lchild; } p = s.top(); s.pop(); cout << p-&

非递归遍历二叉树之前序遍历

前序遍历二叉树 int preorder_tree_walk(BinTreeNode * root){ if(root == NULL){ return -1; } stack<BinTreeNode *> s; BinTreeNode * p = root; while(!s.empty() || p != NULL) { while(p != NULL){ cout << p->key<< endl; s.push(p); p = p->lchild;

非递归遍历二叉树

#include <stack> #include <stdio.h> #include <malloc.h> #include <iostream> using namespace std; typedef struct node { int flag; char value; struct node *lchild; struct node *rchild; }Node, *PNode; void CreateBinaryTree(PNode &

非递归遍历二叉树【层次遍历,先序、中序、后序遍历】

一.层次遍历:借助队列实现 1 void LevelOrderTraversal(BiTree root) 2 { 3 BiTree e = root;//从根节点开始 4 Queue *q; 5 InitQueue(q); 6 7 if(e)//若根结点非空,则入队列 8 { 9 EnQueue(q,e); 10 } 11 12 while(!QueueEmpty(q)) 13 { 14 DelQueue(q,e); 15 Visit(e); 16 if(e->leftChild)//左孩子不