数据结构——二叉树的基本操作(二)

一、实验目的及要求

1.理解二叉树的基本概念和特点
2.掌握二叉树的链式存储结构
3.掌握二叉树的基本操作
4.掌握二叉树遍历操作

二、实验内容(或实验原理、实验拓扑)

1.实现二叉树的如下操作,先序遍历、中序遍历和后序遍历的递归算法,二叉树如下图所示。(采用二叉链存储结构实现)
(1)采用括号表示法,构建如下二叉树,并输出二叉树b;
(2)采用递归算法,输出二叉树的先序序列;(参考课本212页代码)
(3)采用递归算法,输出二叉树的中序序列;
(4)采用递归算法,输出二叉树的后序序列;
2.实现上述二叉树的先序遍历的算法。

三、实验设计方案(包括实验步骤、设计思想、算法描述或开发流程等)

(一)先、中、后序遍历递归思路与写法:
  1. 先、中、后序遍历递归思路
先序遍历:先遍历根节点,再遍历左子树,再遍历右子树,所以最先输出根节点;
中序遍历:先遍历根节点左子树,再遍历根节点,再遍历右子树;
后序遍历:先遍历左子树,再右子树,最后根节点。
2.递归算法的基本操作函数以及主函数(详细代码见附录):
(1)	创建二叉树CreateBTNode(*b,*str):根据二叉树括号表示法字符串str生成对
应的二叉链存储结构,后者的根结点为*b。
(2) 输出二叉树DispBTNode(BTNode *b):以括号表示法输出一棵二叉树。
(3) 销毁二叉树DestroyBTNode(BTNode *&b):销毁二叉树b。
(4) 先序遍历递归算法PreOrder(BTNode * b)
(5) 中序遍历递归算法InOrder(BTNode * b)
(6) 后序遍历递归算法PostOrder(BTNode * b)
(7)主函数main():根据问题依次调用基本操作函数并编写通俗易懂的语句输出。
(二) 先序遍历非递归方法的基本思路与算法:
1. 先序遍历非递归方法的基本思路:
利用栈先输出当前节点(根),然后将所以其左节点压到栈中,方便后面出栈来处理其的右节点,然后把当前的对象指针指到其左节点(左),然后 while 判断指针不为空,所以继续将其输出,然后移到其左节点,直到没有左节点了,通过出栈开始处理右节点(右)。
2.非递归算法的基本操作函数以及主函数(详细代码见附录):
(1)	创建二叉树CreateBTNode(*b,*str):根据二叉树括号表示法字符串str生成对
应的二叉链存储结构,后者的根结点为*b。
(2) 输出二叉树DispBTNode(BTNode *b):以括号表示法输出一棵二叉树。
(3) 销毁二叉树DestroyBTNode(BTNode *&b):销毁二叉树b。
(4) 初始化栈InitStack(SqStack *&s) 
(5) 销毁栈DestroyStack(SqStack *&s) 
(6) 判断栈是否为空StackEmpty(SqStack *s)
(7) 进栈Push(SqStack *&s,BTNode *e) 
(8) 出栈Pop(SqStack *&s,BTNode *&e) 
(9) 取栈顶元素GetTop(SqStack *s,BTNode *&e) 
(10) 先序遍历非递归算法PreOrder2(BTNode *b) 
(11)主函数main():根据问题依次调用基本操作函数并编写通俗易懂的语句输出。

四、实验结果(包括设计效果、测试数据、运行结果等)

(一)递归算法的运行结果如下:

(二)非递归算法的运行结果如下:

五、实验小结(包括收获、心得体会、注意事项、存在问题及解决办法、建议等)

二叉树的遍历是指按照一定次序访问树中所有节点,并且每个节点仅被访问一次的过程。遍历操作实际上是将非线性结构线性化的过程,其结果为线性序列,并根据采用的遍历顺序分别称为先序序列、中序序列、后序序列。

六、附录(包括作品、流程图、源程序及命令清单等)

(一)递归算法:

#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
	ElemType data;				//数据元素
	struct node *lchild;		//指向左孩子
	struct node *rchild;		//指向右孩子
} BTNode;
void CreateBTNode(BTNode *&b,char *str)		//由str串创建二叉链
{
	BTNode *St[MaxSize],*p=NULL;
	int top=-1,k,j=0;  
	char ch;
	b=NULL;				//建立的二叉树初始时为空
	ch=str[j];
	while (ch!='\0')	//str未扫描完时循环
	{
   	   	switch(ch) 
		{
		case '(':top++;St[top]=p;k=1; break;		//为左节点
		case ')':top--;break;
		case ',':k=2; break;                      	//为右节点
		default:p=(BTNode *)malloc(sizeof(BTNode));
			p->data=ch;p->lchild=p->rchild=NULL;
		         	if (b==NULL)                    //p指向二叉树的根节点
						b=p;
					else  							//已建立二叉树根节点
					{	
						switch(k) 
						{
						case 1:St[top]->lchild=p;break;
						case 2:St[top]->rchild=p;break;
						}
					}
		}
		j++;
		ch=str[j];
	}
}
void DispBTNode(BTNode *b)	//以括号表示法输出二叉树
{
	if (b!=NULL)
	{
		printf("%c",b->data);
		if (b->lchild!=NULL || b->rchild!=NULL)
		{
			printf("(");
			DispBTNode(b->lchild);
			if (b->rchild!=NULL) printf(",");
			DispBTNode(b->rchild);
			printf(")");
		}
	}
}
void DestroyBTNode(BTNode *&b)  //销毁二叉树 
{
	if (b!=NULL)
	{
		DestroyBTNode(b->lchild);
		DestroyBTNode(b->rchild);
		free(b);
	}
}
void PreOrder(BTNode * b)  //先序遍历递归算法
{
	if(b!=NULL)
	{
		printf(" %c",b->data);   //访问根结点 
		PreOrder(b->lchild);     //先序遍历左子树 
		PreOrder(b->rchild);     //先序遍历右子树 
	}
} 
void InOrder(BTNode * b)   //中序遍历递归算法
{
	if(b!=NULL)
	{
		InOrder(b->lchild);     //中序遍历左子树 
		printf(" %c",b->data);   //访问根结点 
		InOrder(b->rchild);     //中序遍历右子树 
	}
} 
void PostOrder(BTNode * b)  //后序遍历递归算法
{
	if(b!=NULL)
	{
		PostOrder(b->lchild);     //后序遍历左子树 
		PostOrder(b->rchild);     //后序遍历右子树
		printf(" %c",b->data);   //访问根结点  
	}
} 
int main()
{
	BTNode *b;
	CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
	printf("二叉树b:  ");
	DispBTNode(b);
	printf("\n");
	printf("先序遍历序列:");
	printf("\n");
	printf("\t递归算法:");
	PreOrder(b);
	printf("\n");
	printf("中序遍历序列:"); 
	printf("\n");
	printf("\t递归算法:");
	InOrder(b);
	printf("\n");
	printf("后序遍历序列:");
	printf("\n");
	printf("\t递归算法:");
	PostOrder(b);
	printf("\n");
	return 0;
}

(二)非递归算法:

btree.cpp
#include <stdio.h>
#include <malloc.h>
#define MaxSize 100
typedef char ElemType;
typedef struct node
{
	ElemType data;				//数据元素
	struct node *lchild;		//指向左孩子
	struct node *rchild;		//指向右孩子
} BTNode;
void CreateBTNode(BTNode *&b,char *str)		//由str串创建二叉链
{
	BTNode *St[MaxSize],*p=NULL;
	int top=-1,k,j=0;  
	char ch;
	b=NULL;				//建立的二叉树初始时为空
	ch=str[j];
	while (ch!='\0')	//str未扫描完时循环
	{
   	   	switch(ch) 
		{
		case '(':top++;St[top]=p;k=1; break;		//为左节点
		case ')':top--;break;
		case ',':k=2; break;                      	//为右节点
		default:p=(BTNode *)malloc(sizeof(BTNode));
			p->data=ch;p->lchild=p->rchild=NULL;
		         	if (b==NULL)                    //p指向二叉树的根节点
						b=p;
					else  							//已建立二叉树根节点
					{	
						switch(k) 
						{
						case 1:St[top]->lchild=p;break;
						case 2:St[top]->rchild=p;break;
						}
					}
		}
		j++;
		ch=str[j];
	}
}

void DispBTNode(BTNode *b)	//以括号表示法输出二叉树
{
	if (b!=NULL)
	{
		printf("%c",b->data);
		if (b->lchild!=NULL || b->rchild!=NULL)
		{
			printf("(");
			DispBTNode(b->lchild);
			if (b->rchild!=NULL) printf(",");
			DispBTNode(b->rchild);
			printf(")");
		}
	}
}


void DestroyBTNode(BTNode *&b)
{
	if (b!=NULL)
	{
		DestroyBTNode(b->lchild);
		DestroyBTNode(b->rchild);
		free(b);
	}
}

think1.cpp

#include "btree.cpp"
typedef struct
{	BTNode *data[MaxSize];			//存放栈中的数据元素
	int top;						//存放栈顶指针,即栈顶元素在data数组中的下标
} SqStack;							//顺序栈类型

void InitStack(SqStack *&s)			//初始化栈
{	s=(SqStack *)malloc(sizeof(SqStack));//分配一个是顺序栈空间,首地址存放在s中
	s->top=-1;						//栈顶指针置为-1
}
void DestroyStack(SqStack *&s)		//销毁栈
{
	free(s);
}
bool StackEmpty(SqStack *s)			//判断栈是否为空
{
	return(s->top==-1);
}
bool Push(SqStack *&s,BTNode *e)	//进栈
{	if (s->top==MaxSize-1)			//栈满的情况,即栈上溢出
		return false;
	s->top++;						//栈顶指针增1
	s->data[s->top]=e;				//元素e放在栈顶指针处
	return true;
}
bool Pop(SqStack *&s,BTNode *&e)	//出栈
{	if (s->top==-1)					//栈为空的情况,即栈下溢出
		return false;
	e=s->data[s->top];				//取栈顶指针元素的元素
	s->top--;						//栈顶指针减1
	return true;
}
bool GetTop(SqStack *s,BTNode *&e)	//取栈顶元素
{	if (s->top==-1)					//栈为空的情况,即栈下溢出
		return false;
	e=s->data[s->top];				//取栈顶元素
	return true;
}

void PreOrder2(BTNode *b)      //先序遍历非递归算法
{       BTNode *p;
        SqStack *st;		//定义一个顺序栈指针st
        InitStack(st);			//初始化栈st
         p=b;
         while (!StackEmpty(st) || p!=NULL)
          {
			 while (p!=NULL)	 //访问结点p及其所有左下结点并进栈
			 {
				 printf(" %c",p->data);
		         Push(st,p);
		         p=p->lchild;		//移动到左孩子
	     }
	      //以下考虑栈顶结点
	     if (!StackEmpty(st))		//若栈不空
	      {	Pop(st,p);
		    p=p->rchild;		//转向处理其右子树
	      }
        }
           printf("\n");
           DestroyStack(st);			//销毁栈
}

int main()
{
    BTNode *b;
	CreateBTNode(b,"A(B(D,E(H(J,K(L,M(,N))))),C(F,G(,I)))");
	printf("二叉树b:");
	DispBTNode(b);
	printf("\n");
	printf("先序遍历序列:\n");
	printf("    非递归算法:");
	PreOrder2(b);printf("\n");
	DestroyBTNode(b);
	return 1;
}
  • 0
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值