数据结构二叉树的实验练习

1.实验任务说明:说明1:以下二叉树均以二叉链表作为存储结构。

说明2:为使实验程序标准化、且简洁直观,给出二叉树的结点结构。

//二叉链表的结构

typedef  char   datatype;

typedef struct BiNode

{

    datatype data;

    struct BiNode  *lchild, *rchild;

}bitree;

说明3:完成实验任务的同学请将实验报告以及源码文件以附件形式提交到MOOC平台上,实验报告命名为:实验报告六.doc  源码程序命名为:test6.c,拓展项目保存为huffmancode.c

编程要求:

(1)输入和输出都要有说明性语句提示;

         例如:printf(“请输入结点个数:”);

               Scanf(“%d”,&len);

(2)代码整齐,一句一行,变量命名尽量见名之意

2.实验内容及要求:

在上一次实验的基础上,(已经创建好二叉树并且进行了前中后序遍历),完成本次实验。

基础实验项目

1.以递归方式计算二叉树深度,函数名Depth(bitree *root);

2.以递归方式计算结点总数,函数名Count(bitree *root)

3. 以递归方式计算叶子结点总数,函数名leafNum(bitree  *root)

4. 以递归方式删除整颗二叉树,函数名deleteTree()

拓展实验项目

创建哈夫曼树并输出

#include <stdio.h>
#include <stdlib.h>
#define Maxsize 20

//二叉链表的结构
typedef  char   datatype;
typedef struct BiNode
{
	datatype data;
	struct BiNode* lchild, * rchild;
}bitree;
//非递归前序遍历所需要使用的栈----使用链栈最佳,无需考虑栈溢出这种情况
typedef struct Stack {
	//元素设置为树的结点
	bitree* Node;
	struct Stack* next;
}PreStack;

//前序遍历的递归算法
void   PreOrder(bitree* root);
//中序遍历的递归算法
void InOrder(bitree* root);
//后序遍历的递归算法
void  PostOrder(bitree* root);
//前序遍历的非递归算法
void  PreOrder1(bitree* root);
//创建空链栈
PreStack* InitLinkStack();
//入栈
void PushElem(PreStack* head, bitree* Node);
//出栈---设置为直接输出出栈元素
void PopElem(PreStack* head, bitree** Node);

//以递归方式创建二叉树
bitree* creatBitree();
//删除二叉树
void deleteTree(bitree* root);

//计算二叉树的深度
int  Depth(bitree* root);
//计算结点总数
int Count(bitree* root);  //n为结点总数
//计算叶子结点总数
int leafNum(bitree* root);

//***选做***以广义表的形式输出二叉树结构
void displayBitree(bitree* root);


int main(int argc, char* argv[])
{
	bitree* root = NULL;
	int depthOfTree = 0;
	int n = 0, n0 = 0, x = 0;

	printf("创建二叉树,请输入二叉树中的结点值(字符):\n");
	root = creatBitree();

	printf("\n二叉树的前序遍历序列为  : ");
	if (root != NULL) PreOrder(root);
	printf("\n二叉树的中序遍历序列为  : ");
	if (root != NULL) InOrder(root);
	printf("\n二叉树的后序遍历序列为  : ");
	if (root != NULL) PostOrder(root);
	printf("\n二叉树的前序序列(非递归): ");
	if (root != NULL) PreOrder1(root);

	//以广义表的形式输出二叉树结构
	printf("\n以广义表的形式输出二叉树结构:\n ");
	displayBitree(root);

	depthOfTree = Depth(root);
	printf("\n二叉树的高度为:%d\n ", depthOfTree);

	n = Count(root);
	printf("\n二叉树的结点总数为:%d\n ", n);

	n0 = leafNum(root);
	printf("\n二叉树的叶子结点总数为:%d\n ", n0);

	deleteTree(root);

	printf("\n二叉树已被删除,谢谢使用!\n ");
	return 0;
}

//以递归方式创建二叉树
bitree* creatBitree()
{
	char ch = 'a';
	printf("请输入:");
	scanf_s("%c", &ch, sizeof(char));
	getchar();//清空输入的缓存区域----scanf会吸收回车键,如果不加入,则导致无限递归,造成程序的栈溢出
	if (ch == '#') {
		return NULL;
	}
	else {
		bitree* boot = (bitree*)malloc(sizeof(bitree));
		if (!boot)exit(-1);
		boot->data = ch;
		boot->lchild = creatBitree();
		boot->rchild = creatBitree();
		return boot;
	}
}

/*在哪个位置输出, 就属于什么遍历类型*/
//前序遍历的递归算法
void   PreOrder(bitree* root)
{
	if (root == NULL)
		return;
	else {
		printf("%c", root->data);
		PreOrder(root->lchild);
		PreOrder(root->rchild);
	}
}
//中序遍历的递归算法
void InOrder(bitree* root)
{
	if (root == NULL)
		return;
	else {
		PreOrder(root->lchild);
		printf("%c", root->data);
		PreOrder(root->rchild);
	}
}
//后序遍历的递归算法
void  PostOrder(bitree* root)
{
	if (root == NULL)
		return;
	else {
		PreOrder(root->lchild);
		PreOrder(root->rchild);
		printf("%c", root->data);
	}
}
//前序遍历的非递归算法---每扫描一个结点,将其输出并压入栈;左子树为空,则出栈扫描右子树(分治、dp)
void  PreOrder1(bitree* root)
{
	//存放数据的栈的头结点
	PreStack* head = InitLinkStack();
	//p为指向当前结点的指针或扫描指针
	bitree* p = root;
	while (p || head->next != NULL)
	{
		while (p)
		{
			printf("%c", p->data);
			PushElem(head, p);
			p = p->lchild;
		}
		if (head->next != NULL)
		{
			PopElem(head, &p);
			p = p->rchild;
		}
	}
}
//创建空链栈
PreStack* InitLinkStack()
{
	PreStack* head = (PreStack*)malloc(sizeof(PreStack));
	if (!head)exit(-1);
	head->next = NULL;
}
//入栈
void PushElem(PreStack* head, bitree* Node)
{
	PreStack* t = (PreStack*)malloc(sizeof(PreStack));
	if (!t)exit(-1);
	t->Node = Node;
	t->next = head->next;
	head->next = t;
}
//出栈---设置为直接输出出栈元素
void PopElem(PreStack* head, bitree** Node)
{
	if (head->next == NULL)
		return;
	PreStack* t = head->next;
	*Node = t->Node;
	head->next = t->next;
	free(t);
}
//删除二叉树
void deleteTree(bitree* root)
{
	if (root)
	{
		//递归删除二叉树------自下而上、先叶后父,分治思想
		deleteTree(root->lchild);
		deleteTree(root->rchild);
		free(root);
	}

}
//计算结点总数
int Count(bitree* root)
{
	if (!root)
		return 0;
	//尾递归,一直搜索到叶子结点然后回溯,+1是因为扫到了叶子结点,属于叶子个数
	return Count(root->rchild) + Count(root->lchild) + 1;
}
//计算叶子结点总数
int leafNum(bitree* root)
{
	//想了好久,还是没找到错误的地方,不建议参考;
	if (root == NULL)return 0;
	else {
		if (root->rchild == NULL && root->lchild == NULL)
			return 1;
		return  Count(root->lchild) + Count(root->rchild);
	}
}
//计算二叉树的深度
int  Depth(bitree* root)
{
	if (root == NULL)
		return 0;
	else
	{
		//兵分两路进行深度搜索,每搜索一次,高度加一;遇到分叉,返回高度最大的那个分支
		int lDepth = Depth(root->lchild);
		int rDepth = Depth(root->rchild);
		return lDepth > rDepth ? lDepth + 1 : rDepth + 1;
	}
}
//***选做***以广义表的形式输出二叉树结构
//按照二叉树在广义表的表达形式:a(b,c)属于一个结点;a(b(c,d),e(f,g))是一个高度为三的慢二叉
void displayBitree(bitree* root)
{
	//先输出父节点
	printf("%c", root->data);
	if (root->lchild)
	{
		//若左子树不为空,先将左括号‘(’输出,然后递归搜索左子树,如果右子树为空,则输出右括号')'
		printf("(");
		displayBitree(root->lchild);
		if (!root->rchild)
			printf(")");
	}
	if (root->rchild)
	{
		//若左子树为空,则输出左括号‘(’,主要是考虑了左子树为空,无法输出左括号的情形
		if (!root->lchild)
			printf("(");
		//输出左右子树的辨识标志‘,’---a(,b(c,d))---一个左子树为空的二叉树的广义表表示
		printf(",");
		//递归搜索右子树
		displayBitree(root->rchild);
		//进行括号匹配
		printf(")");
	}
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

惑星撞地球

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值