参考了july的非递归解法,一下是自己的代码:
//递归和非递归遍历Tree // 1 // / \ // 2 3 // / \ / \ // 4 5 6 7 //Pre-Order: 1 2 4 5 3 6 7 //In-Order: 4 2 5 1 6 3 7 //Post-Order:4 5 2 6 7 3 1 #include <iostream> #include <cstdio> #include <stack> using namespace std; typedef struct node { int val; struct node *lc; struct node *rc; node(int v1, struct node* _lc, struct node* _rc):val(v1),lc(_lc),rc(_rc){}; }Node; Node* createTree() { Node *n4 = new Node(4,NULL,NULL); Node *n5 = new Node(5,NULL,NULL); Node *n6 = new Node(6,NULL,NULL); Node *n7 = new Node(7,NULL,NULL); Node *n2 = new Node(2,n4,n5); Node *n3 = new Node(3,n6,n7); Node *n1 = new Node(1,n2,n3); return n1; } void preOrder(const Node * p) { if(!p) { return; } printf("%d\n",p->val); preOrder(p->lc); preOrder(p->rc); } void preOrder1(Node *p) { stack<Node*> ns; while(!ns.empty() || p) { while(p) { printf("%d\n",p->val); ns.push(p); p=p->lc; } if(!ns.empty()) { p=ns.top(); ns.pop(); p=p->rc; } } } void inOrder(const Node *p) { if(!p) { return; } inOrder(p->lc); printf("%d\n",p->val); inOrder(p->rc); } void inOrder1(Node *p) { stack<Node*> ns; while(!ns.empty()||p) { while(p) { ns.push(p); p=p->lc; } if(!ns.empty()) { p=ns.top(); printf("%d\n",p->val); ns.pop(); p=p->rc; } } } void postOrder(const Node *p) { if(!p) { return; } postOrder(p->lc); postOrder(p->rc); printf("%d\n",p->val); } void postOrder1(Node *p) { stack<Node *> ns; bool tag[8] = {false}; while(!ns.empty() || p) { while(p) { ns.push(p); p=p->lc; } while(!ns.empty()&&tag[ns.top()->val]==true) { p=ns.top(); printf("%d\n",p->val); ns.pop(); } if(!ns.empty()) { p=ns.top(); tag[p->val]=true; p=p->rc; } else { p=NULL; } } } int main() { Node *root; root=createTree(); printf("preOrder Travel:\n"); preOrder(root); printf("\n\n"); printf("InOrder Travel:\n"); inOrder(root); printf("\n\n"); printf("PostOrder Travel:\n"); postOrder(root); printf("\n\n"); //with stack, non-recursive travel printf("preOrder1 Travel:\n"); preOrder1(root); printf("\n\n"); printf("InOrder1 Travel:\n"); inOrder1(root); printf("\n\n"); printf("PostOrder1 Travel:\n"); postOrder1(root); printf("\n\n"); return 0; }
转自http://blog.csdn.net/v_JULY_v/article/details/6171539
现在,我们可以看二叉树前序遍历的非递归实现了。
按照二叉树前序遍历的定义,无论是访问整棵树还是其子树,均应该遵循先访问根结点,
然后访问根结点的左子树,最后访问根结点的右子树的。
因为对于一棵树(子树)t,如果t非空,访问完t的根结点值后,就应该进入t的左子树,
但此时必须将t保存起来,以便访问完其左子树后,进入其右子树的访问。
yeah,就是这个意思。:)...
即在t处设置一个回溯点,并将该回溯点进栈保存。
在整个二叉树前序遍历的过程中,程序始终要做的工作分成俩个部分:
1.当前正在处理的树(子树)
2.保存在栈中等待处理的部分。
//注:当栈中元素位于栈顶即将出栈时,意味着其根结点和左子树已访问完成,
//出栈后,进入其右子树进行访问,
//前序遍历,非递归实现
//出栈后,进入其右子树进行访问, //前序遍历,非递归实现 void preorderT(bintree t) { seqstack s; s.top=0; while( (t)||(s.top!=0) ) //当前处理的子树不为空或栈不为空 { while(t) //子树不为空 { printf("%c",t->data); //1.先访问根结点 push(&s,t); //2.访问左子树之前,记得先把根结点进栈保存 t=t->lchild; //3.然后才访问左子树, } if(s.top>0) //栈不为空 { t.pop(&s); //4.pop根结点 t=t->rchild; //5.访问右子树 } } } //中序遍历,非递归实现, void inorderT(bintree t) { seqstack s; s.top=0; while( (t)||(s.top!=0) ) //当前处理的子树不为空或栈不为空 { while(t) //子树不为空 { push(&s,t); //1.访问左子树之前,记得先把根结点push进栈 t=t->lchild; //2.访问左子树 } if(s.top!=0) //栈不为空 { t.pop(&s); //3.pop根结点(访问完左子树后) printf("%c",t->data); //4.访问根结点 (把先前保存的t给拿出来,要用了..) t=t->rchild; //5.访问右子树 } } }
//后序遍历,非递归实现
后序遍历的非递归算法,稍微复杂点。请看,
按照二叉树后序遍历的定义,无论是访问整棵树还是起子树,
均应该遵循先访问根结点左子树,然后访问根结点的右子树,最后访问根结点。
值得注意的是,当一个元素位于栈顶即将处理的是,其左子树的访问一定完成,
如果其右子树不为空,接下来应该进入其右子树尽情访问。
//注意了,
但此时该栈顶元素时不能出栈的,因为它作为根结点,其本身的值还未被访问。
只有等到其右子树也访问完成后,该栈顶元素才能出栈,并输出它的值。
因此,在二叉树后序遍历的算法中,必须使用seqstack类型的数组tag,
其每个元素取值为0或1,用于标识栈中每个元素的状态。
1.当一个元素刚进栈时,其对应的tag值置为0;
2.当它位于栈顶即将被处理时,其tag值为0.意味着应该访问其右子树。
于是将右子树作为当前处理的对象,此时该栈顶元素仍应该保留在栈中。
并将其对应的tag值改为1.
3.当其右子树访问完成后,该元素又一次位于栈顶,而此时其tag值为1,
意味着其右子树已访问完成,接下来,应该直接访问的就是它,将其出栈。
void postorderT(bintree t) { seqstack s; s.top=0; while( (t)||(s.top!=0) ) { while(t) { s.data[s.top]=t; s.tag[s.top]=0; //tag置为0 s.top++; t=t->lchild; //访问左子树 } while( (s.top>0)&&(s.tag[s.top-1]==1) ) { s.top--; t=s.data[s.top]; printf("%c",t->data); } if(s.top>0) { t=s.data[s.top-1]; s.tag[s.top-1]=1; t=t->rchild; } else t=NULL; } }