本文转自 https://blog.csdn.net/weixin_40170902/article/details/80732947
二叉树的非递归遍历
- 二叉树的三种遍历方式也可以通过非递归的方法借助栈来实现。
- 通过控制节点的出栈和入栈先后顺序来实现对树的不同方式的遍历。
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <iostream>
#include <vector>
using namespace std;
typedef int ElemType;
#define nullptr NULL
typedef struct _TreeNode { // 定义二叉查找树的结构
ElemType data; // 数据
struct _TreeNode* left; // 指向左孩子指针
struct _TreeNode* right; // 指向其右孩子指针
}TreeNode, *SearchBTree;
typedef SearchBTree StackElemType;
typedef struct StackNode { // 定义栈的结构(基于链表)
SearchBTree data;
StackNode *next;
}*Stack;
void initStack(Stack St) // 初始化栈,把头节点看作是栈顶
{
St->next = nullptr;
}
int isEmpty(Stack St)
{
return St->next == nullptr;
}
void Push(Stack St, SearchBTree x) // 每次从将元素插入到头节点的位置,头节点上移
{
StackNode* q = new StackNode;
q->data = x;
q->next = St->next; // q的next域指向St(头节点)的后继结点
St->next = q; // St(头节点/栈顶)next域指向q,实现栈往上移
}
void Pop(Stack St) // 出栈
{
StackNode* p = St->next; // 临时结点指向头结点(栈顶)的后继结点
St->next = p->next; // 栈顶下移
delete p; // 释放空间
}
SearchBTree getTop(Stack St)
{
return St->next->data;
}
SearchBTree EmptyTree(SearchBTree T) // 初始化、构造一颗空树/销毁一颗树
{
if (!T)
{
EmptyTree(T->left); // 递归地释放空间
EmptyTree(T->right);
delete T;
}
return nullptr;
}
void Insert(SearchBTree &T, ElemType x)
{
if (!T)
{
TreeNode* pT = new TreeNode; // 申请节点空间
pT->data = x; // 为节点赋值
pT->left = pT->right = nullptr;
T = pT; // 将pT赋给T
}
else
{
if (x < T->data) // 如果x小于某个结点的数据
Insert(T->left, x); // 递归地在其左子树上寻找空结点插入
else if (x > T->data) // 如果x大于某个结点的数据
Insert(T->right, x); // 递归地在其左子树上寻找空结点插入
}
}
void PreorderPrint(SearchBTree T) // 先序根(序)遍历二叉树并打印出结点值
{
if (T == nullptr)
{
cout << "Empty tree!";
exit(1);
}
Stack S = new StackNode; // 借助栈来实现
initStack(S);
TreeNode* pT = T; // 创建临时结点指向根节点
while (pT || !isEmpty(S)) // 当结点不为空或者栈不为空执行循环
{
if (pT) // 当pT不为空
{
Push(S, pT); // pT入栈
cout << pT->data << " "; // 打印当前结点
pT = pT->left; // pT移动指向其左孩子
}
else
{ // pT为空,则
pT = getTop(S);
Pop(S); // 若pT为空表示左子树的左孩子全部遍历完,依次出栈
pT = pT->right; // 当左孩子及根结点遍历完之后,开始遍历其右子树
}
}
cout << endl;
delete S;
}
void InorderPrint(SearchBTree T) // 中根(序)遍历二叉树并打印出结点值
{
if (T == nullptr)
{
cout << "Empty tree!";
exit(1);
}
Stack S = new StackNode; // 借助栈来实现
initStack(S);
TreeNode* pT = T; // 创建临时结点指向根节点
while (pT || !isEmpty(S)) // 当结点不为空或者栈不为空执行循环
{
if (pT) // 当pT不为空
{
Push(S, pT); // pT入栈
pT = pT->left; // pT移动指向其左孩子
}
else
{ // pT为空,则
pT = getTop(S);
Pop(S); cout << pT->data << " "; // 若pT为空表示左子树的左孩子全部遍历完,依次出栈并打印
pT = pT->right; // 当左孩子及根结点遍历完之后,开始遍历其右子树
}
}
cout << endl;
delete S;
}
void PostorderPrint(SearchBTree T) // 先根(序)遍历二叉树并打印出结点值
{
if (T == nullptr)
{
cout << "Empty tree!";
exit(1);
}
Stack S = new StackNode; // 借助栈来实现
initStack(S);
TreeNode* pT = T; // 创建临时结点指向根节点
TreeNode* qT = nullptr;
while (pT || !isEmpty(S)) // 当结点不为空或者栈不为空执行循环
{
if (pT) // 当pT不为空
{
Push(S, pT); // pT入栈
pT = pT->left; // pT移动指向其左孩子
}
else
{
pT = getTop(S); // 取栈顶元素作为当前结点
if (pT->right && pT->right != qT) // 若当前节点有右孩子且不是上一次已经被访问的结点
{
pT = pT->right; // 指向其右孩子
}
else
{ // 若当前结点没有右孩子或者未被访问,则
Pop(S); // 出栈
cout << pT->data << " "; // 访问当前结点的数据
qT = pT; // 令pT记录当前结点,用于稍后判断是否已经被访问过
pT = nullptr; // 将当前结点赋值为空
}
// 当左孩子及根结点遍历完之后,开始遍历其右子树
}
}
cout << endl;
delete S;
}
int main()
{
const ElemType rawdata[] = { 19, 7, 9, 15, 23, 39, 4, 2, 75, 100, 43, 58 };
SearchBTree myTree = new TreeNode;
myTree = EmptyTree(myTree); // 初始化树
for (int i = 0;i < sizeof(rawdata) / sizeof(ElemType);i++)
{
Insert(myTree, rawdata[i]); // 向树中插入给定数据
}
cout << "The inorder print of the tree is: \n";
InorderPrint(myTree);
cout << "The preorder print of the tree is: \n";
PreorderPrint(myTree);
cout << "The postorder print of the tree is: \n";
PostorderPrint(myTree);
delete myTree;
system("pause");
return 0;
}
操作运行结果
The preorder print of the tree is:
19 7 4 2 9 15 23 39 75 43 58 100
The inorder print of the tree is:
2 4 7 9 15 19 23 39 43 58 75 100
The postorder print of the tree is:
2 4 15 9 7 58 43 100 75 39 23 19
---------------------
作者:SanFanCSgo
来源:CSDN
原文:https://blog.csdn.net/weixin_40170902/article/details/80732947
版权声明:本文为博主原创文章,转载请附上博文链接!