实验八 二叉树的建立及遍历应用

一、【实验目的】
1、掌握二叉树的建立方法

2、掌握二叉树遍历的基本方法(前序、中序、后序)

3、掌握递归二叉树遍历算法的应用

二、【实验内容】

1.构造一棵二叉树,树的形态如下图(亦见附件)所示,打印出先序遍历、中序遍历、后序遍历的遍历序列。

在这里插入图片描述

2.选择一种遍历方式计算该树中叶子结点的个数,并打印出叶子结点。

3.编写一个层序遍历算法,利用队列结构按层次(同一层自左至右)输出二叉树中所有的结点。

三、【实验源代码】

 #include<stdio.h>
#include<stdlib.h>
#define MaxQueueSize 100

typedef char ElemType;

typedef struct LBinaryTreeNode
{
	ElemType data;
	struct LBinaryTreeNode *lchild;
	struct LBinaryTreeNode *rchild;
}LPBTreeNode;

LPBTreeNode* createbintree(void)
{
	LPBTreeNode* pbnode;
	char ch;
	scanf("%c",&ch);
	if(ch=='#')
	{
		pbnode=NULL;
	}
	else
	{
		
		pbnode=(LPBTreeNode*)malloc(sizeof(LPBTreeNode));
		if(pbnode==NULL)
		{
			printf("Out of space!\n");
			return pbnode;
		}
		pbnode->data=ch;

		pbnode->lchild=createbintree();
		pbnode->rchild=createbintree();
		
	}
	//printf("1");//
	return pbnode;
}

void visit(LPBTreeNode* t)
{
	printf("%c",t->data);
	return;
}

void preorder(LPBTreeNode* t)
{
	if(t==NULL)
	{
		return;
	}
	visit(t);
	preorder(t->lchild);
	preorder(t->rchild);
}

void inorder(LPBTreeNode* t)
{
	if(t==NULL)
	{
		return;
	}
	
	inorder(t->lchild);
	visit(t);
	inorder(t->rchild);
}

void postorder(LPBTreeNode* t)
{
	if(t==NULL)
	{
		return;
	}
	
	postorder(t->lchild);
	postorder(t->rchild);
	
	visit(t);
}

int leafnum=0;//定义全局变量 

void leafcount(LPBTreeNode* t)//计算叶子结点数,采用先序遍历 
{
	
	if(t!=NULL)
	{
		if(t->lchild==NULL&&t->rchild==NULL)
		{
			leafnum++;
		}
		leafcount(t->lchild);
		
		leafcount(t->rchild);
	}
}
void getleaf(LPBTreeNode* t)//打印叶子结点 
{
	
	if(t!=NULL)
	{ 
		if(t->lchild==NULL&&t->rchild==NULL)
		{
			printf("%c ",t->data);
		}
		getleaf(t->lchild);
		
		getleaf(t->rchild);
	}
}

typedef struct
{
	ElemType queue[MaxQueueSize];
	int rear;
	int front;
	int count;
 } squeue;
 
 void QueueInitiate(squeue *q) 
 {
 	q->rear=0;
 	q->front=0;
 	q->count=0;
 }
 
void QueueAppend(squeue *q, LPBTreeNode* p)
{
	
	q->queue[q->rear] = p;
	q->rear = (q->rear + 1) % 100;
	q->count++;
}

int QueueNotEmpty(squeue* q)//队列为空返回0
{
	if (q->count == 0&& q->front== q->rear)
	{
		return 0;
	}
		
	return 1;
}
 
 int QueueTop(squeue *q,ElemType *d)
{
	if(q->count!=0)
	{
		*d=q->queue[q->front];
		return 1;
	}
	else
	{
		return 0;
	}	
 } 
 
 int  QueueDelete(squeue *q)
 {
 	if(q->count!=0)
 	{
 		q->front=(q->front+1)%MaxQueueSize;
 		q->count--;
 		return 1;
	 }
	 else
	 {
	 	return 0;
	 }
 }
 
void layorder(LPBTreeNode *root)
{
    LPBTreeNode *t;
    squeue myqueue;
    QueueInitiate(&myqueue);
    QueueAppend(&myqueue, root);  //入根节点
    while (QueueNotEmpty(&myqueue))  //队列不为空,重复出队列,入队列
    {
        QueueTop(&myqueue, (void **)&t);
        printf("%c ", t->data);
        if (t->lchild)    //入孩子
        {
            QueueAppend(&myqueue, t->lchild);
        }
        if (t->rchild)
        {
            QueueAppend(&myqueue, t->rchild);
        }
        QueueDelete(&myqueue);   //头删,出队列
    }
}

int main()
{
	LPBTreeNode *t;
	printf("请输入二叉树的元素:"); 
	t=createbintree();//需要将 createbintree 的返回值赋给 t,否则 t 将是一个未初始化的指针。
	printf("先序遍历的结果为:");
	preorder(t);
	printf("\n");
	printf("中序遍历的结果为:");
	inorder(t);
	printf("\n");
	printf("后序遍历的结果为:");
	postorder(t);
	leafcount(t);
	printf("\n");
	printf("叶子结点数为:%d",leafnum);
	printf("\n");
	printf("叶子结点分别为:");
	getleaf(t);
	printf("\n");
	printf("层序遍历的结果为:");
	layorder(t);
	
	return 0;
 } 

四、【实验结果】

在这里插入图片描述

五、【实验心得】
1、难点一:计算叶子结点数。采用递归思想,叶子结点的特点就是不含左右孩子,所以当根节点不为空且没有左右孩子的情况下,该结点为叶子结点。
2、难点二:层序遍历输出所有结点。层序遍历,需要借助队列数据结构,先把根节点入队列,依次出队列,每次出一个数据,就带节点的孩子入队列(先入左孩子,后入右节点),直到全部节点出过队列,队列为空,循坏结束,层序遍历完成。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐