#include <iostream>
#include <string>
#include <stack>
using namespace std;
typedef struct BTNode
{
char data;
BTNode *lChild;
BTNode *rChild;
} BTNode, *BTree;
BTree create_tree();
void pre_traverse(BTree);
void in_traverse(BTree);
void post_traverse(BTree);
int main()
{
BTree head = create_tree();
// pre_traverse(head);
// in_traverse(head);
post_traverse(head);
return 0;
}
BTree create_tree()
{
//容易出错的地方是没有左右子树的节点要显示置空
//不然很容易出现野指针的问题,递归会死循环
BTree head = new BTNode;
head->data = 'A';
BTree b = new BTNode;
b->data = 'B';
head->lChild = b;
BTree c = new BTNode;
c->data = 'C';
head->rChild = c;
c->lChild = nullptr;
c->rChild = nullptr;
BTree d = new BTNode;
d->data = 'D';
b->lChild = d;
d->lChild = nullptr;
d->rChild = nullptr;
BTree f = new BTNode;
f->data = 'F';
b->rChild = f;
f->lChild = nullptr;
f->rChild = nullptr;
return head;
}
void pre_traverse(BTree head)
{
stack<BTNode> stack; //创建一个空栈
//因为BTree是指针类型的,最好是定义的时候就初始化,不然容易出现野指针
BTree pop_node = nullptr; //用来保存出栈的结点
BTree cur_node = head; //定义用来指向当前访问节点的指针
while (cur_node || stack.empty() == false)
{
//从根节点开始,输出当前结点,并将其入栈
//同时转向左孩子为当前节点,直至左孩子没有没有左孩子
cout << cur_node->data << "\t";
stack.push(*cur_node); //当前结点入栈
cur_node = cur_node->lChild;
//如果当前结点为空,且栈不空,则将栈顶结点出栈
//转向右子树为当前结点,循环判断,知道cur_node为空
while (cur_node == nullptr && stack.empty() == false)
{
cur_node = &stack.top(); //取栈顶元素
stack.pop();
cur_node = cur_node->rChild;
}
}
}
void in_traverse(BTree head)
{
stack<BTNode *> stack; //初始化一个空栈
BTNode *cur_node = head;
while (cur_node || !stack.empty())
{
stack.push(cur_node);
cur_node = cur_node->lChild;
//左子树走到叶子结点了,然后访问跟结点,然后转向右子树
while (!cur_node && !stack.empty())
{
cur_node = stack.top(); //左子树为空的结点
stack.pop();
cout << cur_node->data << "\t"; //访问结点
cur_node = cur_node->rChild; //转向右子树
}
}
}
void post_traverse(BTree head)
{
stack<BTNode *> stack;
BTNode *cur_node = head;
BTNode *pre_node = nullptr;
stack.push(cur_node);
while (!stack.empty())
{
cur_node = stack.top();
//沿着左子树一直遍历,直到找到一个左子树为空的结点
if ((cur_node->lChild == nullptr && cur_node->rChild == nullptr) || //左右子树都空,那么可以直接输出当前结点
//前一个结点不为空,如果前一个结点是当前结点的左结点,说明当前结点只有左孩子,且已经访问过,可以输出当前结点
//前一个结点不为空,如果前一个结点时当前结点的右孩子,说明当前结点有左右子树,且右子树也被访问,可以输出当前结点
(pre_node != nullptr && (cur_node->lChild == pre_node || cur_node->rChild == pre_node)))
{
cout << cur_node->data << "\t";
stack.pop();
pre_node = cur_node;
}
else
{
//如果不满足上足情况,将其右孩子,左孩子依次入栈
if (cur_node->rChild)
{
stack.push(cur_node->rChild);
}
if (cur_node->lChild)
{
stack.push(cur_node->lChild);
}
}
}
}
二叉树的非递归遍历
最新推荐文章于 2024-10-30 16:47:45 发布