二叉树遍历非递归实现(借助栈)
- 先序遍历:第一次碰到当前结点进行访问;
- 中序遍历:第二次碰到当前结点进行访问;
- 后序遍历:第三次碰到当前结点进行访问
先序遍历非递归实现
思路:
使用栈来模拟递归的操作:循环条件:节点不为NULL,且栈不为空。
如果当前节点不为空,把节点进栈,并且访问节点(cout
),节点指向其左孩子,直至左孩子为空。
这时相当于左子树已经遍历完了,我们需要访问右节点,将当前元素指向栈顶元素右孩子,弹出栈顶元素。
C++代码
void PreOrder(Node *r)
{
stack<Node *> s;
Node *p = r;
while(p || s.size())
{
while(p)
{
s.push(p);
cout << p->data << " ";
p = p->left;
}
p = s.top();
s.pop();
p = p->right;
}
}
中序遍历非递归实现
思路:
和先序遍历类似,只不过访问节点从第一次进栈时访问变成出栈时访问。
C++代码:
void InOrder(Node *r)
{
stack<Node *> s;
Node *p = r;
while(p || s.size())
{
while(p)
{
s.push(p);
p = p->left;
}
p = s.top();
s.pop();
cout << p->data << " ";
p = p->right;
}
}
后序遍历非递归实现
思路:
后序遍历的难点在于第一次将根节点出栈后,并不能直接访问,必须访问其右子树后才可以。使用一个状态栈来存储栈中元素的状态,状态为0暂时不可访问,状态为1可以访问。
C++代码
void PosOrder(Node *r)
{
stack<Node *> s1;
stack<int> s2;
Node *cur = r;
while(cur || s.size())
{
while(cur)
{
s1.push(cur);
s2.push(0);
cur = cur->left;
}
Node *p = s1.top();
if(s2.top() == 0)
{
s2.top() = 1;
cur = p->right;
}
else
{
s1.pop();
s2.pop();
cout << p->data << " ";
}
}
}
完整可运行代码:
#include <iostream>
#include <stack>
using namespace std;
struct Node
{
int data;
Node *left;
Node *right;
Node(int data)
{
this->data = data;
this->left = NULL;
this->right = NULL;
}
};
class BinTree
{
public:
Node *root;
Node* CreateBinTree();
void PreOrder(Node *r);
void InOrder(Node *r);
void PosOrder(Node *r);
};
Node* BinTree::CreateBinTree()
{
Node *p1 = new Node(1);
Node *p2 = new Node(2);
Node *p3 = new Node(3);
Node *p4 = new Node(4);
Node *p5 = new Node(5);
Node *p6 = new Node(6);
p1->left = p2;
p1->right = p3;
p2->left = p4;
p2->right = p5;
p3->right = p6;
root = p1;
return p1;
}
void BinTree::PreOrder(Node *r)
{
stack<Node *> s;
Node *p = r;
while(p || s.size())
{
while(p)
{
s.push(p);
cout << p->data << " ";
p = p->left;
}
p = s.top();
s.pop();
p = p->right;
}
}
void BinTree::InOrder(Node *r)
{
stack<Node *> s;
Node *p = r;
while(p || s.size())
{
while(p)
{
s.push(p);
p = p->left;
}
p = s.top();
s.pop();
cout << p->data << " ";
p = p->right;
}
}
void BinTree::PosOrder(Node *r)
{
stack<Node *> s1;
stack<int > s2;
Node *cur = r;
while(cur || s1.size())
{
while(cur)
{
s1.push(cur);
s2.push(0);
cur = cur->left;
}
Node *p = s1.top();
if(s2.top() == 0)
{
s2.top() = 1;
cur = p->right;
}
else
{
s1.pop();
s2.pop();
cout << p->data << " ";
}
}
}
int main()
{
BinTree t;
t.CreateBinTree();
cout << "先序遍历为:";
t.PreOrder(t.root);
cout << endl;
cout << "中序遍历为:";
t.InOrder(t.root);
cout << endl;
cout << "后序遍历为:";
t.PosOrder(t.root);
cout << endl;
}