一直想要写的 二叉树 中序 先序 后序遍历算法
当年学习DS最虚的就是这个,因为非递归算法复杂,测试数据不好弄,只能一个一个手动插入。感觉明显比图的难,虽然大家都觉得图更难。。。。。
递归的太简单了,就不写了。关键是非递归版本。
先序:
我自己的版本:
void RootPreTraverse(Node* p) { Stack S; while(S not empty) { p=S.top(); S.pop(); Show(p); if(p->right!=null) S.push(p->right); if(p->left!=null) S.push(p->left); } }
后来发现和层序遍历有点相似,区别就在于 用了栈而不是队列,而且入的顺序换一换,否则到时出栈就错了。
感觉有点微妙,虽然比较容易写出来,但是还是有点悬乎,队列换栈差异这么大!
网上版本(感觉不好写) www.cppblog.com/ngaut/archive/2006/01/01/2351.aspx
void BT_PreOrderNoRec(pTreeT root) { stack<treeT *> s; while ((NULL != root) || !s.empty()) { if (NULL != root) { visit(root); s.push(root); root = root->left; } else //该版本代码相比于下面比较清sang, { root = s.top(); s.pop(); root = root->right; } } }
下面这个和上面是一个思路 blog.csdn.net/fansongy/article/details/6798278
void preorder_dev(bintree t){ seqstack s; s.top = -1; //因为top在这里表示了数组中的位置,所以空为-1 if(!t){ printf("the tree is empty\n"); }else{ while(t || s.stop != -1){ while(t){ //只要结点不为空就应该入栈保存,与其左右结点无关 printf("%c ",t->data); push(&s,t); t= t->lchild; } //令有一个版本http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html,这里加了判断if(S not empty()), 感觉有点画蛇添足。因为此处如果栈为空则说明上面while 一定没执行,t为空,同时S empty()那么上一次外层while已经退出了,遍历结束了。可见,此处栈必不空,上面url楼主加了一个永真判断 t=pop(&s); t=t->rchild; } } }
中序:www.cppblog.com/ngaut/archive/2006/01/01/2351.aspx
void BT_InOrderNoRec(pTreeT root) { stack<treeT *> s; while ((NULL != root) || !s.empty()) { if (NULL != root) { s.push(root); root = root->left; } else { root = s.top(); visit(root); s.pop(); root = root->right; } } }
//和上面preorder_dev 几乎如出一辙,从一个show 的地方就可以看出本质区别,赞博主
void midorder(bintree t){ seqstack s; s.top = -1; if(!t){ printf("the tree is empty!\n"); }else{ while(t ||s.top != -1){ while(t){ push(&s,t); t= t->lchild; } t=pop(&s); printf("%c ",t->data); t=t->rchild; } } }
后序由于有点复杂,先搁置,集中力量打击主要部分。
从逻辑上看,两人其实是一样的,如果t不空,执行if,到while 因此次数if 等价于里面执行while,如果t空,则执行else,与另一个代码一致
另外某博客写的
blog.csdn.net/shunrei/article/details/5680579#reply
递归转非递归的模式其实不大general。。所以这个还得暂时没有通用方法。。。
<pre name="code" class="cpp">将初始状态s0进栈 while (栈不为空) { 退栈,将栈顶元素赋给s; if (s是要找的结果) 返回; else { 寻找到s的相关状态s1; 将s1进栈 } }
后序
//用一个标志位记录是否 左右孩子是否已经被压过栈,如果压过栈了,如果没压栈,会先压站,然后再把该节点压站,因为后面
还要访问(后序),此外还需要把标志位
void PostOrder(TNode* root) { Stack S; if( root != NULL ) { S.push(root); } while ( !S.empty() ) { TNode* node = S.pop(); if ( node->bPushed ) { // 如果标识位为true,则表示其左右子树都已经入栈,那么现在就需要访问该节点了 Visit(node); } else { // 左右子树尚未入栈,则依次将 右节点,左节点,根节点 入栈 if ( node->right != NULL ) { node->right->bPushed = false; // 左右子树均设置为false S.push(node->right); } if ( node->left != NULL ) { node->left->bPushed = false; S.push(node->left); } node->bPushed = true; // 根节点标志位为true S.push(node); } } }
http://www.cnblogs.com/baiyanhuang/archive/2011/02/12/1947435.html
这篇还没看完,mark