实验9-二叉树

写程序实现教材上算法:二叉树的创建、中序递归遍历、 中序非递归遍历、 中序线索化、中序线索化二叉树的遍历,并写程序验证。

本文所使用的二叉树示例

先序遍历: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

  • 13
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值