由于栈和递归原理相同,且递归创建二叉树的效率较低,所以我们可以借助栈来实现二叉树的非递归创建以及遍历。
#include<iostream>
#include<stack>
using namespace std;
template <class T>
struct BinaryTreeNode
{
BinaryTreeNode* _left;
BinaryTreeNode* _right;
T _data;
BinaryTreeNode(const T &x)
: _data(x)
, _left(NULL)
, _right(NULL)
{}
};
template<class T>
class BinaryTree
{
typedef BinaryTreeNode<T> Node;
public:
BinaryTree()
:_root(NULL)
{}
BinaryTree(const T* arr, size_t size, const T &invalid)
{
size_t index = 0;
_root = _CreateBinaryTree(arr,size,index,invalid);
}
void PrevOrder() // 前序遍历
{
Node* root = _root;
stack<Node*> s;
s.push(root);
while (!s.empty())
{
Node* pCur = s.top();
cout << pCur->_data<<" ";
s.pop();
if (pCur->_right)
s.push(pCur->_right);
if (pCur->_left)
s.push(pCur->_left);
}
cout << endl;
}
void InOrder() //中序遍历
{
stack<Node*> s;
Node* pCur = _root;
while (pCur || !s.empty())
{
while (pCur) //依次保存左孩
{
s.push(pCur);
pCur = pCur->_left;
}
pCur = s.top();
cout << pCur->_data << " ";
s.pop();
//若右孩存在,当成一颗新树来遍历
pCur = pCur->_right;
}
cout << endl;
}
void BackOrder() //后序遍历
{
stack<Node*>s;
Node* pCur = _root;
Node* flag = NULL; //标志位
while (pCur || !s.empty())
{
while (pCur) //依次保存左孩
{
s.push(pCur);
pCur = pCur->_left;
}
pCur = s.top();
if (pCur->_right == NULL || pCur->_right == flag)
{
cout << pCur->_data << " ";
s.pop();
flag = pCur;
pCur = NULL;//防止遍历到根部时,栈为空,而跟的右孩子依旧为真造成的死循环问题
}
else
{
pCur = pCur->_right;
}
}
cout << endl;
}
protected:
Node* _CreateBinaryTree(const T* arr, size_t size, size_t index, const T &invalid)
{
stack<Node*> s;
int flag = 1;
Node*root = new Node(arr[index++]);
s.push(root);
Node* cur = NULL;
Node* tmp = NULL;
while (index < size)
{
if (flag == 1) //创建左树
{
if (arr[index] == invalid) //若左树位置无效,flag设为2,创建右树
{
flag = 2;
}
else
{
cur = new Node(arr[index]);
tmp = s.top();
tmp->_left = cur;
s.push(cur);
}
}
else if (flag == 2)
{
if (arr[index] == invalid) //若右树位置无效,flag设为3,准备出栈
{
flag = 3;
}
else
{
cur = new Node(arr[index]);
tmp = s.top();
tmp->_right = cur;
s.push(cur);
flag = 1; //右树创建完毕后flag设为1,下次接着创建左树
}
}
else
{
if (!s.empty()) //若栈非空,依次出栈判断
{
tmp = s.top();
s.pop();
}
//如果已经出栈的元素是当前栈顶的右孩子,表示此结点左右子树已经创建完毕,继续出栈
while ((!s.empty()) && (tmp == (s.top()->_right)))
{
tmp = s.top();
s.pop();
}
flag = 2;
index--;
}
index++;
}
return root;
}
private:
Node* _root;
};
void test()
{
int arr[] = { 1, 2, 3, '#', '#',4,'#','#', 5, 6 ,'#','#',7};
size_t sz = sizeof(arr) / sizeof(arr[0]);
BinaryTree<int>t(arr, sz, '#');
t.PrevOrder();
t.InOrder();
t.BackOrder();
}
int main()
{
test();
system("pause");
return 0;
}