回 帖 发 新 帖 刷新版面

主题:产生哈夫曼编码的源代码

#include"stdio.h"
#include"stdlib.h"
#include"string.h"

typedef char ElemType;
typedef struct
{
   ElemType elem;
   unsigned int m_weight;
   unsigned int parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef char** HuffmanCode;
typedef int Status;
typedef struct weight
{
  char elem;
  unsigned int m_weight;
}Weight; // save the information of the symbolizes;

void HuffmanCoding(HuffmanTree *,HuffmanCode *,Weight *,int);
void Select(HuffmanTree,int,int *,int *);
void OutputHuffmanCode(HuffmanTree,HuffmanCode,int);

Status main(void)
{
  HuffmanTree HT;
  HuffmanCode HC;
  Weight *w;
  char c;     // the symbolizes;
  int i,n;      // the number of elements;
  int wei;    // the weight of a element;

  printf("input the tatol number of the Huffman Tree:" );
  scanf("%d",&n);
  w=(Weight *)malloc(n*sizeof(Weight));
  for(i=0;i<n;i++)
  {
    printf("input the element & its weight:");
    scanf("%1s%d",&c,&wei);
    w[i].elem=c;
    w[i].m_weight=wei;
  }

  HuffmanCoding(&HT,&HC,w,n);
  OutputHuffmanCode(HT,HC,n);
  return 1;

}

void HuffmanCoding(HuffmanTree *HT,HuffmanCode *HC,Weight *w,int n)
{
  int i,m,s1,s2,start,c,f;
  char *cd;
  HuffmanTree p;
  if(n<=1)
  return;

  m=2*n-1;
  (*HT)=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
  for(i=1;i<=n;++i)
  {
     (*HT)[i].elem=w[i-1].elem;
     (*HT)[i].m_weight=w[i-1].m_weight;
     (*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0;
  }

  for(;i<=m;++i)
  {
    (*HT)[i].elem='0';
    (*HT)[i].m_weight=(*HT)[i].parent=(*HT)[i].lchild=(*HT)[i].rchild=0;
  }

  for(i=n+1;i<=m;++i)
  {
    Select(*HT,i-1,&s1,&s2);
    (*HT)[s1].parent=i;(*HT)[s2].parent=i;
    (*HT)[i].lchild=s1;(*HT)[i].rchild=s2;
    (*HT)[i].m_weight=(*HT)[s1].m_weight+(*HT)[s2].m_weight;
  }

  (*HC)=(HuffmanCode)malloc(n*sizeof(char*));
  cd=(char *)malloc(n*sizeof(char));
  cd[n-1]='\0';
  for(i=1;i<=n;++i)
  {
     start=n-1;
     for(c=i,f=(*HT)[i].parent;f!=0;c=f,f=(*HT)[f].parent)
 {
       if((*HT)[f].lchild==c) cd[--start]='0';
       else cd[--start]='1';
     }

     (*HC)[i]=(char *)malloc((n-start)*sizeof(char));
     strcpy((*HC)[i],&cd[start]);
  }
}

void Select(HuffmanTree HT,int n,int *s1,int *s2)
{
  int i;
  (*s1)=(*s2)=0;
  for(i=1;i<=n;i++)
  {
    if(HT[i].m_weight<HT[(*s2)].m_weight&&HT[i].parent==0&&(*s2)!=0)
{
      if(HT[i].m_weight<HT[(*s1)].m_weight)
  {
  (*s2)=(*s1);
  (*s1)=i;
      }
      else (*s2)=i;

    }

    if(((*s1)==0||(*s2)==0)&&HT[i].parent==0)
{
      if((*s1)==0) (*s1)=i;
      else if((*s2)==0)
  {
  if(HT[i].m_weight<HT[(*s1)].m_weight)
  {
  (*s2)=(*s1);
  (*s1)=i;
  }
  else (*s2)=i;
      } // end of else if
    } // end of if
  } // end of for

  if((*s1)>(*s2))
  {
    i=(*s1);
(*s1)=(*s2);
(*s2)=i;
  }
  return;
}

void OutputHuffmanCode(HuffmanTree HT,HuffmanCode HC,int n)
{
  int i;
  printf("\nnumber---element---weight---huffman code\n");
  for(i=1;i<=n;i++)
    printf("  %d        %c         %d        %s\n",i,HT[i].elem,HT[i].m_weight,HC[i]);

回复列表 (共24个回复)

沙发

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*                                                                  *
*HUFF.C Huffman encode for multimedia application 8*8 pixel Ver 3  *
*                                                                  *
*Ver 1:  Complied in Borland Turbo C++ 3.0                         *
*Ver 2:  Complied in Microsoft Visual C++ 6.0                      *
*Ver 3:  Complied in Microsoft Visual C++ 6.0                      *
*          add code to print code table of the compression         *
*          print output message in Chinese                         *
*                                                                  *
*by Lee Meitz, Solid Mechanics, Huazhong Univ of Sci and Tech      *
*2001.11.15 - 2001.12.27                                           *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define  DNUM 64    //define data number 8*8
#define  LOOP 10000 //times of compression

typedef struct
{
    unsigned short weight, data;
    unsigned short parent, lchild, rchild;
} HuffNode;

typedef struct
{
    unsigned char code;
    unsigned short codelength;
} HuffCode;

unsigned int fCount[256] = {0};
unsigned int data_num;
unsigned int code_size;
unsigned int last_bit;
void FrequencyCount(unsigned char*);         //频率统计
void HuffSelect(HuffNode*, int, int*, int*); //从结点中选出权最小的两个节点
void HuffmanCodeTable(HuffNode*, HuffCode*); //构造huffman树,生成huffman编码表
void HuffmanCompress(unsigned char*, unsigned char *, HuffCode*); //压缩数据
void BitPrint(unsigned char*);               //按位打印结果,用于调试

void main()
{
    int i, j, loop;                               //variable for loop
    HuffNode hfdata[2*DNUM] = {{0, 0, 0, 0, 0}};  //Huffman node
    HuffCode code_table[256] = {{0, 0}};          //code table will be searched by subscript
    unsigned char hfcode[2*DNUM];                 //output code
    time_t time1, time2;
/*  unsigned char pixel[DNUM] = {
    1,2,3,4, 1,2,3,4, 1,2,3,4, 1,1,1,1};
*/
/*  unsigned char pixel[DNUM] = {
        139,144,149,153,155,155,155,155,
        144,151,153,156,159,156,156,156,
        150,155,160,163,158,156,156,156,
        159,161,162,160,160,159,159,159,
        159,160,161,162,162,155,155,155,
        161,161,161,161,160,157,157,157,
        162,162,161,163,162,157,157,157,
        162,162,161,161,163,158,158,158};
*/
    unsigned char pixel[DNUM] = { //random data
        141, 101, 126, 111, 163, 112, 133, 156,
        103, 144, 111, 176, 117, 120, 188, 187,
        175, 164, 190, 156, 112, 179, 142, 119,
        140, 111, 127, 186, 196, 190, 189, 127,
        185, 103, 185, 110, 192, 139, 159, 104,
        151, 193, 178, 198, 114, 170, 179, 149,
        124, 149, 165, 108, 141, 176, 113, 164,
        101, 140, 120, 126, 173, 189, 158, 184};
/*  unsigned char pixel[DNUM] = {
        202, 221, 159, 183, 41, 136, 247, 66,
        146, 29, 101, 108, 45, 61, 210, 236,
        90, 130, 54, 66, 132, 206, 119, 232,
        184, 135, 96, 78, 120, 41, 231, 203,
        150, 94, 172, 142, 122, 180, 150, 204,
        232, 121, 180, 221, 3, 207, 115, 147,
        72, 149, 169, 121, 76, 208, 235, 43,
        107, 58, 0, 237, 197, 7, 210, 89};
*/
    FrequencyCount(pixel);
    time1 = time(NULL);
    for (loop=0; loop<LOOP; loop++) {
        //set huffman nodes data and weight, i=0:255, j=1:64
        for (i=0, j=1, data_num=0; i<256; i++) {
            if (fCount[i]) {
                hfdata[j].weight = fCount[i];
                hfdata[j++].data = i;
                data_num ++;
            }
        }
        //build huffman tree and generate huffman code table
        HuffmanCodeTable(hfdata, code_table);
        //compress source data to huffman code using code table
        HuffmanCompress(pixel, hfcode, code_table);
        //initial hfdata and code_table
        for (j=0; j<2*DNUM; j++) {
            hfdata[j].data=0;
            hfdata[j].lchild=0;
            hfdata[j].parent=0;
            hfdata[j].rchild=0;
            hfdata[j].weight=0;
        }
    }
    time2 = time(NULL);
    //conclude
    printf("\n哈夫曼编码压缩图块,压缩报告\n华中科技大学力学系:李美之\n");
    printf("\n◎源数据(%d字节):\n ", DNUM);
    for (i=0; i<DNUM; i++) {
        printf(i%8==7 ? "%02X\n " : "%02X ", pixel[i]);
    }
    printf("\n◎压缩数据(%d字节):\n ", code_size);
    for (i=0; i<code_size; i++) {
        printf(i%8==7 ? "%02X\n " : "%02X ", hfcode[i]);
    }
    //打印码表
    printf("\n\n◎码表-编码字典(%d项)\n", data_num);
    for (i=0; i<256; i++) {
        if (code_table[i].codelength) {
            printf("%3d|%02X: ", i, i);
            for (j=0; j<code_table[i].codelength; j++) {
                printf("%d", ((code_table[i].code << j)&0x80)>>7);
            }
            printf("\t");
        }
    }
    printf("\n\n◎压缩率:%2.0f%% \t压缩时间:%.3f毫秒\n",(float)code_size/DNUM * 100, 1E3*(time2-time1)/LOOP);
}

void BitPrint(unsigned char *hfcode)
{
    int i, j;
    int endbit = last_bit;
    unsigned char thebyte;
    for (i=0; i < code_size-1; i++) {
        thebyte = hfcode[i];
        for (j=0; j<8; j++) {
            printf("%d", ((thebyte<<j)&0x80)>>7);
        }
    }
    if (last_bit == 7) {
        endbit = -1;
    }
    thebyte = hfcode[i];
    for (j=7; j>endbit; j--) {
        printf("%d", ((thebyte<<(7-j))&0x80)>>7);
    }
}

void HuffmanCompress(unsigned char *pixel, unsigned char *hfcode, HuffCode * code_table)
{
    int i, j;
    int curbit=7; //current bit in _thebyte_
    unsigned int bytenum=0; //number of destination code can also be position of byte processed in destination
    unsigned int ptbyte=0; //position of byte processed in destination
    unsigned int curlength; //code's length of _curcode_
    unsigned char curcode; //current byte's huffman code
    unsigned char thebyte=0; //destination byte write
    unsigned char value; //current byte's value (pixel[])
    //process every byte
    for (i=0; i<DNUM; i++) {
        value = pixel[i];
        curcode = (code_table[value]).code;
        curlength = (code_table[value]).codelength;
        //move out every bit from curcode to destination
        for (j=0;j<=curlength;j++) {
            if ((curcode<<j)&0x80) {
                thebyte |= (unsigned char)(0x01<<curbit);
            }
            curbit --;
            if (curbit < 0) {
                hfcode[ptbyte++] = thebyte;
                thebyte = 0;
                curbit  = 7;
                bytenum ++;
            }
        }
    }
    //think about which bit is the end
    if (curbit != 7) {
        hfcode[ptbyte] = thebyte;
        bytenum ++;
    }
    code_size = bytenum;
    last_bit  = curbit;
}

void HuffmanCodeTable(HuffNode *hfdata, HuffCode *code_table)
{
    int i, j; //variable for loop
    int tree_num = 2*data_num - 1; //node of huffman tree
    int min1, min2; //two minimum weight
    int p; //the id of parent node
    unsigned char curcode; //current code being processing
    int curlength; //current code's length
    //build huffman tree
    for (i=data_num; i<tree_num; i++) {
        HuffSelect(hfdata, i, &min1, &min2);
        hfdata[min1].parent = i+1;
        hfdata[min2].parent = i+1;
        hfdata[i+1].lchild = min1;
        hfdata[i+1].rchild = min2;
        hfdata[i+1].weight = hfdata[min1].weight + hfdata[min2].weight;
    }
    //generate huffman code
    //i present the i th code, j present from leaf to root in huffman tree
    //hfdata[i].data (0:255) is a byte number
    //编码从叶读到根,按位从高往低压入一个字节,读编码从左向右
    for (i=1; i<=data_num; i++) {
        curcode = 0;
        curlength = 0;
        for (j=i, p=hfdata[j].parent; p!=0; j=p, p=hfdata[j].parent) {
            curlength ++;
            if (j==hfdata[p].lchild) curcode >>= 1;
            else curcode = (curcode >> 1) | 0x80; //0x80 = 128 = B1000 0000
        }
        code_table[hfdata[i].data].code = curcode;
        code_table[hfdata[i].data].codelength = curlength;
    }
}

void HuffSelect(HuffNode *hfdata, int end, int *min1, int *min2)
{
    int i; //variable for loop
    int s1, s2;
    HuffNode wath[30];
    for (i=0; i<30; i++) {
        wath[i] = hfdata[i];
    }
    s1 = s2 = 1;
    while (hfdata[s1].parent) {
        s1++;
    }
    for (i=2; i<=end; i++) {
        if (hfdata[i].parent == 0 && hfdata[i].weight < hfdata[s1].weight) {
            s1 = i;
        }
    }
    while (hfdata[s2].parent || s1 == s2) {
        s2++;
    }
    for (i=1; i<=end; i++) {
        if (hfdata[i].parent ==0 && hfdata[i].weight < hfdata[s2].weight && (i - s1)) {
            s2 = i;
        }
    }
    *min1 = s1;
    *min2 = s2;
}

void FrequencyCount(unsigned char *chs)
{
    int i;
    for (i=0; i<DNUM; i++) {
        fCount[*(chs+i)] ++;
    }

板凳

有什么用?压缩文件?效率不高呀!有更好算法吗?

3 楼

一种思想。
“白云黄鹤”上有关于压缩的更多源码,可上去看一下。
呵呵,有关版权,我就不拿到这旦来贴了,:)

4 楼

这个好象运行不了 哦?
请问上面2个有哪写区别啊?

5 楼

谢谢,太好了,实在太感谢你了

6 楼

请问版主“白云黄鹤”是什么?网址?

7 楼

如果有空,请帮忙!交一个朋友如何?作好或没好都联系吧!0518-5893512
[问题描述]
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。
[基本要求]
一个完整的系统应具有以下功能:
(1)I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
(2)E:编码(Encoding)。利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
(3)D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
(4)P:印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。
(5)T:印哈夫曼树(Tree printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
[测试数据]
(1)利用下面这道题中的数据调试程序。
某系统在通信联络中只可能出现八种字符,其概率分别为0.25,0.29,0.07,0.08,0.14,0.23,0.03,0.11,试设计哈夫曼编码。
(2)用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。
字符 空格  A   B   C   D   E   F   G   H   I   J   K   L   M
频度 186   64  13  22  32 103  21  15  47  57  1   5   32  20
字符  N    O   P   Q   R   S   T   U   V   W   X   Y   Z
频度  57   63  15  1   48  51  80  23  8   18  1   16  1

[实现提示]
(1) 编码结果以文本方式存储在文件CodeFile中。
(2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出运行Quit。请用户键入一个选择功能符。此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。
(3) 在程序的一次执行过程中,第一次执行I,D或C命令之后,哈夫曼树已经在内存了,不必再读入。每次执行中不一定执行I命令,因为文件hfmTree可能早已建好。

[color=FF0000][/color]

8 楼

其实也不错哦

9 楼

m=2*n-1这个地方改为
m=(n<<1) -1 会不会快些?[em2]

10 楼

我上个学期用四个小时编完 Huffman 被老师说是 不错。
到是  表达式的  那个程序花了一个星期才弄好。

我来回复

您尚未登录,请登录后再回复。点此登录或注册