四种遍历方法
前三种方法,非递归实现比较抽象,一步步走,可以得出结论
(1)前序遍历
先输出根节点,再遍历左子树,最后遍历右子树
//非递归前序遍历,整体思路先左后右
void preOrder2(BinTree *root)
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL || !s.empty())
{
while(p!=NULL)
{
cout<<p->data<<" ";
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top();
s.pop();
p=p->rchild;
}
}
}
(2)中序遍历
先遍历左子树,再输出根节点,最后遍历右子树
//非递归中序遍历,先左,后根节点,再右
void inOrder2(BinTree *root)
{
stack<BinTree*> s;
BinTree *p=root;
while(p!=NULL || !s.empty())
{
while(p!=NULL)
{
s.push(p);
p=p->lchild;
}
if(!s.empty())
{
p=s.top(); //当p == root 时,转向右子树
cout<<p->data<<" ";
s.pop();
p=p->rchild;
}
}
}
(3)后序遍历
先遍历左子树,再遍历右子树,最后输出根节点
//非递归后序遍历
void postOrder2(BinTree *root)
{
stack<BinTree*> s;
BinTree *cur; //当前结点
BinTree *pre=NULL; //前一次访问的结点
s.push(root);
while(!s.empty())
{
cur=s.top();
if((cur->lchild==NULL && cur->rchild==NULL) || //两个条件满足其中之一
(pre!=NULL && (pre==cur->lchild || pre==cur->rchild)))
{
cout<<cur->data<<" "; //如果当前结点没有孩子结点或者孩子节点都已被访问过
s.pop();
pre=cur;
}
else
{
if(cur->rchild!=NULL)
s.push(cur->rchild); //先压入右孩子,再压入左孩子
if(cur->lchild!=NULL) //
s.push(cur->lchild);
}
}
}
(4)层序遍历
从树的深度,由根节点到最大深度,一层层遍历,根节点的深度为0
void printNodeByLevel(BinTree root)
{
if(root == NULL)
return;
vector<Node *> vec;
vec.push_back(root);
int cur = 0;
int last = 1; //last为上一层的最后一个节点的后一个节点,作为边界条件
while(cur < vec.size()) {
last = vec.size();
while(cur < last) {
cout<<vec[cur]->data<<" ";
if(vec[cur]->pLeft != NULL)
vec.push_back(vec[cur]->pLeft);
if(vec[cur]->pRight != NULL)
vec.push_back(vec[cur]->pRight);
++cur;
}
cout<<endl;
}
}