非遞歸遍歷主要利用棧這個數據結構後進先出的性質
非遞歸先序遍歷
根節點壓棧,棧不空就進入循環,根節點出棧,打印數據域,,如果右孩子不空,壓右孩子,
如果左孩子不空,壓左孩子,一定要先壓右孩子,再壓左孩子,一直循環,直到棧爲空。
void NPreOrder(BNode *ptr)
{
if(ptr == NULL) return;
stack<BNode*> sta;
sta.push(ptr);
while(!sta.empty())
{
BNode *p = sta.top();
sta.pop();
cout<<p->data;
if(p->right != NULL) //右孩子不空,入棧
sta.push(p->right);
if(p->left != NULL) //左孩子不空,入棧
sta.push(p->left);
}
}
非遞歸中序遍歷
void NInOrder(BNode *ptr)
{
if(ptr == NULL) return;
stack<BNode *> sta;
while(!sta.empty() || ptr != NULL)
{
while(ptr != NULL) //遍歷左子樹
{
sta.push(ptr); //入棧
ptr = ptr->left;
}
ptr = sta.top();
sta.pop();
cout<<ptr->data;
ptr = ptr->right; //ptr指向右子樹
}
}
非遞歸後序遍歷
void NLastOrder(BNode *ptr)
{
if(ptr == NULL) return;
stack<BNode*> sta;
BNode *tag = NULL; //標記右子樹已經被訪問過了
while(!sta.empty() || ptr != NULL)
{
while(ptr != NULL)
{
sta.push(ptr);
ptr = ptr->left;
}
ptr = sta.top(); //先出棧,不刪除
if(ptr->right == NULL || ptr->right == tag)
{
cout<<ptr->data;
sta.pop();
tag = ptr;
ptr = NULL; //這句很關鍵
}
else //右孩子不空且右孩子沒有被訪問
{
ptr = ptr->right;
}
}
}