数据结构实验报告:二叉树

一、实验目的

1.掌握二叉树的遍历与实现的思想和算法,学会树与二叉树的转换;

2.熟悉哈夫曼树的构造过程.

二、实验环境

windows 10、Visual C++6.0

三、实验内容

1.二叉树的三种遍历算法

#include <stdio.h>
#include <malloc.h>
#include <conio.h>
typedef char DataType;
typedef struct Node
{
	DataType data;
	struct Node *LChild;
	struct Node *RChild;
}BiTNode, *BiTree;
void CreateBiTree(BiTree *bt)
{
	char ch;
	ch = getchar();
    if(ch=='.') *bt=NULL;
    else 
	{
		*bt=(BiTree)malloc(sizeof(BiTNode)); //生成一个新结点
        (*bt)->data=ch;
        CreateBiTree(&((*bt)->LChild)); //生成左子树
        CreateBiTree(&((*bt)->RChild)); //生成右子树
	}
}
void Visit(char ch)
{
	printf("%c",ch);
}

void  PreOrder(BiTree root) 
/*先序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
	if (root!=NULL)
	{
		Visit(root->data);  /*访问根结点*/
		PreOrder(root->LChild);  /*先序遍历左子树*/
		PreOrder(root->RChild);  /*先序遍历右子树*/
	}
}

void  InOrder(BiTree root)  
/*中序遍历二叉树, root为指向二叉树(或某一子树)根结点的指针*/
{
	if (root!=NULL)
	{
		InOrder(root->LChild);   /*中序遍历左子树*/
		Visit(root->data);        /*访问根结点*/
		InOrder(root->RChild);   /*中序遍历右子树*/
	}
}

void  PostOrder(BiTree root)  
/* 后序遍历二叉树,root为指向二叉树(或某一子树)根结点的指针*/
{
	if(root!=NULL)
	{
		PostOrder(root->LChild); /*后序遍历左子树*/
		PostOrder(root->RChild); /*后序遍历右子树*/
		Visit(root->data);       /*访问根结点*/
	}
}

void main()
{
	BiTree T;
	printf("请输入二叉树序列:\n");
    CreateBiTree(&T);
	printf("先序遍历序列为:");
	PreOrder(T);
	printf("\n中序遍历序列为:");
	InOrder(T);
	printf("\n后序遍历序列为:");
	PostOrder(T);
	getch();
//----------------------------------.二叉树的三种遍历算法

2.哈夫曼树的构造和生成

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef char* HuffmanCode;/*动态分配数组,存储哈夫曼编码*/

typedef struct 
{
	unsigned int weight ; /* 用来存放各个结点的权值*/
	unsigned int parent, LChild,RChild ; /*指向双亲、孩子结点的指针*/
}HTNode, * HuffmanTree;   /*动态分配数组,存储哈夫曼树*/

void select(HuffmanTree *ht,int n, int *s1, int *s2)
{
	int i;
	int min;
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent == 0)
		{
			min = i;
			i = n+1;
		}
	}
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent == 0)
		{
			if((*ht)[i].weight < (*ht)[min].weight)
				min = i;
		}
	}
	*s1 = min;
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent == 0 && i!=(*s1))
		{
			min = i;
			i = n+1;
		}
	}
	for(i=1; i<=n; i++)
	{
		if((*ht)[i].parent == 0 && i!=(*s1))
		{
			if((*ht)[i].weight < (*ht)[min].weight)
				min = i;
		}
	}
	*s2 = min;
}

void CrtHuffmanTree(HuffmanTree *ht , int *w, int n)
{ /* w存放已知的n个权值,构造哈夫曼树ht */
	int m,i;
	int s1,s2;
	m=2*n-1;
	*ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode));  /*0号单元未使用*/
	for(i=1;i<=n;i++) 
	{/*1-n号放叶子结点,初始化*/
		(*ht)[i].weight = w[i];
		(*ht)[i].LChild = 0;
		(*ht)[i].parent = 0;
		(*ht)[i].RChild = 0;
	}		
	for(i=n+1;i<=m;i++)
	{
		(*ht)[i].weight = 0;
		(*ht)[i].LChild = 0;
		(*ht)[i].parent = 0;
		(*ht)[i].RChild = 0;
	}    /*非叶子结点初始化*/
/*	------------初始化完毕!对应算法步骤1---------*/
	
	for(i=n+1;i<=m;i++)    /*创建非叶子结点,建哈夫曼树*/
	{  /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2返回*/
		select(ht,i-1,&s1,&s2);
		(*ht)[s1].parent=i;
		(*ht)[s2].parent=i;
		(*ht)[i].LChild=s1;
		(*ht)[i].RChild=s2;
		(*ht)[i].weight=(*ht)[s1].weight+(*ht)[s2].weight;
	} 
}/*哈夫曼树建立完毕*/
void outputHuffman(HuffmanTree HT, int m)
{
	if(m!=0)
	{
		printf("%d  ", HT[m].weight);
		outputHuffman(HT,HT[m].LChild);
		outputHuffman(HT,HT[m].RChild);
	}
}

void CrtHuffmanCode(HuffmanTree *ht, HuffmanCode *hc, int n)
/*从叶子结点到根,逆向求每个叶子结点对应的哈夫曼编码*/
{
	char *cd;
	int i;
	unsigned int c;
	int start;
	int p;
	hc=(HuffmanCode *)malloc((n+1)*sizeof(char *));  /*分配n个编码的头指针*/
	cd=(char * )malloc(n * sizeof(char ));  /*分配求当前编码的工作空间*/
	cd[n-1]='\0';   /*从右向左逐位存放编码,首先存放编码结束符*/
	for(i=1;i<=n;i++)  /*求n个叶子结点对应的哈夫曼编码*/
	{
		start=n-1;    /*初始化编码起始指针*/
		for(c=i,p=(*ht)[i].parent; p!=0; c=p,p=(*ht)[p].parent) /*从叶子到根结点求编码*/
			if( (*ht)[p].LChild == c) 
				cd[--start]='0';  /*左分支标0*/
			else 
				cd[--start]='1';  /*右分支标1*/
	hc[i]=(char *)malloc((n-start)*sizeof(char));  /*为第i个编码分配空间*/
	strcpy(hc[i],&cd[start]);
	}
	free(cd);
	for(i=1;i<=n;i++)
		printf("%d编码为%s\n",(*ht)[i].weight,hc[i]);
}


void main() 
{ 
	HuffmanTree HT; 
	HuffmanCode HC; 
	int *w; 
	int i,n;      // the number of elements; 
	int wei;    // the weight of a element; 
	int m;
	printf("输入哈夫曼树总数:" ); 
	scanf("%d",&n); 
	w=(int *)malloc((n+1)*sizeof(int)); 
	for(i=1;i<=n;i++)
	{ 
		printf("input the %d element's weight:",i); 
		fflush(stdin);
		scanf("%d",&wei); 
		w[i]=wei; 
	} 
	CrtHuffmanTree(&HT,w,n); 
	m = 2*n-1;
	outputHuffman(HT,m); 
	printf("\n");
	CrtHuffmanCode(&HT,&HC,n);
}
//----------------------------------.哈夫曼树的构造和生成

四、实验结果与分析

1.

2a1ff7718e4c421082979556d280c96a.png

分析:树的先序遍历:递归算法,先输出根节点,再以左子树进行递归最后以右子树进行递归。非递归算法,用栈模拟整个递归过程。
树的中序遍历:递归算法,先以左子树进行递归,再输出根节点,最后以右子树进行递归。非递归算法,同上。
树的后序遍历:递归算法,先以左子树进行递归,再后以右子树进行递归,最后输出根节点。非递归算法,同上。

2.

ed7d06e645524d74bfbfdb3cd4a1bd90.png

分析:构建哈夫曼树的关键在于找最小树;在F中选择两棵根结点权值最小的树作为左右子树构造一 棵新的二叉树,且至新的二叉树的根结点的权值为其左右子树上根结点的权值之和。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值