赫夫曼编码

 

 

 

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

int m,xiao,dia; 

typedef struct { 
unsigned int weight; 
unsigned int parent,lchild,rchild; 
}HTNode;
typedef HTNode * HuffmanTree; //动态分配数组存储哈夫曼树 
typedef char * HuffmanCode; //动态分配数组存储哈夫曼编码表 

void Select(HuffmanTree HT,int n) 
{ 
int i,j; 
for(i = 1;i <= n;i++) 
   if(!HT[i].parent){xiao = i;break;} 
for(j = i+1;j <= n;j++) 
   if(!HT[j].parent){dia = j;break;} 
for(i = 1;i <= n;i++) 
   if((HT[xiao].weight>HT[i].weight)&&(!HT[i].parent)&&(dia!=i))
       xiao=i;               //找到最小值的索引
for(j = 1;j <= n;j++) 
   if((HT[dia].weight>HT[j].weight)&&(!HT[j].parent)&&(xiao!=j))
       dia=j;               //找到比xiao大的索引
} 

void HuffmanCoding(HuffmanTree HT, HuffmanCode HC[], int *w, int n) { 
// 算法6.13 
// w存放n个字符的权值(均>0),构造哈夫曼树HT, 
// 并求出n个字符的哈夫曼编码HC 
int i, j; 
char *cd; 
int p; 
int cdlen; 

if (n<=1) return; 
m = 2 * n - 1; //所有的顶点数量,树叶数量加上内点数量
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode)); // 0号单元未用 
for (i=1; i<=n; i++) { //初始化 
   HT[i].weight=w[i-1]; 
   HT[i].parent=0; 
   HT[i].lchild=0; 
   HT[i].rchild=0; 
} 
for (i=n+1; i<=m; i++) { //初始化 
   HT[i].weight=0; 
   HT[i].parent=0; 
   HT[i].lchild=0; 
   HT[i].rchild=0; 
} 

puts("\n哈夫曼树的构造过程如下所示:"); 
printf("HT初态:\n 结点 weight parent lchild rchild"); 
for (i=1; i<=m; i++) 
printf("\n%4d%8d%8d%8d%8d",i,HT[i].weight, HT[i].parent,HT[i].lchild, HT[i].rchild); 
printf(" 按任意键,继续 ..."); 
getchar(); 

for (i=n+1; i<=m; i++)  // 建哈夫曼树 
{ 
   // 在HT[1..i-1]中选择parent为0且weight最小的两个结点, 
   // 其序号分别为s1和s2。 
   Select(HT, i-1); 
   HT[xiao].parent = i; HT[dia].parent = i; 
   HT[i].lchild = dia; HT[i].rchild = xiao; 
   HT[i].weight = HT[xiao].weight + HT[dia].weight; 
   printf("\nselect: dia=%d xiao=%d\n", dia, xiao); 
   printf(" 结点 weight parent lchild rchild"); 
   for (j=1; j<=i; j++) 
   printf("\n%4d%8d%8d%8d%8d",j,HT[j].weight, HT[j].parent,HT[j].lchild, HT[j].rchild); 
   printf(" 按任意键,继续 ..."); 
   getchar(); 

   while(getchar()!='\n')
	continue;         //删除多余的换行符
} 

//------无栈非递归遍历哈夫曼树,求哈夫曼编码 
cd = (char *)malloc(n*sizeof(char)); // 分配求编码的工作空间 
p = m; cdlen = 0; 
for (i=1; i<=m; ++i) // 遍历哈夫曼树时用作结点状态标志 
HT[i].weight = 0; 

while (p)
{ 
   if (HT[p].weight==0) 
   { // 向左 
        HT[p].weight = 1; 
        if (HT[p].lchild != 0) 
        { 
              p = HT[p].lchild; 
              cd[cdlen++] ='0'; 
        } 
        else if (HT[p].rchild == 0) 
        { // 登记叶子结点的字符的编码 
             HC[p] = (char *)malloc((cdlen+1) * sizeof(char)); 
             cd[cdlen] ='\0'; 
             strcpy(HC[p], cd); // 复制编码(串) 
      } 
   } else if (HT[p].weight==1)
   { // 向右 
      HT[p].weight = 2; 
      if (HT[p].rchild != 0) 
      { 
            p = HT[p].rchild; 
           cd[cdlen++] ='1'; 
      } 
  } 
  else 
  { // HT[p].weight==2,退回退到父结点,编码长度减1 
     HT[p].weight = 0; p = HT[p].parent; --cdlen; 
  } 
} 

} // HuffmanCoding 

int main(void) { 
HuffmanTree HT;HuffmanCode *HC;int *w,n,i; 
puts("输入结点数:"); 
scanf("%d",&n); 
HC = (HuffmanCode *)malloc(n*sizeof(HuffmanCode)); 
w = (int *)malloc(n*sizeof(int)); 
printf("输入%d个结点的权值\n",n); 
for(i = 0;i < n;i++) 
scanf("%d",&w[i]); 
HuffmanCoding(HT,HC,w,n); 
puts("\n各结点的哈夫曼编码:"); 
for(i = 1;i <= n;i++) 
printf("%2d(%4d):%s\n",i,w[i-1],HC[i]); 
getchar(); 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值