先序:根结点->左子树->右子树
中序:左子树->根结点->右子树
后序:左子树->右子树->根结点
层次:逐层访问,从左到右
这里我采用的是先序创建。用来测试程序的二叉树为ABD#G###CE##F##,如图所示:
基本数据结构:
typedef struct BiTNode {
char data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode, * BiTree;
下面就来看代码吧。
递归法实现二叉树遍历(先序、中序、后序):
//先序遍历并打印
void PrePrint_Tree(BiTree T)
{
if (T != NULL) {
cout << T->data; //访问根节点
PrePrint_Tree(T->lchild); //先序遍历左子树
PrePrint_Tree(T->rchild); //先序遍历右子树
}
}
//中序遍历并打印
void InPrint_Tree(BiTree T)
{
if (T != NULL) {
InPrint_Tree(T->lchild); //中序遍历左子树
cout << T->data; //访问根节点
InPrint_Tree(T->rchild); //中序遍历右子树
}
}
//后序遍历并打印
void PostPrint_Tree(BiTree T)
{
if (T != NULL) {
PostPrint_Tree(T->lchild); //后序遍历左子树
PostPrint_Tree(T->rchild); //后序遍历右子树
cout << T->data; //访问根节点
}
}
栈实现二叉树遍历(先序、中序、后序):
//先序遍历并打印(非递归)(直接使用了C++STL自带的栈)
void SPrePrint_Tree(BiTree T)
{
if (T == NULL) {
return;
}
else {
stack<BiTree>S;
S.push(T); //根结点入栈
while (!S.empty()) {
T = S.top();
S.pop();
cout << T->data; //访问结点
if (T->rchild) {
S.push(T->rchild); //右子树进栈
}
if (T->lchild) {
S.push(T->lchild); //左子树进栈
}
}
}
}
//中序遍历并打印(非递归)(直接使用了C++STL自带的栈)
void SInPrint_Tree(BiTree T)
{
if (T == NULL) {
return;
}
else {
stack<BiTree>S;
S.push(T); //根结点先入栈
T = T->lchild; //先遍历左子树
while (T || !S.empty()) {
while (T) { //先遍历左子树
S.push(T);
T = T->lchild;
}
T = S.top(); //打印结点
cout << T->data;
S.pop();
T = T->rchild; //遍历右子树
}
}
}
//后序遍历并打印(非递归)(直接使用了C++STL自带的栈)
void SPostPrint_Tree(BiTree T)
{
if (T == NULL) {
return;
}
else {
stack<BiTree>S;
S.push(T);
T = T->lchild;
while (!S.empty()) {
while (T) { //先遍历左子树
S.push(T);
T = T->lchild;
}
T = S.top();
T = T->rchild; //遍历右子树
if (T == NULL) { //左右子树皆为空
T = S.top();
cout << T->data;
S.pop();
while (!S.empty() && T == S.top()->rchild) { //如果T原本就是右子树,
T = S.top(); //则该层已遍历完毕
cout << T->data; //输出根结点
S.pop(); //继续向上一层
}
if (!S.empty()) {
T = S.top()->rchild; //遍历右子树
}
}
}
}
}
队列实现二叉树层次遍历:
//层次遍历并打印
void LevelPrint_Tree(BiTree T)
{
BiTree p;
queue<BiTree>qu; //定义队列,存放二叉树结点指针(这里使用了STL的queue类型)
qu.push(T); //根节点入队
while (!qu.empty()) {
p = qu.front();
cout << p->data; //访问队首结点
qu.pop(); //队首结点出队
if (p->lchild != NULL) {
qu.push(p->lchild); //若结点有左孩子,则左孩子入队
}
if (p->rchild != NULL) {
qu.push(p->rchild); //若结点有右孩子,则左孩子入队
}
}
}
全部代码(包括程序测试):
//实现二叉树的先序、中序、后序遍历,用递归和非递归方法;实现层次遍历
# include <iostream>
# include <stdlib.h>
# include <stack>
# include <queue>
using namespace std;
typedef struct BiTNode {
char data;
struct BiTNode* lchild;
struct BiTNode* rchild;
}BiTNode, * BiTree;
void Init_Tree(BiTree& T) //初始化
{
T = (BiTree)malloc(sizeof(BiTNode));
T->data = '#';
T->lchild = NULL;
T->rchild = NULL;
}
void Destroy_Tree(BiTree& T) //销毁(基于后序顺序)
{
if (T) {
Destroy_Tree(T->lchild);
Destroy_Tree(T->rchild);
free(T);
}
}
void Create_Tree(BiTree& T) //创建(基于先序顺序)
{
char c;
cin >> c;
if (c == '#') {
T = NULL;
}
else {
T = (BiTree)malloc(sizeof(BiTNode));
T->data = c;
Create_Tree(T->lchild);
Create_Tree(T->rchild);
}
}
void PrePrint_Tree(BiTree T) //先序遍历并打印(递归)
{
if (T == NULL) {
return;
}
else {
cout << T->data;
PrePrint_Tree(T->lchild);
PrePrint_Tree(T->rchild);
}
}
void SPrePrint_Tree(BiTree T) //先序遍历并打印(非递归)(栈)
{
if (T == NULL) {
return;
}
else {
stack<BiTree>S;
S.push(T); //根结点入栈
while (!S.empty()) {
T = S.top();
S.pop();
cout << T->data; //访问结点
if (T->rchild) {
S.push(T->rchild); //右子树进栈
}
if (T->lchild) {
S.push(T->lchild); //左子树进栈
}
}
}
}
void InPrint_Tree(BiTree T) //中序遍历并打印(递归)
{
if (T == NULL) {
return;
}
else {
InPrint_Tree(T->lchild);
cout << T->data;
InPrint_Tree(T->rchild);
}
}
void SInPrint_Tree(BiTree T) //中序遍历并打印(非递归)(栈)
{
if (T == NULL) {
return;
}
else {
stack<BiTree>S;
S.push(T); //根结点先入栈
T = T->lchild; //先遍历左子树
while (T || !S.empty()) {
while (T) { //先遍历左子树
S.push(T);
T = T->lchild;
}
T = S.top(); //打印结点
cout << T->data;
S.pop();
T = T->rchild; //遍历右子树
}
}
}
void PostPrint_Tree(BiTree T) //后序遍历并打印(递归)
{
if (T == NULL) {
return;
}
else {
PostPrint_Tree(T->lchild);
PostPrint_Tree(T->rchild);
cout << T->data;
}
}
void SPostPrint_Tree(BiTree T) //后序遍历并打印(非递归)(栈)
{
if (T == NULL) {
return;
}
else {
stack<BiTree>S;
S.push(T);
T = T->lchild;
while (!S.empty()) {
while (T) { //先遍历左子树
S.push(T);
T = T->lchild;
}
T = S.top();
T = T->rchild; //遍历右子树
if (T == NULL) { //左右子树皆为空
T = S.top();
cout << T->data;
S.pop();
while (!S.empty() && T == S.top()->rchild) { //如果T原本就是右子树,
T = S.top(); //则该层已遍历完毕
cout << T->data; //输出根结点
S.pop(); //继续向上一层
}
if (!S.empty()) {
T = S.top()->rchild; //遍历右子树
}
}
}
}
}
void LevelPrint_Tree(BiTree T) //层次遍历并打印
{
queue<BiTree>Q;
Q.push(T);
while (!Q.empty()) {
T = Q.front();
Q.pop();
cout << T->data;
if (T->lchild) {
Q.push(T->lchild);
}
if (T->rchild) {
Q.push(T->rchild);
}
}
}
int main()
{
BiTree T;
Init_Tree(T); //初始化
cout << "按先序顺序输入元素:";
Create_Tree(T); //创建
cout << "先序遍历二叉树(递归):";
PrePrint_Tree(T); //先序遍历并打印
cout << endl;
cout << "先序遍历二叉树(用栈):";
SPrePrint_Tree(T); //先序遍历并打印
cout << endl;
cout << "中序遍历二叉树(递归):";
InPrint_Tree(T); //中序遍历并打印
cout << endl;
cout << "中序遍历二叉树(用栈):";
SInPrint_Tree(T); //中序遍历并打印
cout << endl;
cout << "后序遍历二叉树(递归):";
PostPrint_Tree(T); //后序遍历并打印
cout << endl;
cout << "后序遍历二叉树(用栈):";
SPostPrint_Tree(T); //后序遍历并打印
cout << endl;
cout << "层次遍历二叉树:";
LevelPrint_Tree(T); //层次遍历并打印
cout << endl;
return 0;
}
运行结果:
按先序顺序输入元素:ABD#G###CE##F##
先序遍历二叉树(递归):ABDGCEF
先序遍历二叉树(用栈):ABDGCEF
中序遍历二叉树(递归):DGBAECF
中序遍历二叉树(用栈):DGBAECF
后序遍历二叉树(递归):GDBEFCA
后序遍历二叉树(用栈):GDBEFCA
层次遍历二叉树:ABCDEFG
小结:通过递归来实现先序、中序、后序遍历,优点在于写起来比较简单,但实际运行中时间复杂度会比较高。用非递归方法,也就是栈的方法,写起来比较复杂,但实际运行中的时间复杂度较低。而层次遍历是借助队列来实现的,和BFS的道理相同。
以上是我的个人学习成果,很高兴能与大家分享。