赫夫曼樹與赫夫曼編碼

【問題描述】
    利用Huffman編碼進行通信可以大大提高信道利用率,縮短信息傳輸時間,降低傳輸成本。但是,這要求在發送端通過一個編碼系統對待傳數據預先編碼,在接受端將傳來的數據編碼進行譯碼(復原)。對於有些信道,每端都需要一個完整的編/譯碼系統。試爲這樣的信息收發站編寫一個Huffman的編/譯碼系統。給定一組權值{7,9,5,6,10,1,13,15,4,8},構造一棵赫夫曼樹,並計算帶權路徑長度WPL。

 【數據描述】

//- - - - - 赫夫曼樹的存儲表示 - - - - -

typedef struct {

   unsigned int weight;

   unsigned int parent,lchild,rchild;

}HTNode;    //用順序存儲結構表示赫夫曼樹的結點結構定義

//動態分配數組存儲Huffman編碼表

【算法描述】

1.初始化:從鍵盤讀入n個字符,以及它們的權值,建立Huffman樹
2.編碼:根據建立的Huffman樹,求每個字符的Huffman編碼。對給定的待編碼字符序列進行編碼。
3.譯碼:利用已經建立好的Huffman樹,對上面的編碼結果譯碼。譯碼的過程是分解電文中的字符串,從根結點出發,按字符’0’和’1’確定找左孩子或右孩子,直至葉結點,便求得該子串相應的字符。
4.打印 Huffman樹。

【C源程序】
/*實現初始化,建立Huffman樹,並完成字符的編碼*/

#include <stdio.h>

#define N 10     /*待編碼字符的個數,即樹中葉結點的最大個數*/

#define M 2*N-1  /*樹中總的結點數目*/

typedef struct{

  unsigned int weight;

  unsigned int parent,lchild,rchild;

  }HTNode;  /*樹中結點的結構*/

typedef struct {

  char data;     /*待編碼的字符*/

  int weight;    /*字符的權值  */

  char code[N];  /*字符的編碼 */

} HTCode;

void Init(HTCode hc[],int *n){

  /*初始化,讀入待編碼字符的個數n,從鍵盤輸入n個字符和n個權值*/

int i;

  printf("/ninput n=");

  scanf("%d",&(*n));

  printf("/ninput %d character/n",*n);

  for (i=1;i<=*n;i++) hc[i].data=getch();

  printf("/ninput %d weight/n",*n);

  for (i=1;i<=*n;i++) scanf("%d",&(hc[i].weight));

}

void Select(HTNode ht[],int k,int *s1,int *s2){

/*ht[1…k]中選擇parent爲0,並且weight最小的兩個結點

其序號由指針變量s1,s2指向*/

  int i;

  for (i=1;i<=k && ht[i].parent!=0 ;i++);

  *s1=i;

  for (i=1;i<=k;i++)

    if (ht[i].parent==0 && ht[i].weight<ht[*s1].weight) *s1=i;

  for (i=1; i<=k ; i++)

    if (ht[i].parent==0 && i!=*s1) break;

  *s2=i;

  for (i=1;i<=k;i++)

    if ( ht[i].parent==0 && i!=*s1 && ht[i].weight<ht[*s2].weight) *s2=i;

}

void HuffmanCoding(HTNode ht[],HTCode hc[],int n){

/*構造Huffman樹ht,並求出n個字符的編碼*/

  char cd[N];

  int i,j,m,c,f,s1,s2,start;

  m=2*n-1;

  for (i=1;i<=m;i++){

   if (i<=n)  ht[i].weight=hc[i].weight;

   else ht[i].weight=0;

   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].weight=ht[s1].weight+ht[s2].weight;

  }

  cd[n-1]='/0';

  for (i=1;i<=n;i++) {

    start=n-1;

    for (c=i,f=ht[i].parent;f;c=f,f=ht[f].parent)

      if (ht[f].lchild==c) cd[--start]='0';

      else cd[--start]='1';

    strcpy(hc[i].code,&cd[start]);

  }

}

main(){

 int i,m,n,w[N+1];

 HTNode ht[M+1];

 HTCode hc[N+1];

 Init(hc,&n);           /*初始化*/

 HuffmanCoding(ht,hc,n);/*構造Huffman樹,並形成字符的編碼*/

/*輸出字符的編碼*/

 for (i=1;i<=n;i++)printf("/n%c --- %s",hc[i].data,hc[i].code);

}

【測試數據】

1. 根據運行提示,依次輸入待編碼的字符個數和這些字符,以及每個字符的權值:

input n=4↙

input 4character       

abcd↙

input4 weight       

7 5 2 4↙

        輸出:

        a --- 0

        b --- 10

        c --- 110

        d --- 111

2.可根據運行提示,自行指定數據,觀察程序的運行結果。

【說明】
    此處只是Huffman樹的建立和編碼算法的實現,一個完整的Huffman編/譯碼系統應進一步完善,實現以上算法描述的四個基本要求,並可考慮將Hufmman樹和Huffman編碼存在磁盤文件中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章