哈夫曼编码步骤:一、对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,...,Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。
(为方便在计算机上实现算法,一般还要求以Ti的权值Wi的升序排列。
)二、在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
三、从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
四、重复二和三两步,直到集合F中只有一棵二叉树为止。
/*-------------------------------------------------------------------------* Name: 哈夫曼编码源代码。
* Date: 2011.04.16 * Author: Jeffrey Hill+Jezze(解码部分)* 在Win-TC 下测试通过* 实现过程:着先通过HuffmanTree() 函数构造哈夫曼树,然后在主函数main()中* 自底向上开始(也就是从数组序号为零的结点开始)向上层层判断,若在* 父结点左侧,则置码为0,若在右侧,则置码为1。
最后输出生成的编码。
*------------------------------------------------------------------------*/#include <stdio.h>#include<stdlib.h>#define MAXBIT 100#define MAXVALUE 10000#define MAXLEAF 30#define MAXNODE MAXLEAF*2 -1typedef struct {int bit[MAXBIT];int start;} HCodeType; /* 编码结构体*/typedef struct{int weight;int parent;int lchild;int rchild;int value;} HNodeType; /* 结点结构体*//* 构造一颗哈夫曼树*/void HuffmanTree (HNodeType HuffNode[MAXNODE], int n){/* i、j:循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。
*/int i, j, m1, m2, x1, x2;/* 初始化存放哈夫曼树数组HuffNode[] 中的结点*/for (i=0; i<2*n-1; i++){HuffNode[i].weight = 0;//权值HuffNode[i].parent =-1;HuffNode[i].lchild =-1;HuffNode[i].rchild =-1;HuffNode[i].value=i;//实际值,可根据情况替换为字母} /* end for *//* 输入n 个叶子结点的权值*/for (i=0; i<n; i++){printf ("Please input weight of leaf node %d: \n", i);scanf ("%d", &HuffNode[i].weight);} /* end for *//* 循环构造Huffman 树*/for (i=0; i<n-1; i++){m1=m2=MAXV ALUE;/* m1、m2中存放两个无父结点且结点权值最小的两个结点*/x1=x2=0;/* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树*/ for (j=0; j<n+i; j++){if (HuffNode[j].weight < m1 && HuffNode[j].parent==-1) { m2=m1;x2=x1;m1=HuffNode[j].weight;x1=j;}else if (HuffNode[j].weight < m2 && HuffNode[j].parent==-1) {m2=HuffNode[j].weight;x2=j;}} /* end for *//* 设置找到的两个子结点x1、x2 的父结点信息*/HuffNode[x1].parent = n+i;HuffNode[x2].parent = n+i;HuffNode[n+i].weight = HuffNode[x1].weight + HuffNode[x2].weight; HuffNode[n+i].lchild = x1;HuffNode[n+i].rchild = x2;printf ("x1.weight and x2.weight in round %d: %d, %d\n", i+1, HuffNode[x1].weight, HuffNode[x2].weight);/* 用于测试*/printf ("\n");} /* end for *//*for(i=0;i<n+2;i++){printf("Parents:%d,lchild:%d,rchild:%d,value:%d,weight:%d\n",HuffNode[i].parent,HuffNode[i].l child,HuffNode[i].rchild,HuffNode[i].value,HuffNode[i].weight);}*///测试}/* end HuffmanTree *///解码void decodeing(char string[],HNodeType Buf[],int Num){int i,tmp=0,code[1024];int m=2*Num-1;char *nump;char num[1024]for(i=0;i<strlen(string);i++){if(string[i]=='0')num[i]=0;else num[i]=1;}i=0;nump=&num[0];while(nump<(&num[strlen(string)])){tmp=m-1;while((Buf[tmp].lchild!=-1)&&(Buf[tmp].rchild!=-1)){if(*nump==0){tmp=Buf[tmp].lchild ;}else tmp=Buf[tmp].rchild;nump++;}printf("%d",Buf[tmp].value);}}int main(void){HNodeType HuffNode[MAXNODE]; /* 定义一个结点结构体数组*/ HCodeType HuffCode[MAXLEAF], cd;/* 定义一个编码结构体数组,同时定义一个临时变量来存放求解编码时的信息*/int i, j, c, p, n;char pp[100];printf ("Please input n:\n");scanf ("%d", &n);HuffmanTree (HuffNode, n);for (i=0; i < n; i++){cd.start = n-1;c = i;p = HuffNode[c].parent;while (p != -1)/* 父结点存在*/{if (HuffNode[p].lchild == c)cd.bit[cd.start] = 0;elsecd.bit[cd.start] = 1;cd.start--;/* 求编码的低一位*/c=p;p=HuffNode[c].parent;/* 设置下一循环条件*} /* end while *//* 保存求出的每个叶结点的哈夫曼编码和编码的起始位*/ for (j=cd.start+1; j<n; j++){HuffCode[i].bit[j] = cd.bit[j];}HuffCode[i].start = cd.start;} /* end for *//* 输出已保存好的所有存在编码的哈夫曼编码*/for (i=0; i<n; i++){printf ("%d 's Huffman code is: ", i);for (j=HuffCode[i].start+1; j < n; j++){printf ("%d", HuffCode[i].bit[j]);}printf(" start:%d",HuffCode[i].start);printf ("\n");}/*for(i=0;i<n;i++){for(j=0;j<n;j++){printf ("%d", HuffCode[i].bit[j]);}printf("\n");}*/printf("Decoding?Please Enter code:\n");scanf("%s",&pp);decodeing(pp,HuffNode,n);getch();return 0;}解码#include "string.h"#include "stdio.h"#define MAXVALUE 1000 /*定义最大权值*/#define MAXLEAF 30 /*定义哈夫曼树叶结点个数*/#define MAXNODE MAXLEAF*2-1#define MAXBIT 30 /*定义哈夫曼编码的最大长度*/typedef struct{ int bit[MAXBIT];int start;} HCODETYPE;typedef struct{ int weight;int parent;int lchild;int rchild;} HNODETYPE;char *getcode1(char *s1,char *s2,char *s3) /*首先去掉电文中的空格*/{ char temp[128]="",*p,*q;p=s1;while ((q=strstr(p,s2))!=NULL){ *q='\0';strcat(temp,p);strcat(temp,s3);p=q+strlen(s2); }strcat(temp,p);strcpy(s1,temp);return s1;}/*再去掉重复出现的字符(即压缩电文),提取哈夫曼树叶结点*/ char * getcode (char *s1){ char s2[26],s5[26];char temp[200]="",*p,*q,*r,*s3="";int m,e,n=0;m=strlen(s1);while(m>0){ p=s1;s2[0]=s1[0];s2[1]='\0';r=s2;e=0;while((q=strstr(p,r))!=NULL){ *q='\0';strcat(temp,p);strcat(temp,s3);p=q+strlen(s2);e++; }m-=e;strcat(temp,p);strcpy(s1,temp);s5[n]=s2[0];n++;strcpy(temp,"");}s5[n]='\0';strcpy(s1,s5);printf(" 压缩后的电文(即叶结点): %s\n",s1);return s1;}HNODETYPE huffmantree(char *s2,char s3[]){ HNODETYPE huffnode[MAXNODE];HCODETYPE huffcode[MAXLEAF],cd;int sum,i,j,n1,n2,x1,x2,p,k,c;char s1[26]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};char s5[MAXLEAF];int ww[26]={0},n=0;strcpy( s5,s2);sum=strlen(s2);for(i=0;i<26;i++) /*统计所有字符出现的频度*/for(j=0;j<sum;j++)if(s2[j]==s1[i]) ww[i]++;n=strlen(s3);for (i=0;i<2*n-1;i++){ huffnode[i].weight=0;huffnode[i].parent=-1;huffnode[i].lchild=-1;huffnode[i].rchild=-1; }for(i=0;i<n;i++) /*分配给各叶结点权值*/for(j=0;j<26;j++)if (s3[i]==s1[j]) huffnode[i].weight=ww[j];for (i=0;i<n-1;i++) /*构造哈夫曼树*/{ n1=n2=MAXVALUE;x1=x2=0;for(j=0;j<n+i;j++){ if (huffnode[j].parent==-1 && huffnode[j].weight<n1){ n2=n1;x2=x1;n1=huffnode[j].weight;x1=j; }elseif (huffnode[j].parent==-1 && huffnode[j].weight<n2){ n2=huffnode[j].weight; x2=j;}}huffnode[x1].parent=n+i;huffnode[x2].parent=n+i;huffnode[n+i].weight=huffnode[x1].weight+huffnode[x2].weight; huffnode[n+i].lchild=x1;huffnode[n+i].rchild=x2;}for(i=0;i<n;i++) /*求每个叶结点的哈夫曼编码*/{ cd.start=n-1;c=i;p=huffnode[c].parent;while (p!=-1){ if (huffnode[p].lchild==c)cd.bit[cd.start]=0;elsecd.bit[cd.start]=1;cd.start--;c=p;p=huffnode[c].parent;}for (j=cd.start+1;j<n;j++)huffcode[i].bit[j]=cd.bit[j];huffcode[i].start=cd.start;}printf(" 各叶结点对应哈夫曼编码: ");/*输出每个叶结点的哈夫曼编码*/for(i=0;i<n;i++){ for(j=huffcode[i].start+1;j<n;j++)printf("%d",huffcode[i].bit[j]);printf(" ");}printf("\n 电文的全部哈夫曼编码: ");/*输出电文的全部哈夫曼编码*/ for(k=0;k<sum;k++)for(i=0;i<n;i++)if(s2[k]==s3[i]){ for(j=huffcode[i].start+1;j<n;j++)printf("%d",huffcode[i].bit[j]);printf(" "); }printf("\n");}main(){char s1[MAXLEAF],s2[MAXLEAF];printf("\n 请输入电文: ");gets(s1);strcpy(s2,getcode1(s1," ",""));huffmantree(s1,getcode(s2));}nclude<string.h>#include<stdlib.h>#include<stdio.h>int m,s1,s2;typedef struct {unsigned int weight;unsigned int parent,lchild,rchild;}HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表void Select(HuffmanTree HT,int n) {int i,j;for(i = 1;i <= n;i++)if(!HT[i].parent){s1 = i;break;}for(j = i+1;j <= n;j++)if(!HT[j].parent){s2 = j;break;}for(i = 1;i <= n;i++)if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i))s1=i;for(j = 1;j <= n;j++)if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j))s2=j;}void HuffmanCoding(HuffmanTree &HT, HuffmanCode HC[], int *w, int n) {// 算法6.13// w存放n个字符的权值(均>0),构造哈夫曼树HT,// 并求出n个字符的哈夫曼编码HCint 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。