写程序实现教材上算法:二叉树的创建、中序递归遍历、 中序非递归遍历、 中序线索化、中序线索化二叉树的遍历,并写程序验证。
本文所使用的二叉树示例
先序遍历:ABDGECF
中序遍历:DGBEAFC
后序遍历:GDEBFCA
二叉树结构体
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
int ltag,rtag;
}BiTNode, *BiTree;
访问二叉树结点数据
//访问二叉树结点数据
void visit(BiTree T)
{
cout<<T->data;
}
递归建立二叉树
//递归建立二叉树,此处也是先序的顺序
void CreateBiTree(BiTree &T)
{
ElemType ch;
cin>>ch;
if(ch=='#') T=NULL;
else
{
T = (BiTNode *)calloc(1,sizeof(BiTNode));
T->data =ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
如果要建立如图二叉树,需要输入什么序列??
先建立根节点,然后建立左子树,最后建立右子树。如果某个子树为空,输入#即可
输入序列:ABD#G##E##CF###即可建立如图二叉树
中序递归遍历
//中序遍历
void InOrder(BiTree T)
{
if(T){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
中序非递归遍历
//中序非递归遍历,需要引入栈的数据结构
#define MaxSize 50 //定义栈中的最大个数
typedef struct{
BiTree data[MaxSize]; //存放栈中的元素
int top; //栈顶指针
}SqStack;
void InitStack(SqStack &S)
{
S.top = -1; //初始化栈顶指针
}
bool StackEmpty(SqStack S)
{
if( S.top==-1 )
return true;
else
return false;
}
bool Push(SqStack &S, BiTree x)
{
if( S.top == MaxSize-1 ){ //栈满,报错
return false;
}
S.data[++S.top] = x; //指针先加1,再入栈
return true;
}
bool Pop( SqStack &S,BiTree &x )
{
if(S.top==-1) //栈空,报错
return false;
x = S.data[S.top--]; //先出栈,指针再减1
return true;
}
//非递归中序遍历
void InOrder2(BiTree T)
{
SqStack S;
InitStack(S); //初始化栈S
BiTree p = T; //p是遍历指针
while( p || !StackEmpty(S) ){ //当栈空并且p空时,结束循环
if(p){
Push(S,p); //当前结点入栈
p=p->lchild;//一直向左走
}
else{
Pop(S,p);
visit(p);
p=p->rchild;
}
}
}
中序线索化
//中序线索化-本质就是中序遍历,边遍历边线索化。2个函数
void InThread(BiTree p, BiTree &pre)
{
if(p){
InThread(p->lchild,pre);
if(p->lchild==NULL){ //左子树为空,建立前驱线索
p->lchild = pre;
p->ltag = 1;
}
if( pre && pre->rchild==NULL ){
pre->rchild = p; //建立前驱结点的后继线索
pre->rtag = 1;
}
pre=p;
InThread(p->rchild,pre);
}
}
//中序线索化二叉树T
void CreateInThread(BiTree T)
{
BiTree pre=NULL;
if(T!=NULL){ //非空二叉树,线索化
InThread(T,pre); //线索化二叉树
pre->rchild = NULL; //处理遍历的最后一个结点
pre->rtag = 1;
}
}
中序线索化二叉树的遍历
//3个函数实现中序线索化二叉树的遍历
//找到以p为根的子树中,第一个被中序遍历的结点
BiTree FirstNode(BiTree p)
{
//循环找到最左下结点(不一定是叶结点,也有可能是只含右子树的根节点)
while(p->ltag==0) p=p->lchild;
return p;
}
//在中序线索二叉树中找到结点p的后继结点
BiTree NextNode(BiTree p)
{
//右子树中最左下结点
if(p->rtag==0) return FirstNode(p->rchild);
else return p->rchild;
}
//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)
void ThreadInOrder(BiTree T)
{
for( BiTree p=FirstNode(T); p!=NULL; p=NextNode(p) )
visit(p);
}
完整代码
#include <iostream>
using namespace std;
typedef char ElemType;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild, *rchild;
int ltag,rtag;
}BiTNode, *BiTree;
//访问二叉树结点数据
void visit(BiTree T)
{
cout<<T->data;
}
//递归建立二叉树,此处也是先序的顺序
void CreateBiTree(BiTree &T)
{
ElemType ch;
cin>>ch;
if(ch=='#') T=NULL;
else
{
T = (BiTNode *)calloc(1,sizeof(BiTNode));
T->data =ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
//先序遍历
void PreOrder(BiTree T)
{
if(T){
visit(T);
PreOrder(T->lchild);
PreOrder(T->rchild);
}
}
//中序遍历
void InOrder(BiTree T)
{
if(T){
InOrder(T->lchild);
visit(T);
InOrder(T->rchild);
}
}
//后序遍历
void PostOrder(BiTree T)
{
if(T){
PostOrder(T->lchild);
PostOrder(T->rchild);
visit(T);
}
}
//中序非递归遍历,需要引入栈的数据结构
#define MaxSize 50 //定义栈中的最大个数
typedef struct{
BiTree data[MaxSize]; //存放栈中的元素
int top; //栈顶指针
}SqStack;
void InitStack(SqStack &S)
{
S.top = -1; //初始化栈顶指针
}
bool StackEmpty(SqStack S)
{
if( S.top==-1 )
return true;
else
return false;
}
bool Push(SqStack &S, BiTree x)
{
if( S.top == MaxSize-1 ){ //栈满,报错
return false;
}
S.data[++S.top] = x; //指针先加1,再入栈
return true;
}
bool Pop( SqStack &S,BiTree &x )
{
if(S.top==-1) //栈空,报错
return false;
x = S.data[S.top--]; //先出栈,指针再减1
return true;
}
//非递归中序遍历
void InOrder2(BiTree T)
{
SqStack S;
InitStack(S); //初始化栈S
BiTree p = T; //p是遍历指针
while( p || !StackEmpty(S) ){ //当栈空并且p空时,结束循环
if(p){
Push(S,p); //当前结点入栈
p=p->lchild;//一直向左走
}
else{
Pop(S,p);
visit(p);
p=p->rchild;
}
}
}
//中序线索化-本质就是中序遍历,边遍历边线索化。2个函数
void InThread(BiTree p, BiTree &pre)
{
if(p){
InThread(p->lchild,pre);
if(p->lchild==NULL){ //左子树为空,建立前驱线索
p->lchild = pre;
p->ltag = 1;
}
if( pre && pre->rchild==NULL ){
pre->rchild = p; //建立前驱结点的后继线索
pre->rtag = 1;
}
pre=p;
InThread(p->rchild,pre);
}
}
//中序线索化二叉树T
void CreateInThread(BiTree T)
{
BiTree pre=NULL;
if(T!=NULL){ //非空二叉树,线索化
InThread(T,pre); //线索化二叉树
pre->rchild = NULL; //处理遍历的最后一个结点
pre->rtag = 1;
}
}
//3个函数实现中序线索化二叉树的遍历
//找到以p为根的子树中,第一个被中序遍历的结点
BiTree FirstNode(BiTree p)
{
//循环找到最左下结点(不一定是叶结点,也有可能是只含右子树的根节点)
while(p->ltag==0) p=p->lchild;
return p;
}
//在中序线索二叉树中找到结点p的后继结点
BiTree NextNode(BiTree p)
{
//右子树中最左下结点
if(p->rtag==0) return FirstNode(p->rchild);
else return p->rchild;
}
//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)
void ThreadInOrder(BiTree T)
{
for( BiTree p=FirstNode(T); p!=NULL; p=NextNode(p) )
visit(p);
}
int main()
{
BiTree T;
CreateBiTree(T); //输入:ABD#G##E##CF###
PreOrder(T); //先序:ABDGECF
cout<<endl;
InOrder(T); //中序:DGBEAFC
cout<<endl;
PostOrder(T); //后序:GDEBFCA
cout<<endl;
InOrder2(T); //非递归中序:DGBEAFC
cout<<endl;
CreateInThread(T);
ThreadInOrder(T); //线索中序:DGBEAFC
return 0;
}
运行
ABD#G##E##CF###
ABDGECF
DGBEAFC
GDEBFCA
DGBEAFC
DGBEAFC