这里主要实现了常见的二叉树的几种遍历方法:1) 递归实现的先序、中序、后序遍历; 2) 非递归实现的先序、中序、后序遍历; 3) 层次遍历中包含普通的层次遍历、层次遍历的分行输出、层次遍历的“之”字形输出。
下图是采用的一个二叉树示例图,后续将通过"#"法,先序输入的方式建立二叉树(‘#’表示为空)。再通过上述各种方法遍历输出。
先序遍历: 根左右---A B E F C G
中序遍历: 左根右---E B F A G C
后序遍历: 左右根---E F B G C A
关于递归实现的比较简单,不做说明;
非递归实现中,主要利用了栈。后序遍历中还需要用到一个辅助指针,指向最近访问的指针;
层次遍历中,主要用到的是队列。之字形遍历需要用到两个栈。具体思路说明可参见代码。
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
//节点
typedef struct BitNode
{
char data;
struct BitNode *lchild, *rchild;
}*BiTree;
//按照先序遍历建树 '#'法
void CreateTree(BiTree &T)
{
//按先序输入节点值,‘#’表示空
char data;
cin >> data;
//cout << data;
if (data == '#')
T = NULL;
else
{
T = new BitNode();
T->data = data;
CreateTree(T->lchild); //左子树
CreateTree(T->rchild); //右子树
}
}
/***********递归遍历***********/
void visit(BiTree T)
{
if (T->data != '#')
cout << T->data << " ";
}
//先序遍历
void PreOrder(BiTree T)
{
if (T != NULL)
{
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
//中序
void InOrder(BiTree T)
{
if (T != NULL)
{
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
//后序
void LastOrder(BiTree T)
{
if (T != NULL)
{
LastOrder(T->lchild);
LastOrder(T->rchild);
visit(T);
}
}
//非递归
//先序 访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。
void PreOrder2(BiTree T)
{
stack<BiTree> stack;
BiTree p = T; //p作为遍历指针
while (p != nullptr || !stack.empty())
{
if (p != nullptr)
{
cout << p->data << " ";
stack.push(p);
p = p->lchild;
}
else
{
p = stack.top();
stack.pop();
p = p->rchild;
}
}
}
//中序 T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。
//先将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。
void InOrder2(BiTree T)
{
stack<BiTree> stack;
BiTree p = T;
while (p != nullptr || !stack.empty())
{
if (p != nullptr)
{
stack.push(p);
p = p->lchild;
}
else
{
p = stack.top();
cout << p->data << " ";
stack.pop();
p = p->rchild;
}
}
}
//后序遍历
void LastOrder2(BiTree T)
{
stack<BiTree> stack;
BiTree p = T, help = nullptr; //r指向最近访问的指针
while (p != nullptr || !stack.empty())
{
if (p) //先走到最左结点,沿途入栈
{
stack.push(p);
p = p->lchild;
}
else
{
p = stack.top();
if (p->rchild && p->rchild != help)
p = p->rchild;
else
{
cout << p->data << " ";
stack.pop();
help = p;
p = nullptr;
}
}
}
}
//几种不同风格的层次遍历 需要用到队列
//普通的层次遍历直接输出
void LevelOrder(BiTree T)
{
BiTree p = T;
queue<BiTree> queue;
queue.push(p);
while (!queue.empty())
{
p = queue.front();
cout << p->data << " ";
queue.pop();
if (p->lchild)
queue.push(p->lchild);
if (p->rchild)
queue.push(p->rchild);
}
}
//便于后面两个输出的
void ShowVector(vector<vector<char> > &vec)
{
int row = vec.size();
for (int i = 0; i < row; ++i)
{
int col = vec[i].size();
for (int j = 0; j < col; ++j)
cout << vec[i][j] << " ";
cout << endl;
}
}
//分行输出
void LevelOrder1(BiTree T)
{
vector<vector<char> > vec;
BiTree p = T;
queue<BiTree> queue;
queue.push(p);
while (!queue.empty())
{
int size = queue.size(); //读取每一层的元素的数量
vector<char> LevelElem; //存放一层的值
while (size--) //遍历完一层,队列中正好剩下下一层的所有元素
{
p = queue.front();
LevelElem.push_back(p->data);
queue.pop();
if (p->lchild)
queue.push(p->lchild);
if (p->rchild)
queue.push(p->rchild);
}
vec.push_back(LevelElem);
}
ShowVector(vec);
}
//层次遍历之字形打印
//利用两个栈.打印奇数层,则先保存左结点,再保存右节点到第二个栈里,出栈时即先右后左
//打印偶数层,先保存右节点再保存左结点到第一个栈里
void LevelOrder2(BiTree T)
{
vector<vector<char> > vec;
BiTree p = T;
stack<BiTree> stack1, stack2;
stack1.push(T); //根节点,奇数层,压入栈1
while (!stack1.empty() || !stack2.empty())
{
if (!stack1.empty())
{
vector<char> tmp;
while (!stack1.empty())
{
p = stack1.top();
tmp.push_back(p->data);
stack1.pop();
if (p->lchild)
stack2.push(p->lchild);
if (p->rchild)
stack2.push(p->rchild);
}
vec.push_back(tmp);
}
if (!stack2.empty())
{
vector<char> tmp;
while (!stack2.empty())
{
p = stack2.top();
tmp.push_back(p->data);
stack2.pop();
if (p->rchild)
stack1.push(p->rchild);
if (p->lchild)
stack1.push(p->lchild);
}
vec.push_back(tmp);
}
}
ShowVector(vec);
}
int main()
{
BiTree T;
CreateTree(T);
cout << "*****递归遍历:先序*****" << endl;
PreOrder(T);
cout << endl;
cout << "*****递归遍历:中序*****" << endl;
InOrder(T);
cout << endl;
cout << "*****递归遍历:后序*****" << endl;
LastOrder(T);
cout << endl;
cout << "*****非递归遍历:先序*****" << endl;
PreOrder2(T);
cout << endl;
cout << "*****非递归遍历:中序*****" << endl;
InOrder2(T);
cout << endl;
cout << "*****非递归遍历:后序*****" << endl;
LastOrder2(T);
cout << endl;
cout << "*****普通的层次遍历*****" << endl;
LevelOrder(T);
cout << endl;
cout << "*****分行输出的层次遍历*****" << endl;
LevelOrder1(T);
cout << endl;
cout << "*****之字形的层次遍历*****" << endl;
LevelOrder2(T);
cout << endl;
system("pause");
return 0;
}
运行结果如下: