这三种常见的扁历方式,是考研面试等场合经常遇到的,在此做一个总结。
1、前序遍历比较简单:用指针p指向根节点,若p!=NULL且栈非空,则直接访问节点,并将节点的右孩子入栈,同时指针p向左孩子移动。
2、中序扁历:用指针p指向根节点,若p!=NULL且栈非空,则当前节点入栈,同时指针p向左孩子移动,出栈是指针指向当前节点的右孩子。
3、后序扁历相对复杂:需要设置一个辅助栈,标识该节点是否是第二次出栈,只有第二次出栈的节点才可被访问。
具体实现就不啰嗦了,直接上代码吧!
#include <stack>
#include <queue>
using namespace std;
// Binary tree struct
struct BinaryTreeNode
{
BinaryTreeNode() :m_nValue(0), m_pLeft(NULL), m_pRight(NULL){}
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
// 按层次创建节点
BinaryTreeNode* CreateBinaryTree()
{
int a;
BinaryTreeNode *t = NULL;
queue<BinaryTreeNode*> queue_nodes;
cout << "Enter the value of current node value, (space to the leaf node)." << endl;
if (cin >> a && a != -1)
{
t = new BinaryTreeNode;
t->m_nValue = a;
queue_nodes.push(t);
}
while (!queue_nodes.empty())
{
BinaryTreeNode *tNode = queue_nodes.front();
queue_nodes.pop();
if (cin >> a && a != -1)
{
BinaryTreeNode *newLeftNode = new BinaryTreeNode;
newLeftNode->m_nValue = a;
tNode->m_pLeft = newLeftNode;
queue_nodes.push(newLeftNode);
}
if (cin >> a && a != -1)
{
BinaryTreeNode *newRightNode = new BinaryTreeNode;
newRightNode->m_nValue = a;
tNode->m_pRight = newRightNode;
queue_nodes.push(newRightNode);
}
}
return t;
}
void PreOrderTraverse(BinaryTreeNode *t, void(*visit)(int))
{
stack<BinaryTreeNode*> stack_nodes;
BinaryTreeNode *p = t;
while (p || !stack_nodes.empty())
{
if (p){
visit(p->m_nValue);
if (p->m_pRight)
stack_nodes.push(p->m_pRight);
p = p->m_pLeft;
}
else{
p = stack_nodes.top();
stack_nodes.pop();
}
}
}
void InOrderTraverse(BinaryTreeNode *t, void(*visit)(int))
{
stack<BinaryTreeNode*> stack_nodes;
BinaryTreeNode *p = t;
while (p || !stack_nodes.empty())
{
if (p){
stack_nodes.push(p);
p = p->m_pLeft;
}
else{
p = stack_nodes.top();
stack_nodes.pop();
visit(p->m_nValue);
p = p->m_pRight;
}
}
}
void PostOrderTraverse(BinaryTreeNode *t, void(*visit)(int))
{
stack<BinaryTreeNode*> stack_nodes;
stack<bool> stack_visited; // 辅助栈,标识节点是否已经出过栈,只有第二次出栈的节点才能被访问
BinaryTreeNode *p = t;
bool visited = false;
while (p || !stack_nodes.empty())
{
if (p){
stack_nodes.push(p); // 当前节点入栈
stack_visited.push(false); // 对应的辅助标识入栈
p = p->m_pLeft; // 对左孩子进行操作
}
else{
p = stack_nodes.top();
stack_nodes.pop();
visited = stack_visited.top();
stack_visited.pop();
if (!visited){
stack_nodes.push(p);
stack_visited.push(true);
p = p->m_pRight; // 对第一次出栈的节点,入栈后跳转到其右孩子
}
else{
visit(p->m_nValue);
p = NULL;
}
}
}
}