二叉树的建立及遍历实现

/*----------------------------------------
	树结构 :   	      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、付费专栏及课程。

余额充值