能递归实现的一般都可以用栈来实现,因此可以用栈来实现二叉树的非递归遍历。以下图的二叉树为例:
1、先序遍历:首先把根结点入栈,然后根结点出栈(访问结点),在出栈的同时将其右左孩子进栈,再把栈顶元素出栈(访问结点),同时将其右左孩子入栈,如此反复知道栈为空。
typedef struct node
{
int data;
struct node *lchild,*rchild;
}BTree;
void PreOrderUnrec(BTree *root)
{
if (NULL == root)
{
return;
}
stack<BTree*> s;
BTree *p;
s.push(root);
while (!s.empty())
{
p = s.top();
Visit(p->data);
s.pop();
if (p->rchild != NULL)
{
s.push(p->rchild);
}
if (p->lchild != NULL)
{
s.push(p->lchild);
}
}
}
还有另外一种方法:
(1)将二叉树的根结点作为当前结点;
(2)若当前结点非空,先访问该结点,并将该结点进栈,再将其左孩子结点作为当前结点,重复步骤(2),直到当前结点为空;
(3)若栈非空,则栈顶结点出栈,并将当前结点的右孩子在哦为当前结点;
(4)重复步骤(2)(3),直到栈为空且当前结点为空。
void PreOrderUnrec1(BTree *root)
{
if (NULL == root)
{
return;
}
stack<BTree*> s;
BTree *p;
p = root;
while (p != NULL && !s.empty())
{
while (p != NULL)
{
Visit(p->data);
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.pop();
p = p->rchild;
}
}
}
2、中序遍历:
(1)将二叉树的根结点作为当前结点;
(2)如果当前结点非空,则该结点进栈并将其左孩子作为当前结点,重复步骤(2)直到当前结点为空;
(3)若栈非空,将栈顶结点出栈并访问,再将其右孩子作为当前结点;
(4)重复步骤(2)(3),直到栈为空且当前结点为空。
void MidOrderUnrec(BTree *root)
{
if (NULL == root)
{
return;
}
stack<BTree*> s;
BTree *p;
p = root;
while (p != NULL || !s.empty())
{
while (p != NULL)
{
s.push(p);
p = p->lchild;
}
if (!s.empty())
{
p = s.pop();
Visit(p->data);
p = p->rchild;
}
}
}
3、后序遍历:
后续遍历的非递归实现可以仿照先序遍历的第一种实现方法,和先序遍历不同的是,后序遍历不应该在出栈时才右左孩子进栈,而是应该在根父结点进栈的同时就把右左孩子入栈。在父结点出栈的时候,需要判断左右孩子是否已经遍历过,如果遍历过了才能遍历父结点。因此需要增加一个标志位来判断右左孩子是否遍历过,定义一个新的结构体
typedef struct STreeNode
{
BTree *treeNode;
int flag;
}*pSTree;
其中flag=0表示右左孩子没有遍历过,flag=2表示右左孩子已经遍历完。
void PostOrderUnrec(BTree *root)
{
stack<pSTree> s;
//根结点先入栈
pSTree sTree = (pSTree)malloc(sizeof(struct STreeNode));
sTree->treeNode = root;
sTree->flag = 0;
s.push(sTree);
while (!s.empty())
{
pSTree p = s.pop;
if (p->flag == 2)//如果栈顶结点标志位是2
{
Visit(p->treeNode->data);//则访问
s.pop();
}
else
{
//如果右孩子存在,则进栈并将标志位加1
if (p->treeNode->rchild)
{
pSTree sTree = (pSTree)malloc(sizeof(struct STreeNode));
sTree->treeNode = p->treeNode->rchild;
sTree->flag = 0;
s.push(sTree);
}
p->flag++;
//如果左孩子存在,则进栈并将标志位加1
if (p->treeNode->lchild)
{
pSTree sTree = (pSTree)malloc(sizeof(struct STreeNode));
sTree->treeNode = p->treeNode->lchild;
sTree->flag = 0;
s.push(sTree);
}
p->flag++;
}
}
}