typedef struct TNode
{
struct TNode* left;
struct TNode* right;
int data;
}*BinTree;
1、先序遍历
前序遍历按照“根结点-左孩子-右孩子”的顺序进行遍历。
具体算法:先遍历左孩子,并输出。当左孩子遍历完后,取栈顶,并借助栈顶找到右孩子。此时循环还没有结束,再遍历它的左子树,右孩子直至孩子全部遍历结束。
void PreorderTraversal(BinTree T) //前序遍历
{
if(!T) return;
BinTree p = T;
stack<BinTree> s;
while(!s.empty() || p)
{
//遍历左孩子并输出
if(p)
{
cout<<p->data<<" ";
s.push(p);
p = p->left;
}
//左孩子遍历结束,取栈顶,找右孩子
else
{
p = s.top();
p = p->right;
s.pop();
}
}
}
2、中序遍历
中序遍历按照左孩子-根节点-右孩子”的顺序进行遍历。
具体算法:先遍历左孩子,先不急着输出。当左孩子遍历完后,取栈顶并输出栈顶元素,借助栈顶找到右孩子。此时循环还没有结束,再按照“左-根-右”顺序遍历右孩子,直至孩子全部遍历结束。
void InorderTraversal(BinTree T) //中序遍历
{
if(!T) return;
BinTree p = T;
stack<BinTree> s;
while(!s.empty() || p)
{
//先遍历左孩子
if(p)
{
s.push(p);
p = p->left;
}
//左孩子遍历完,输出根节点,找到右孩子
else
{
p = s.top();
cout<<p->data<<" ";
p = p->right;
s.pop();
}
}
}
3、后序遍历
后序遍历按照左孩子-右孩子-根节点”的顺序进行遍历。
后序遍历的难点在于:需要判断上次访问的节点是左孩子,还是右孩子。若是左孩子,则需跳过根节点,先访问右孩子,再回头访问根节点;若是右孩子,则直接访问根节点。因为涉及到判断节点的访问状态,所以后序遍历就比较难写。
现在有个很巧妙的方法:
后序:左->右->根
那么可以把后序按:根->右->左 遍历,然后再反转一下即可
void PostorderTraversal(BinTree T) //后序遍历
{
if(!T) return;
stack<BinTree> s1;
stack<BinTree> s2;
BinTree p;
s1.push(T);
while(!s1.empty())
{
p = s1.top();
s1.pop(); //根节点访问完,出栈s1,进栈s2
s2.push(p);
//先按left right进栈s1, 则之后取s1栈顶 便是 right left
if(p->left) s1.push(p->left);
if(p->right) s1.push(p->right);
}
while(!s2.empty())
{
cout<<s2.top()->data<<" ";
s2.pop();
}
}