/*
二叉树的各种遍历,先,中,后,层次,递归与非递归。
*/
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
typedef struct Bi_Node
{
char data;
struct Bi_Node *lchild,*rchild;
}Bit_Node,*Bit_Tree;
/*因为你的BiTree类型本身就是指向结构体的指针类型 所以在传递参数的过程中
不会发生深拷贝 如果你传递一个对象参数 而且这个对象里面还有指针如果不加引用
就会发生浅拷贝 但是这样发生析构的时候就会使两个指针指向同一块内存
所以必须自己写拷贝构造函数实现深拷贝 但是如果加上引用他就不会去调用拷贝构造函数去构造临时对象
而是直接引用了你的实参对象 所以类里面有指针也不会崩掉
*/
void creat_node(Bit_Tree &T) //不加&,确实没有对指针赋值,从而成为野指针
{
char data;
cin>>data;
if (data == '#')
{
T = NULL;
}
else
{
T = (Bit_Tree)malloc(sizeof(Bi_Node));
T->data = data;
creat_node(T->lchild);
creat_node(T->rchild);
}
}
void print_node(Bit_Tree T)
{
if (T->data != '#')
{
cout<<T->data<<" ";
}
}
void pref_order(Bit_Tree T) //先序遍历 递归 根-左-右
{
if (T != NULL)
{
print_node(T);
pref_order(T->lchild);
pref_order(T->rchild);
}
}
void _pref_order(Bit_Tree T) //先序遍历 非递归
{
stack<Bit_Tree> s;
Bit_Tree p = T;
while(p || !s.empty())
{
if (p != NULL)
{
s.push(p);
cout<<p->data<<" ";
p = p->lchild;
}
else
{
p=s.top();
s.pop();
p = p->rchild;
}
}
}
void in_order(Bit_Tree T) //中序遍历 递归 左-根-右
{
if (T != NULL)
{
in_order(T->lchild);
print_node(T);
in_order(T->rchild);
}
}
void _in_order(Bit_Tree T) //中序遍历 非递归
{
stack<Bit_Tree> s;
Bit_Tree p = T;
while(p || !s.empty())
{
if (p != NULL)
{
s.push(p);
//cout<<p->data<<" ";
p = p->lchild;
}
else
{
p=s.top();
cout<<p->data<<" ";
s.pop();
p = p->rchild;
}
}
}
void post_order(Bit_Tree T) //后序遍历 递归 左-右-根
{
if (T != NULL)
{
post_order(T->lchild);
post_order(T->rchild);
print_node(T);
}
}
typedef struct Bit_Node_Post
{
char tag;
Bit_Tree bit_tree;
}*_Bit_Node_Post;
void _post_order(Bit_Tree T) //后序遍历 非递归
{
stack<_Bit_Node_Post> s;
Bit_Tree p = T;
_Bit_Node_Post bt;
while(p || !s.empty())
{
while (p != NULL)
{
bt = (_Bit_Node_Post)malloc(sizeof(Bit_Node_Post));
bt->tag = 'L';
bt->bit_tree = p;
s.push(bt);
p = p->lchild;
}
while(!s.empty() && ((s.top())->tag == 'R'))
{
bt = s.top();
s.pop();
cout<<bt->bit_tree->data<<" ";
}
if (!s.empty())
{
bt = s.top();
bt->tag = 'R';
p = bt->bit_tree;
p = p->rchild;
}
}
}
void level_order(Bit_Tree T) //层次遍历 (good) 一层一层,从左到右
{
queue<Bit_Tree> q;
Bit_Tree p = T;
q.push(p);
while (!q.empty())
{
p = q.front();
cout<<p->data<<" ";
q.pop();
if (p->lchild != NULL)
{
q.push(p->lchild);
}
if (p->rchild != NULL)
{
q.push(p->rchild);
}
}
}
int main()
{
Bit_Tree T; //这里指向根节点的指针被初始化,后面的T就不用&再引用了。
creat_node(T);
cout<<"先序遍历(递归)"<<endl;
pref_order(T);
cout<<endl;
cout<<"先序遍历(非递归)"<<endl;
_pref_order(T);
cout<<endl;
cout<<"中序遍历(递归)"<<endl;
in_order(T);
cout<<endl;
cout<<"中序遍历(非递归)"<<endl;
_in_order(T);
cout<<endl;
cout<<"后序遍历(递归)"<<endl;
post_order(T);
cout<<endl;
cout<<"后序遍历(非递归)"<<endl;
_post_order(T);
cout<<endl;
cout<<"层次遍历"<<endl;
level_order(T);
cout<<endl;
return 0;
}
Bitree T -> 定义Bitree一个实例对象:T; Bitree &T -> 定义Bitree的实例对象的引用,就是一个已经定义的对象的别名,需要初始化; /* 摘自<<高质量C++/C编程指南>> 引用是C++中的概念,初学者容易把引用和指针混淆一起。一下程序中,n是m的一个引用(reference),m是被引用物(referent)。 int m; int &n = m; n相当于m的别名(绰号),对n的任何操作就是对m的操作。例如有人名叫王小毛,他的绰号是“三毛”。说“三毛”怎么怎么的,其实就是对王小毛说三道四。所以n既不是m的拷贝,也不是指向m的指针,其实n就是m它自己。 */ Bitree *T -> 定义Bitree的实例对象指针,指向一个实例对象; 代码参考: Bitree T; Bitree &T = T; Bitree *T = &T; //&是取地址.