二叉树相关操作的实现

本文档详细介绍了二叉树的二叉链表存储结构,并通过C语言实现了二叉树的创建、先序、中序、后序遍历,以及求结点个数、树高度、叶子结点数、交换左右子树等功能。通过递归算法,展示了二叉树操作的实践应用,加深了对二叉树和递归理解。
摘要由CSDN通过智能技术生成

实 验 报 告

实验名称 二叉树相关操作的实现

一、实验目的和要求

1.理解二叉树二叉链表的存储结构。
2.以二叉树二叉链表的存储结构,实现二叉树的基本操作。
3.掌握二叉树二叉链表存储结构下,相关递归算法的实现。

二、实验内容:

(一)完成二叉树二叉链表结构的定义
(二)实现二叉链表创建二叉树,并实现先序、中序和后序遍历算法。
(三)实现二叉树求结点个数,求树的高度,求叶子结点数、交换二叉树左右子树的算法。

三、实验环境(实验设备)

Visual Studio等
Visual Studio 2019

实 验 报 告

四、实验过程描述与结果分析

代码实现:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>

//二叉树的结点类型;
typedef struct tree
{
	char ch;
	struct tree* lchild;
	struct tree* rchild;
}BitTree;

//创建树;
BitTree* CreateTree()
{
	BitTree* bt;
	char str;
	scanf("%c", &str);
	if (str == '#')
		return NULL;
	else
	{
		bt = (BitTree*)malloc(sizeof(BitTree));
		bt->ch = str;
		bt->lchild = CreateTree();
		bt->rchild = CreateTree();
		return bt;
	}
}

//交换左右二叉树;
void Exchange(BitTree* bt)
{
	if (bt->lchild == NULL && bt->rchild == NULL)
		;
	else    //三种情况,1.都不为空,2.左为空,3.右为空;
	{
		//交换左右子树;
		BitTree* temp = bt->lchild;
		bt->lchild = bt->rchild;
		bt->rchild = temp;
	}

	//如果交换后的这个结点左子树不为空,则继续向下寻找可以交换的结点;
	if (bt->lchild)
		Exchange(bt->lchild);
	if (bt->rchild)
		Exchange(bt->rchild);
}

//先序输出交换后的二叉树;
void PreOrder(BitTree* bt)
{
	if (bt != NULL)
	{
		printf("%c ", bt->ch);
		PreOrder(bt->lchild);
		PreOrder(bt->rchild);
	}
}

//中序输出交换后的二叉树;
void InOrder(BitTree* bt)
{
	if (bt != NULL)
	{
		InOrder(bt->lchild);
		printf("%c ", bt->ch);
		InOrder(bt->rchild);
	}
}

//后序输出交换后的二叉树;
void PostOrder(BitTree* bt)
{
	if (bt != NULL)
	{
		PostOrder(bt->lchild);
		PostOrder(bt->rchild);
		printf("%c ", bt->ch);
	}
}

//二叉树求叶子数
int leaves(BitTree* bt)
{
	if (bt == NULL)
	{
		return 0;
	}
	else if (bt->lchild == NULL && bt->rchild == NULL)
	{
		return 1;
	}
	else
	{
		return leaves(bt->lchild) + leaves(bt->rchild);
	}
}

//求树深度的递归算法
int deep(BitTree* bt)
{
	int lnum, rnum;
	if (bt == NULL)
	{
		return 0;
	}
	else
	{
		lnum = deep(bt->lchild);
		rnum = deep(bt->rchild);
		return (lnum > rnum ? lnum : rnum) + 1;
	}
}

//求二叉树中以某值为根的子树深度(递归)
void x_deep(BitTree* bt, char x)
{
	int lnum = 0, rnum = 0;
	if (bt == NULL)
	{
		printf("空树深度为0\n");
	}
	if (bt->ch == x)
	{
		printf("%d\n", deep(bt));
	}
	else
	{
		if (bt->lchild)
		{
			x_deep(bt->lchild, x);
		}
		if (bt->rchild)
		{
			x_deep(bt->rchild, x);
		}
	}
}

//二叉树求指定结点的层数
int floor(BitTree* bt, char x)
{
	int lnum, rnum, fnum;
	if (bt == NULL)
	{
		fnum = 0;
	}
	else if (bt->ch == x)
	{
		fnum = 1;
	}
	else
	{
		lnum = floor(bt->lchild, x);
		rnum = floor(bt->rchild, x);
		if (lnum == 0 && rnum == 0)//查找失败
		{
			/*printf("查找结束\n");*/
			fnum = 0;
		}
		else
		{
			fnum = ((lnum > rnum) ? lnum : rnum) + 1;
		}
	}
	return fnum;
}


//统计数中结点个数
int nodenum(BitTree* bt)
{
	if (bt == NULL)
	{
		return 0;
	}
	else
	{
		return(nodenum(bt->lchild) + nodenum(bt->rchild)) + 1;
	}
}

int main()
{
	BitTree* bt;
	printf("请以先序序列输入需要创建的二叉树:\n");
	bt = CreateTree();
	int temp;
	while (1)
	{
		printf("<---------------------------二叉树综合实验----------------------------->\n");
		printf("<---------------------------1.二叉树先序遍历--------------------------->\n");
		printf("<---------------------------2.二叉树中序遍历--------------------------->\n");
		printf("<---------------------------3.二叉树后序遍历--------------------------->\n");
		printf("<---------------------------4.求二叉树深度(递归----------------------->\n");
		printf("<---------------------------5.二叉树求叶子数--------------------------->\n");
		printf("<---------------------------6.二叉树求结点数--------------------------->\n");
		printf("<---------------------------7.交换左右子树----------------------------->\n");
		printf("<---------------------------0.退出exit--------------------------------->\n");
		printf("<---------------------------------------------------------------------->\n");
		printf("输入你的选项:");
		scanf_s("%d", &temp);
		if (temp == 0)
		{
			printf("程序退出》》》");
			break;
		}
		switch (temp)
		{
		case 1:
			printf("二叉树前序遍历(递归)为:\n");
			PreOrder(bt);
			printf("\n");
			break;
		case 2:
			printf("二叉树中序遍历(递归)为:\n");
			InOrder(bt);
			printf("\n");
			break;
		case 3:
			printf("二叉树后序遍历(递归)为:\n");
			PostOrder(bt);
			printf("\n");
			break;
		case 4:
			printf("二叉树的深度为%d层\n", deep(bt));
			break;
		case 5:
			printf("二叉树中含有%d个叶子结点\n", leaves(bt));
			break;
		case 6:
			printf("二叉树共有%d个结点\n", nodenum(bt));
			break;
		case 7:
			printf("交换左右子树\n");
			Exchange(bt);
			break;
		default:
			printf("error");
			break;
		}
	}
	return 0;
}



运行结果:一开始用前序遍历创建二叉树 然后分别前序 中序 后序遍历输出 再输出树得深度 叶子树
结点数 然后交换左右子树 最后前序遍历检验 按0结束程序

在这里插入图片描述
在这里插入图片描述

五、实验小结(包括问题和解决方法、心得体会、意见与建议等)

  1. 树本身是一种非线性结构,二叉树基本操作的算法中基本上都用到了递归的思想
  2. 本次实验是对之前所学栈,队列,递归的具体实现及综合应用,熟练掌握栈先进后出,队列先进先出的特性可以解决很多类似问题。、
  3. 利用栈实现先序,中序遍历时,需要注意在定义栈的存储结构时,其头指针,尾指针的数据类型为指向根结点的指针的指针,队列实现层序遍历同理;
  4. 因为C语言中的scanf等一些函数是不安全的函数,所以在用使用Visual Studio 2019的时候会报错,这个则需要添加一个申明加入#define _CRT_SECURE_NO_WARNINGS就可以编译成功了
  5. 真正自己动手写代码的时候,一定要有耐心和细心,不细心可能一个错误能让你让浪费更多的时间去排除错误,没有耐心你就解决不了问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值