最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会。
希望这些能提供给初学者一些参考。
在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;
}