结点结构定义如下:(运用了模板)
template<class T>
struct tNode
{ T data;
tNode *left, *right;
};
1.二叉树的前序遍历
递归方面代码比较简单,先输出根结点,然后输出左结点,再是右结点
template<class T>
void preOrder_digui(tNode<T> *p)//根结点
{
if(p==NULL)return;
cout<<p->data<<' ';
preOrder_digui(p->left);
preOrder_digui(p->right);
}
非递归方面,我们要利用栈来实现,
template<class T>
void preOrder(tNode<T> *p)//根结点
{
stack<tNode<T>*> s; //构建一个栈
s.push(p);//压入根节点
while(s.top() || s.size()>0)// 栈顶不为空,栈中还有元素
{
if(s.top())// 栈顶不为空
{
cout<<s.top()->data<<' ';
s.push(s.top()->left);//走左边
}
else
{//走到叶子结点下的空结点时
s.pop();//弹出空结点
//取出头结点
tNode<T>* temp=s.top();
s.pop();
//用头结点的右节点替代原来头结点的位置
s.push(temp->right);
}
}
}
2.中序
递归方面,与前序相似,只是顺序问题。
template<class T>
void midOrder_digui(tNode<T> *p)//根结点
{
if(p==NULL)return;
midOrder_digui(p->left);
cout<<p->data<<' ';
midOrder_digui(p->right);
}
非递归方面,先压入根结点,然后一直走左边,找到最左边的结点,找到最左边的结点,此时cur指向最左结点的左子树,cur==NULL,栈顶是最左边的结点,取出栈顶元素,输出该结点,用该结点的右结点压入栈中。(讲得不是很清楚,大家最好结合实例,手动跑一遍代码)
template<class T>
void midorder(tNode<T>*p)
{
stack<tNode<T>*> s;
s.push(p);//压入根结点
tNode<T>*cur=p->left;
while(cur||s.top()||s.size()>0)
{
while(cur)
{
s.push(cur);//压入但不输出
cur=cur->left;
}
cur=s.top();s.pop();
cout<<cur->data<<' ';
cur=cur->right;
}
}
3.后序
递归依旧是很简单
template<class T>
void afterOrder_digui(tNode<T> *p)//根结点
{
if(p==NULL)return;
afterOrder_digui(p->left);
afterOrder_digui(p->right);
cout<<p->data<<' ';
}
非递归
其中temp用来指向上一个输出的结点,如果上一个输出的结点是下一个结点的右孩子,那么就可以输出这个结点。cur==NULL,使用来防止在走左边,因为输出顺序是由左到右,右边都输出了,那么左边也就已经输出完毕了。大家可结合实例进行分析。
template<class T>
void afterorder(tNode<T>*p)
{
stack<tNode<T>*> s;
s.push(p);
tNode<T>*temp=NULL,*cur=p->left;
while(cur||s.size()>0)
{
while(cur)
{
s.push(cur);
cur=cur->left;
}
cur=s.top();
if(!cur->right||cur->right==temp)
{
s.pop();
cout<<cur->data<<' ';
temp=cur;
cur=NULL;
}
else{
cur=cur->right;
}
}
}
参考文章: