(编程锻炼)再回首,数据结构——哈夫曼编码的实现

(编程训练)再回首,数据结构——哈夫曼编码的实现

 

       最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会。


       希望这些能提供给初学者一些参考。


       在VC++6.0下可运行,当初还写了不少注释。


【问题描述】

根据给定字符的使用频率,为其设计哈夫曼编码

【基本要求】

·功能:求出n个字符的哈夫曼编码

·输入:输入n个字符和字符在电文中的使用频率

·输出:n个字符的哈夫曼编码


【模块划分】

1.    初始化哈夫曼树函数 InitHuffmanTree()

2.    输入权值函数 InputWeight()

3.    选择两个权值最小的根节点函数SelectMin()

4.    构造哈夫曼树函数 CreateHuffmanTree()

5.求哈夫曼编码函数 Huffmancode()


/*设计哈夫曼编码*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//Huffman树的数据结构
#define n 8			//叶子数目
#define m (n*2-1)		//Huffman树的节点数

//Huffman树的节点
typedef struct
{
	int weight;
	int lchild,rchild,parent;
}HTNode;

//Huffman树的节点数组
typedef HTNode HuffmanTree[m+1];

//Huffman编码的节点
typedef struct
{
	char ch;			
	char code[n+1];
}CodeNode;

//Huffman编码的节点数组
typedef CodeNode HuffmanCode[n+1];

//初始化输入HuffmanTree树的节点
void InitHuffmanTree (HuffmanTree ht)
{
	int i;
	for(i=0;i<=m;i++)
	{
		ht[i].weight=0;
		ht[i].lchild=ht[i].rchild=ht[i].parent=0;
	}
}

//输入HuffmanTree树各节点的权值
void InputHuffmanTree (HuffmanTree ht)
{
	int i;
	for(i=1;i<=n;i++)
	{
		printf("请输入第 %d 个权值: ",i);
		scanf("%d",&ht[i].weight);
	}
	getchar();
}

/*
 * 在ht[1..i]中选择2个权值最小的节点,
 * p1、*p2分别存放最小节点、次小节点的下标 
 */
void SelectMin(HuffmanTree ht, int i, int *p1, int *p2)
{
	int j,min1,min2;
	min1=min2=4294967295;
	*p1=*p2=0;
	for(j=1;j<=i;j++)
		if(0==ht[j].parent)
			if(ht[j].weight<min1 || 4294967295==min1)
			{
				if(4294967295!=min1)
				{
					min2=min1;
					*p2=*p1;
				}
				min1=ht[j].weight;
				*p1=j;
			}
			else
				if(ht[j].weight<min2 || 4294967295==min2)
				{
					min2=ht[j].weight;
					*p2=j;
				}
}

//构建Huffman树
void CreateHuffmanTree (HuffmanTree ht)
{
	int i,p1,p2;

	//初始化Huffman树
	InitHuffmanTree(ht);

	//输入Huffman树的权值
	InputHuffmanTree(ht);

	for(i=n+1;i<=m;i++)
	{
		SelectMin(ht,i-1,&p1,&p2);
		ht[p1].parent=ht[p2].parent=i;
		ht[i].lchild=p1;
		ht[i].rchild=p2;
		ht[i].weight=ht[p1].weight+ht[p2].weight;
	}

}

//根据Huffman树求Huffman编码
void CreateHuffmanCode (HuffmanTree ht, HuffmanCode hcd)
{
	int c,p,s,i,j;	//c、p、s分别代表孩子节点、双亲节点、编码开始位置
	char cd[n+1];
	cd[n]='\0';
	printf("请输入字符: ");
	for(i=1;i<=n;i++)
	{
		hcd[i].ch=getchar();
		c=i;
		s=n;
		while(0!=(p=ht[c].parent))	//一直回溯到根节点
		{
			cd[--s]=(c==ht[p].lchild)?'0':'1';
			c=p;
		}
//		strcpy(hcd[i].code,&cd[s]);
		j=0;
		while((hcd[i].code[j++]=cd[s++])!='\0')
			;
	}
	printf("\n");

	//输出各字符的编码
	for(i=1;i<=n;i++)
		printf("第 %d 个字符 %c 的编码为 %s\n",i,hcd[i].ch,hcd[i].code);
}

int main()
{
	HuffmanTree t;
	HuffmanCode h;
	printf("请输入 %d 个权值\n",n);
	CreateHuffmanTree(t);
	CreateHuffmanCode(t,h);
	return 0;
}


(编程锻炼)再回首,数据结构——哈夫曼编码的实现