实验十一、构造赫夫曼树

1 实验目的

本实验是要实现赫夫曼树的构造和编码,通过该实验更深刻地理解赫夫曼树的构造和编码过程。

2 实验内容

根据表11.1构造一棵赫夫曼树,输出对应的赫夫曼编码和带树路径长度。

表11.1 单词及出现的频度
单词 The of a to and in that he is at on for His are be
频度 1192 677 541 518 462 450 242 195 190 181 174 157 138 124 123


Code

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

//******宏定义参数******
#define NO 0
#define OK 1
#define EORRO 0
#define WordMaxSize 10
#define DATAMAXSIZE 10000

//******定义数据类型别名******
typedef int Status;

//******声明数据结构******
typedef struct
{
	int Size;
	char word[WordMaxSize];
}ElemType;

typedef struct TNode
{
	ElemType data;
	struct TNode *lchild;
	struct TNode *rchild;
}BinaryTree,*BiTreePoint;

typedef struct LNode
{
	BiTreePoint data;
	struct LNode *next;
}ListNode,*ListPoint;

typedef struct
{
	int length;
	ListPoint next;
}HeadNode,*HeadPoint;

//******以下为二叉树数据结构操作******
BiTreePoint InitBiTree()
{
	return NULL;
}

Status BiTreeEmpty(BiTreePoint T)
{
	if(T==NULL)
		return OK;
	return NO;
}

void BiTreeDelete(BiTreePoint *T) //释放HuffmanTree
{
	if(*T==NULL)
		return ;
	BiTreeDelete(&(*T)->lchild);
	BiTreeDelete(&(*T)->rchild);
	free(*T);
	return ;
}

void previsitHuffmanTree(BiTreePoint T,char *s,int ans) //先序访问huffman树,结点编码
{
	if(T==NULL)
		return ;
	else if(T->lchild==NULL && T->rchild==NULL)
	{
		s[ans]=0;
		printf("单词:%s 频数:%d 编码:%s\n",T->data.word,T->data.Size,s);
		return ;
	}
	s[ans]='1';
	previsitHuffmanTree(T->lchild,s,ans+1);
	s[ans]='0';
	previsitHuffmanTree(T->rchild,s,ans+1);
	return ;
}

unsigned int HuffmanWPL(BiTreePoint T,unsigned int L)
{
	if(T==NULL)
		return 0;
	else if(T->lchild==NULL && T->rchild==NULL)
		return T->data.Size*L;
	return HuffmanWPL(T->lchild,L+1)+HuffmanWPL(T->rchild,L+1);
}
//******以上为二叉树数据结构操作******

//******以下为链表操作******
ListPoint ListNode_Search(ListPoint Head,int ans)
{
	if(Head->next==NULL || Head->next->data->data.Size > ans)
		return Head;
	return ListNode_Search(Head->next,ans);
}

ListPoint Init(int *n)
{
	ListPoint Head,p,q;
	int ans;
	char temp[10]={'1'};
	Head=NULL;
	while(gets(temp) && temp[0]!='0')
	{
		scanf("%d ",&ans);
		q=(ListPoint)malloc(sizeof(ListNode));
		q->data=(BiTreePoint)malloc(sizeof(BinaryTree));
		q->data->data.Size=ans;
		strcpy(q->data->data.word,temp);
		q->data->lchild=q->data->rchild=NULL;
		if(*n==0 || Head->data->data.Size>ans) q->next=Head,Head=q;
		else
		{
			p=ListNode_Search(Head,ans);
			q->next=p->next;
			p->next=q;
		}
		*n++;
	}
	return Head;
}

HeadPoint HeadInit()
{
	HeadPoint Head;
	Head=(HeadPoint)malloc(sizeof(HeadNode));
	Head->length=0;
	Head->next=Init(&Head->length);
	return Head;
}

BiTreePoint CreatHuffmanTree(ListPoint *Head)
{
	ListPoint q,p,temp;
	if(*Head==NULL)
		return NULL;
	while((*Head)->next)
	{
		q=(*Head);
		p=(*Head)->next;
		(*Head)=p->next;
		temp=(ListPoint)malloc(sizeof(ListNode));
		temp->data=(BiTreePoint)malloc(sizeof(BinaryTree));
		strcpy(temp->data->data.word,"Parent");
		if(q->data->data.Size < p->data->data.Size)
		{
			temp->data->lchild=q->data;
			temp->data->rchild=p->data;
		}
		else
		{
			temp->data->lchild=p->data;
			temp->data->rchild=q->data;
		}
		temp->data->data.Size=q->data->data.Size + p->data->data.Size;
		free(q);
		free(p);
		if((*Head) && (*Head)->data->data.Size < temp->data->data.Size)
		{
			q=ListNode_Search((*Head),temp->data->data.Size);
			temp->next=q->next;
			q->next=temp;
		}
		else
		{
			temp->next=(*Head);
			(*Head)=temp;
		}
	}
	return (*Head)->data;
}
//******以上为链表数据结构操作******

int main()
{
	BiTreePoint T;
	HeadPoint Head;
	char *s=(char *)malloc(DATAMAXSIZE*sizeof(char));
	Head=HeadInit();
	T=CreatHuffmanTree(&Head->next);
	printf("\n先序遍历HuffmanTree结点编码:\n");
	previsitHuffmanTree(T,s,0);
	printf("\nHuffmanTree的带权路径长度:\n");
	printf("%u\n",HuffmanWPL(T,0));
	free(s);
	BiTreeDelete(&T);
	return 0;
}

/*
intput:
The
1192
of
677
a
541
and
462
in
450
that
242
he
195
is
190
at
181
on
174
for
157
His
138
are
124
be
123
0
*/