C++编程练习(17)----“二叉树非递归遍历的实现“
2014-05-15 17:58
375 查看
二叉树的非递归遍历
最近看书上说道要掌握二叉树遍历的6种编写方式,之前只用递归方式编写过,这次就用非递归方式编写试一试。C++编程练习(8)----“二叉树的建立以及二叉树的三种遍历方式“(前序遍历、中序遍历、后续遍历)
递归的思想也就是栈的思想,既然不用递归,那就改用栈的方式。
“递归=栈”
1、前序遍历
前序遍历按照“根结点-左孩子-右孩子”的顺序进行访问。a)递归实现前序遍历:
void PreOrderTraverse(BiTNode *T) /*递归前序遍历*/ { if (T==NULL) return; std::cout<<T->data<<"\t"; PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); }
b)非递归实现前序遍历:
对于根结点P:1)访问结点P,并将结点P入栈;
2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P;
3)直到P为NULL并且栈为空,则遍历结束。
void nPreOrderTraverse(BiTNode *T) /*非递归前序遍历*/ { if (T==NULL) return; BiTNode *p; p = T; std::stack<BiTNode*> stk; while(p!=NULL||!stk.empty()) { while(p!=NULL) { std::cout<<p->data<<"\t"; stk.push(p); p = p->lchild; } if(!stk.empty()) { p = stk.top(); stk.pop(); p = p->rchild; } } }
2、中序遍历
中序遍历按照“左孩子-根结点-右孩子”的顺序进行访问。a)递归实现中序遍历
void InOrderTraverse(BiTNode *T) /*递归中序遍历*/ { if (T==NULL) return; InOrderTraverse(T->lchild); std::cout<<T->data<<"\t"; InOrderTraverse(T->rchild); }
b)非递归实现中序遍历
对于根结点P:1)若其左孩子不为空,则将P入栈并将P的左孩子置为当前的P,然后对当前结点P再进行相同的处理;
2)若其左孩子为空,则取栈顶元素并进行出栈操作,访问该栈顶结点,然后将当前的P置为栈顶结点的右孩子;
3)直到P为NULL并且栈为空则遍历结束。
void nInOrderTraverse(BiTNode *T) /*非递归中序遍历*/ { if(T==NULL) return; std::stack<BiTNode*> stk; BiTNode* p; p = T; while(p!=NULL || !stk.empty()) { while(p!=NULL) { stk.push(p); p = p->lchild; } if(!stk.empty()) { p = stk.top(); stk.pop(); std::cout<<p->data<<"\t"; p = p->rchild; } } }
3、后序遍历
后序遍历按照“左孩子-右孩子-根结点”的顺序进行访问。a)递归实现后序遍历
void PostOrderTraverse(BiTNode *T) /*递归后序遍历*/ { if(T==NULL) return; PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); std::cout<<T->data<<"\t"; }
b)非递归实现后序遍历
这里实现略复杂,当初想出来的方法过于笨重,后参考http://www.cnblogs.com/dolphin0520/archive/2011/08/25/2153720.html,改写如下:要保证根结点在左孩子和右孩子访问之后才能访问,因此对于任一结点P,先将其入栈。如果P不存在左孩子和右孩子,则可以直接访问它;或者P存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则同样可以直接访问该结点。若非上述两种情况,则将P的右孩子和左孩子依次入栈,这样就保证了每次取栈顶元素的时候,左孩子在右孩子前面被访问,左孩子和右孩子都在根结点前面被访问。
对于根结点P:
1)将P入栈,设置当前结点 cur ;
2)将当前的 cur 置为栈顶结点,如果 cur 不存在左孩子和右孩子,或者 cur 存在左孩子或者右孩子,但是其左孩子和右孩子都已被访问过了,则可以直接访问该结点并进行出栈操作。否则将 cur 的右孩子和左孩子依次入栈;
3)直到栈为空则遍历结束。
void nPostOrderTraverse(BiTNode *T) /*非递归后序遍历*/ { if(T==NULL) return; BiTNode* cur; /*当前结点*/ BiTNode* pre = NULL; /*前一次输出的结点*/ std::stack<BiTNode*> stk; stk.push(T); while(!stk.empty()) { cur = stk.top(); if((cur->lchild==NULL && cur->rchild==NULL) || (pre!=NULL && (cur->lchild==pre || cur->rchild==pre))) { /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/ std::cout<<cur->data<<"\t"; stk.pop(); pre = cur; } else { if(cur->rchild!=NULL) stk.push(cur->rchild); if(cur->lchild!=NULL) stk.push(cur->lchild); } } }
4、完整测试代码
1)BiTree.h头文件/* BiTree.h头文件 */
#include<iostream>
#include<stack>
typedef char TElemType;
class BiTNode{ /*创建结点类,使用的是左右孩子表示法*/
public:
BiTNode():data(0),lchild(NULL),rchild(NULL){}
TElemType data;
BiTNode *lchild,*rchild;
};
void CreateBiTree(BiTNode **T) /*二叉树的建立,这里形参用的是双指针,需要注意*/
{ /*这里输入的是一个扩展二叉树,每个结点若有空指针,*/
TElemType ch; /*则将其值设为一个特定值,本代码中是'#'*/
std::cin>>ch;
std::cin.clear();
if(ch=='#')
*T=NULL;
else
{
*T=new BiTNode;
if(!*T)
exit(1);
(*T)->data=ch;
CreateBiTree(&(*T)->lchild);
CreateBiTree(&(*T)->rchild);
}
}
void PreOrderTraverse(BiTNode *T) /*递归前序遍历*/ { if (T==NULL) return; std::cout<<T->data<<"\t"; PreOrderTraverse(T->lchild); PreOrderTraverse(T->rchild); }
void nPreOrderTraverse(BiTNode *T) /*非递归前序遍历*/ { if (T==NULL) return; BiTNode *p; p = T; std::stack<BiTNode*> stk; while(p!=NULL||!stk.empty()) { while(p!=NULL) { std::cout<<p->data<<"\t"; stk.push(p); p = p->lchild; } if(!stk.empty()) { p = stk.top(); stk.pop(); p = p->rchild; } } }
void InOrderTraverse(BiTNode *T) /*递归中序遍历*/ { if (T==NULL) return; InOrderTraverse(T->lchild); std::cout<<T->data<<"\t"; InOrderTraverse(T->rchild); }
void nInOrderTraverse(BiTNode *T) /*非递归中序遍历*/ { if(T==NULL) return; std::stack<BiTNode*> stk; BiTNode* p; p = T; while(p!=NULL || !stk.empty()) { while(p!=NULL) { stk.push(p); p = p->lchild; } if(!stk.empty()) { p = stk.top(); stk.pop(); std::cout<<p->data<<"\t"; p = p->rchild; } } }
void PostOrderTraverse(BiTNode *T) /*递归后序遍历*/ { if(T==NULL) return; PostOrderTraverse(T->lchild); PostOrderTraverse(T->rchild); std::cout<<T->data<<"\t"; }
void nPostOrderTraverse(BiTNode *T) /*非递归后序遍历*/ { if(T==NULL) return; BiTNode* cur; /*当前结点*/ BiTNode* pre = NULL; /*前一次输出的结点*/ std::stack<BiTNode*> stk; stk.push(T); while(!stk.empty()) { cur = stk.top(); if((cur->lchild==NULL && cur->rchild==NULL) || (pre!=NULL && (cur->lchild==pre || cur->rchild==pre))) { /*如果当前结点没有孩子结点或者孩子节点都已被访问过*/ std::cout<<cur->data<<"\t"; stk.pop(); pre = cur; } else { if(cur->rchild!=NULL) stk.push(cur->rchild); if(cur->lchild!=NULL) stk.push(cur->lchild); } } }
2)main文件
#include"BiTree.h" using namespace std; int main() { BiTNode *T=new BiTNode; std::cout<<"请前序遍历输入各节点:"; CreateBiTree(&T); cout<<"\n该树的前序遍历输出为:"<<endl; PreOrderTraverse(T); cout<<endl; nPreOrderTraverse(T); cout<<"\n该树的中序遍历输出为:"<<endl; InOrderTraverse(T); cout<<endl; nInOrderTraverse(T); cout<<"\n该树的后序遍历输出为:"<<endl; PostOrderTraverse(T); cout<<endl; nPostOrderTraverse(T); cout<<endl; return 0; }
5、测试结果
相关文章推荐
- C++编程练习(17)----“二叉树非递归遍历的实现“
- C++编程练习(17)----“二叉树非递归遍历的实现“
- 二叉树的遍历方法及递归实现
- 二叉树三种遍历方式的递归与非递归实现
- 数据结构(六)——二叉树 前序、中序、后序、层次遍历及非递归实现 查找、统计个数、比较、求深度的递归实现
- 二叉树的三种遍历的非递归实现
- 二叉树(前中后序递归非递归遍历,层次遍历,C++实现)
- ::递归实现——创建二叉树 ----> 装入数据--->遍历---> 显示 --->销毁
- 二叉树的遍历 非递归 C实现——先序遍历篇
- 树——二叉树的遍历之递归实现
- 递归方法实现二叉树的创建,遍历
- 非递归实现二叉树的遍历
- 二叉树的遍历(非递归实现)
- java语言实现二叉树的前序、中序与后序遍历(递归与非递归)
- 二叉树的遍历:前序,中序,后序,层序--包括递归和非递归实现(转)
- 二叉树三种非递归遍历实现
- 二叉树的遍历:前序,中序,后序,层序--包括递归和非递归实现(转)
- C++实现二叉树 前序遍历, 后序遍历, 中序遍历, 层序遍历(不用递归)
- 递归、非递归实现二叉树的前中后序遍历
- 【应聘笔记系列】二叉树的递归与非递归遍历实现