(c语言)树的先序/中序非递归遍历算法(包括测试用例)

本实验取材于浙江大学《数据结构》
在中序遍历非递归遍历算法中,采用了堆栈存储结构。步数如下:

  • 遇到一个结点,就把它压栈,并去遍历它的左子树;
  • 当左子树遍历结束后,从栈顶弹出这个结点并访问它;
  • 然后按其指针再去中序遍历该结点的右子树。
    在这里插入图片描述
    如果按照树的模型来看,在沿着左子树深入时,进入一个结点就将其压入堆栈。若为中序遍历,则此时访问该结点,然后从该结点的右子树继续深入
void InOrderTraveral(BinTree BT)
{
	BinTree T = BT;
	Stack S = CreateStack(MaxSize1);
	while(T || !IsEmpty(S)){
		while(T){//一直向左并将沿途结点压入堆栈
			Push(S,T);
			T = T->Left;
		}
		if(!IsEmpty(S))
		{
			T=(struct TNode *)Pop(S);//结点弹出堆栈
			printf("%5d",T->Data);//访问打印结点
			T = T->Right;
		}
	}
}

若是先序遍历,则在入栈之前访问之,当沿左分支深入不下去时,则返回,即从堆栈中弹出前面压入的结点。

void PreorderTraversal( BinTree BT )
{
	BinTree T = BT;
	Stack S = CreateStack(MaxSize1);
	while(T || !IsEmpty(S)){
		while(T){//一直向左并将沿途结点压入堆栈
			printf("%5d",T->Data);//访问打印结点
			Push(S,T);
			T = T->Left;
		}
		if(!IsEmpty(S))
		{
			T=(struct TNode *)Pop(S);//结点弹出堆栈
			
			T = T->Right;
		}
	}
}

这样看起来还差一个后序遍历,后序遍历则将此结点二次入栈,然后从该结点右子树继续深入,与前面类同,仍为进入一个结点入栈一个结点,深入不下去再返回,直到第二次从栈里弹出该结点,才访问之。因为两次入栈,比较繁杂,因此,先给出两种遍历!

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ERROR -1
#define MaxSize1 10
//中序遍历的非递归算法
//一个结点,就把它压栈,并去遍历它的左子树
//当左子树遍历结束后,从栈顶弹出这个结点并访问它
//然后按其右指针再去中序遍历该节点的右子树

typedef struct SNode *PtrToStack;

typedef int ElementType;
typedef struct TNode *Position;
typedef Position BinTree; /* 二叉树类型 */

struct TNode{ /* 树结点定义 */
    ElementType Data; /* 结点数据 */
    BinTree Left;     /* 指向左子树 */
    BinTree Right;    /* 指向右子树 */
};

struct SNode{
	ElementType *Data;
	int Top;
	int MaxSize;
};
typedef PtrToStack Stack;
Stack CreateStack(int MaxSize);//生成空堆栈,其最大长度为Maxsize
int IsFull(Stack S);//判断堆栈S是否已满
int Push(Stack S,Position X);//将元素item压入堆栈
int IsEmpty(Stack S);//判断堆栈S是否为空
ElementType Pop(Stack S);//删除并返回栈顶元素
Stack CreateStack(int MaxSize){
	Stack S=(Stack)malloc(sizeof(struct SNode));
	S->Data = (ElementType *)malloc(MaxSize*sizeof(ElementType));
	S->Top = -1;
	S->MaxSize = MaxSize;
	return S;
}
int IsFull(Stack S){
	return (S->Top==S->MaxSize-1);
}

int Push(Stack PtrS,Position X)
{
	if(IsFull(PtrS)){
		printf("堆栈满");
		return ERROR;
	}else{
		PtrS->Data[++(PtrS->Top)] = (int )X;
		return PtrS->Data[PtrS->Top];
	}
}
int IsEmpty(Stack S){
	return (S->Top==-1);
}
ElementType Pop(Stack PtrS)
{
	if(PtrS->Top==-1){
		printf("堆栈空");
		return ERROR;
	}else{
		return (PtrS->Data[(PtrS->Top)--]);
	}
}
void InOrderTraveral(BinTree BT)
{
	BinTree T = BT;
	Stack S = CreateStack(MaxSize1);
	while(T || !IsEmpty(S)){
		while(T){//一直向左并将沿途结点压入堆栈
			Push(S,T);
			T = T->Left;
		}
		if(!IsEmpty(S))
		{
			T=(struct TNode *)Pop(S);//结点弹出堆栈
			printf("%5d",T->Data);//访问打印结点
			T = T->Right;
		}
	}
}
void PreorderTraversal( BinTree BT )
{
	BinTree T = BT;
	Stack S = CreateStack(MaxSize1);
	while(T || !IsEmpty(S)){
		while(T){//一直向左并将沿途结点压入堆栈
			printf("%5d",T->Data);//访问打印结点
			Push(S,T);
			T = T->Left;
		}
		if(!IsEmpty(S))
		{
			T=(struct TNode *)Pop(S);//结点弹出堆栈
			
			T = T->Right;
		}
	}
}
int main()
{
	BinTree Bt = (BinTree)malloc(sizeof(struct TNode));
	BinTree Bt1 = (BinTree)malloc(sizeof(struct TNode));
	BinTree Bt2 = (BinTree)malloc(sizeof(struct TNode));
	BinTree Bt3 = (BinTree)malloc(sizeof(struct TNode));
	BinTree Bt4 = (BinTree)malloc(sizeof(struct TNode));
	Bt->Data = 1;
	Bt1->Data=2;
	Bt2->Data=3;
	Bt3->Data=4;
	Bt4->Data=5;
	Bt->Left = Bt1;
	Bt->Right = Bt2;
	Bt1->Left = NULL;
	Bt1->Right = NULL;
	
	Bt2->Left = Bt3;
	Bt2->Right = Bt4;
	Bt3->Left = NULL;
	Bt3->Right = NULL;
	Bt4->Left = NULL;
	Bt4->Right = NULL;	
	printf("\nzhong xu bian li\n");
	
	InOrderTraveral(Bt);

	printf("\nxian xu bian li \n");	
	PreorderTraversal(Bt);
	printf("\n");

	
	return 0;

	
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值