二叉树的建立及遍历实现

/*----------------------------------------
	树结构 :   	      A
			Bl			      Cr
	  El		 Fr	      Gl
	Hl		  Il   Jr       Kr
	
	先序:A B E H F I J C G K
	中序:H E B I F J A G K C
	后序:H E I J F B K G C A
-----------------------------------------*/

#include<stdio.h>
#include<malloc.h>

//-------------------------数据结构----------------------------------------------
//二叉树结点的定义
typedef char ElemType;
typedef struct Node
{
	ElemType data;
	struct Node* lchild;
	struct Node* rchild;
	//本题为二叉链
}node,*pnode;

//定义顺序堆栈结构
#define LEN 15
typedef struct
{
	pnode p[LEN];
	int max;
	int top;
}stack,*pstack;
//-----------------------------------------------------------------------------------

//--------------------------函数声明-------------------------------------------------

int iNodeNum = 0;                       //遍历时记录结点数
pnode Create_BT(ElemType );
pnode Insert_Lchild(pnode ,ElemType );
pnode Insert_Rchild(pnode ,ElemType );
pstack InitStack(pstack );
void Push(pstack ,pnode );
pnode Pop(pstack );
void TLR_Recursion(pnode );
void LTR_Recursion(pnode );
void LRT_Recursion(pnode );
void LTR_StackTrav(pnode );
void TLR_StackTrav(pnode );
//void LRT_StackTrav(pnode );
//-------------------------------------------------------------------------------------

//---------------------------堆栈算法--------------------------------------------------
//初始化堆栈
pstack InitStack(pstack sp)
{
	int i;
	sp = (pstack)malloc(sizeof(stack));
	for(i=0;i<LEN;i++)
	{
		sp->p[i] = NULL;
	}
	sp->max = LEN-1;
	sp->top = -1;
	return sp;
}
//入栈
void Push(pstack sp,pnode x)
{
	if(sp->top == sp->max)
	{
		printf("error!the stack is full!\n");
		return;
	}
	else
	{
		sp->top++;
		sp->p[sp->top] = x;
	}
}
//出栈
pnode Pop(pstack sp)
{
	if(sp->top == -1)
	{
		printf("error!the stack is empty!\n");
		return NULL;
	}
	else
	{
		return sp->p[sp->top--];
	}
}
//---------------------------------------------------------------------------------------

//------------------------------二叉树算法-----------------------------------------------

//新建一棵只有根节点的二叉树,返回树的起始结点指针
pnode Create_BT(ElemType x)
{
	pnode ptr,pBT;
	ptr = (pnode)malloc(sizeof(node));
	pBT = ptr;
	
	ptr->data = x;
	ptr->lchild = NULL;
	ptr->rchild = NULL;
	
	return pBT;
}

//在当前父节点parent的左孩子插入一个数据位x的新结点,返回新建结点
pnode Insert_Lchild(pnode p,ElemType x)
{
	pnode ptr;
	
	if(p == NULL)
	{
		printf("无法插入新结点!父节点错误!\n");
		return NULL;
	}
	
	ptr = (pnode)malloc(sizeof(node));
	ptr->data = x;
	ptr->lchild = NULL;
	ptr->rchild = NULL;
	
	if(p->lchild == NULL)
	{
		p->lchild = ptr;
	}
	else
	{
		//若父节点已有左子树,则新建结点插入父节点和左树之间
		ptr->lchild = p->lchild;
		p->lchild = ptr;
	}
	
	return ptr;
}


//在当前父节点parent的右孩子插入一个数据位x的新结点,返回新建结点
pnode Insert_Rchild(pnode p,ElemType x)
{
	pnode ptr;
	
	if(p == NULL)
	{
		printf("无法插入新结点!父节点错误!\n");
		return NULL;
	}
	
	ptr = (pnode)malloc(sizeof(node));
	ptr->data = x;
	ptr->lchild = NULL;
	ptr->rchild = NULL;
	
	if(p->rchild == NULL)
	{
		p->rchild = ptr;
	}
	else
	{
		//若父节点已有左子树,则新建结点插入父节点和左树之间
		ptr->rchild = p->rchild;
		p->rchild = ptr;
	}
	
	return ptr;
}
//-------------------------------------------------------------------------------------------


//----------------------------------5种遍历算法-----------------------------------------------
//TLR先序遍历递归算法
void TLR_Recursion(pnode BT)
{
	if( BT != NULL)
	{
		printf("%3c",BT->data);		//访问根节点
		iNodeNum++;
		TLR_Recursion(BT->lchild);	//先序遍历左子树
		TLR_Recursion(BT->rchild);	//先序遍历右子树
	}
}

//LTR中序遍历递归算法
void LTR_Recursion(pnode BT)
{
	if( BT != NULL)
	{
		LTR_Recursion(BT->lchild);	//中序遍历左子树
		printf("%3c",BT->data);		//访问根节点
		iNodeNum++;
		LTR_Recursion(BT->rchild);	//中序遍历右子树
	}
}

//LRT后序遍历递归算法
void LRT_Recursion(pnode BT)
{
	if( BT != NULL)
	{
		LRT_Recursion(BT->lchild);	//后序遍历左子树
		LRT_Recursion(BT->rchild);	//后序遍历右子树
		printf("%3c",BT->data);		//访问根节点
		iNodeNum++;
	}
}

//TLR先序遍历非递归算法(堆栈,好吧ps:神用递归,人用迭代)
void TLR_StackTrav(pnode BT)
{
	pstack pStack = NULL;
	pnode ptr;
	
	iNodeNum = 0;
	ptr = BT;
	pStack = InitStack(pStack);   //初始化堆栈

	Push(pStack,NULL);			  //压入一个空元素,为下列while设立退出循环值
	while(pStack->top!=-1)
	{
		while(ptr != NULL)
		{
			printf("%3c",ptr->data);
			iNodeNum++;
			if(ptr->rchild != NULL)
			{
				Push(pStack,ptr->rchild);
			}
			ptr = ptr->lchild;
		}
		if(pStack->top != -1)
		{
			ptr = Pop(pStack);
		}
	}

	printf("\n先序非递归遍历结点数为:%d\n",iNodeNum);
}

//LTR中序遍历非递归算法(堆栈)
void LTR_StackTrav(pnode BT)
{
	pstack pStack = NULL;
	pnode ptr;
	
	iNodeNum = 0;
	ptr = BT;
	pStack = InitStack(pStack);   //初始化堆栈
	
	Push(pStack,NULL);           //压入一个空元素,为下列while设立退出循环值
	while(pStack->top != -1)
	{
		while(ptr != NULL)
		{
			Push(pStack,ptr);
			ptr = ptr->lchild;
		}
		if(pStack->top != -1)
		{
			ptr = Pop(pStack);
			if(ptr != NULL)
			{
				printf("%3c",ptr->data);
				iNodeNum++;
				ptr = ptr->rchild;         //这步是中序的关键(理解!)
			}
		}
	}
	printf("\n中序非递归遍历结点数为:%d\n",iNodeNum);
}
//-------------------------------------------------------------------------------------

//---------------------------------------主函数-----------------------------------------

//先建立树,然后开始遍历
int main()
{
	pnode BT,ptr,qtr;
	
	//初始化树
	BT = Create_BT('A');
	qtr = Insert_Lchild(BT,'B');   //左树
	ptr = Insert_Lchild(qtr,'E');
	ptr = Insert_Lchild(ptr,'H');
	qtr = Insert_Rchild(qtr,'F');
	ptr = Insert_Lchild(qtr,'I');
	ptr = Insert_Rchild(qtr,'J');
	qtr = Insert_Rchild(BT,'C');   //右树
	qtr = Insert_Lchild(qtr,'G');
	qtr = Insert_Rchild(qtr,'K');
	qtr = BT;					//指针用完回原位
	ptr = BT;
	
	//开始遍历
	//依次先序中序后序递归遍历树。
	iNodeNum = 0;
	TLR_Recursion(BT);
	printf("\n先序递归遍历共有节点数为:%d\n",iNodeNum);
	getchar();

	iNodeNum = 0;
	LTR_Recursion(BT);
	printf("\n中序递归遍历共有节点数为:%d\n",iNodeNum);
	getchar();

	iNodeNum = 0;
	LRT_Recursion(BT);
	printf("\n后序递归遍历共有节点数为:%d\n",iNodeNum);
	getchar();

	//依次先序中序后序非递归遍历树。
	TLR_StackTrav(BT);
	getchar();

	LTR_StackTrav(BT);
	getchar();

	return 0;
}

//-------------------------------------------------------------------------------


由于后序非递归遍历方法较为麻烦,需要设置两个堆栈,一个暂存数据,一个做标识,所以未做研究。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值