日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

数据结构——哈弗曼编码问题

發布時間:2023/12/4 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 数据结构——哈弗曼编码问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實驗六 基于哈夫曼樹的數據壓縮算法
【實驗目的】

  • 掌握哈夫曼樹的構造算法。
  • 掌握哈夫曼編碼的構造算法。
    【實驗內容】
    問題描述
    輸入一串字符,根據給定的字符串中字符出現的頻率建立相應的哈夫曼樹,
    構造哈夫曼編碼表,在此基礎上可以對壓縮文件進行壓縮(即編碼),同時可以對
    壓縮后的二進制編碼文件進行解壓(即譯碼)。
    輸入要求
    多組數據,每組數據 1 行,為一個字符串(只考慮 26 個小寫字母即可)。當輸
    入字符串為“00”時,輸入結束。
    輸出要求
    每組數據輸出 2n+3 行(n 為輸入串中字符類別的個數)。第 1 行為統計出來
    的字符出現頻率(只輸出存在的字符,格式為字符:頻度),每兩組字符之間用一個
    空格分隔,字符按照 ASCII 碼從小到大的順序排列。第 2 行至第 2n 行為哈夫曼樹
    的存儲結構的終態(參照實驗提示表 5.2,一行當中的數據用空格分隔)。第 2n+1
    行為每個字符的哈夫曼編碼(只輸出存在的字符,格式為字符:編碼),每兩組字符
    之間用一個空格分隔,字符按照 ASCII 碼從小到大的順序排列。第 2n+2 行為編碼
    后的字符串,第 2n+3 行為解碼后的字符串(與輸入的字符串相同)。
    輸入樣例
    aaaaaaabbbbbccdddd
    aaccb
    00
    輸出樣例
    a:7 b:5 c2 d:4
    1 7 7 0 0
    2 5 6 0 0
    3 2 5 0 0
    4 4 5 0 0
    5 6 6 3 4
    6 1 1 7 2 5
    7 1 8 0 1 6
    a:0 b:10 c:110 d:111
    00000001010101011011011111
    aaaaaaabbbbbccdddd
    a:2 b:1 c:3
    1 2 4 0 0
    2 1 4 0 0
    3 3 5 0 0
    4 3 5 2 1
    5 6 0 3 4
    a:11 b:10 c:0
    111110000
    aabccc
    【實驗提示】
    首先,讀入一行字符串,統計每個字符出現的頻率;然后,根據字符出現的頻
    率利用提示算法 1 建立相應的哈夫曼樹;最后,根據得到的哈夫曼樹利用算法 2
    求出每個字符的哈夫曼編碼。
  • 思路:

  • 該問題使用順序表來存儲哈夫曼樹

  • char_statiscal()函數統計每種字符出現的次數

  • CreatHuffmanCode()構建哈弗曼樹數組,共有n個葉子結點,n-1個非葉子結點。

  • select()函數選取哈弗曼數組中權值最小的兩個葉子結點,返回到CreatHuffmanCode()函數中,用于完成對非葉子結點的構建
    并且同時修改葉子結點的父親結點,和非葉子結點的孩子結點

  • 結構體
    typedef struct
    {
    char info;//存儲每一個結點對應的字符
    int weight;//權值
    int parent,lchild,rchild;
    int index;//存儲每一個結點對應的下標
    char code[MAXCODE];//存儲每一個字符對應的二進制編碼

  • }HTNode,*HuffmanTree;

    6.CreatHuffmanCode()函數為每種字符創建各自的二進制編碼

  • encode()將每個字符的編碼放到該葉子結點的code[]
    中去。
    具體過程:依次讀入字符,在哈弗曼編碼表(數組中)找到次字符,將字符轉換為編碼表中存放的編碼串。

  • decode()利用以構建好的哈弗曼樹來進行解碼
    對編碼后的文件進行譯碼的過程必須借助于哈弗曼樹。
    具體過程:依次讀入文件的二進制碼,從哈弗曼樹的根節點出發,若是0,則走向左子樹,否則走向右子樹。一旦到達葉子結點,便譯出相應的字符編碼。然后繼續從根節點出發繼續譯碼,直到全部結束。

  • #include<stdio.h> #include<iostream> #include<string.h> using namespace std; #define MAXSTRLEN 255 #define MAXCODE 20char alphabet[26]={0}; char alphabet2[26]; typedef char **HuffmanCode; typedef struct {char String[MAXSTRLEN]; }SqString;typedef struct {char info;//存儲每一個結點對應的字符 int weight;//權值 int parent,lchild,rchild;int index;//存儲每一個結點對應的下標 char code[MAXCODE];//存儲每一個字符對應的二進制編碼 }HTNode,*HuffmanTree;//統計字符串中每種字符出現的次數 void char_statiscal(SqString &S,char *alphabet,int &num,char *alphabet2) {int i=0,j=0;for(i=0;S.String[i]!='\0';i++){if(S.String[i]>='a'&&S.String[i]<='z')alphabet[S.String[i]-'a']++;}for(int j=0;j<26;j++){if(alphabet[j]>0){printf("%c:%d ",'a'+j,alphabet[j]);num++;}}printf("\n"); int x=0;for(int j=0;j<26;j++){if(alphabet[j]>0){alphabet2[x]='a'+j;x++;}}}//創建一個簡單的哈弗曼樹用于復制一個復雜的哈弗曼樹 主要用于排序了 void createHuffmanTree2(HuffmanTree &HT,int n,char *alphabet,char*alphabet2) {if(n<1)return ;int m=2*n-1;int number=0;HT=new HTNode[m+1];for(int i=1;i<=n;i++){HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;HT[i].index=i;}for(int j=0;j<26;j++){if(alphabet[j]>0)HT[++number].weight=0;}}//HT哈夫曼樹,ht,是用于存儲排序后的哈夫曼樹,n是所要排序的哈夫曼樹的節點個數 void select(HuffmanTree &HT,int length,int &s1,int &s2) { HuffmanTree ht;createHuffmanTree2(ht,length,alphabet,alphabet2);for(int i=1;i<=length;i++){{ ht[i].weight=HT[i].weight;ht[i].index=HT[i].index;}}int temp_index=0;int temp_weight=0;for(int i=1;i<length;i++){for(int j=1;j<=length-i;j++){if(ht[j].weight>ht[j+1].weight){temp_weight=ht[j].weight;ht[j].weight=ht[j+1].weight;ht[j+1].weight=temp_weight;temp_index=ht[j].index;ht[j].index=ht[j+1].index;ht[j+1].index=temp_index;}}}for(int i=1;i<=length;i++){if(HT[ht[i].index].parent==0){s1=ht[i].index;HT[ht[i].index].parent=length+1;break;}}for(int j=1;j<=length;j++){if(HT[ht[j].index].parent==0){s2=ht[j].index;HT[ht[j].index].parent=length+1;break;}}}//構建一顆完整的哈夫曼樹 void createHuffmanTree(HuffmanTree &HT,int n,char *alphabet) { //----------------------------創建哈夫曼樹---------------------// if(n<1)return ;int m=2*n-1;int number=0;HT=new HTNode[m+1];//構造哈夫曼樹節點 的結構體數組,0號單元不占用,其中共有n個葉子節點,n-1個非葉子節點;for(int i=1;i<=m;i++){HT[i].info=alphabet2[i-1];HT[i].parent=0;HT[i].lchild=0;HT[i].rchild=0;HT[i].index=i;}for(int j=0;j<26;j++){if(alphabet[j]>0)HT[++number].weight=alphabet[j];} //---------------------------------初始化--------------------------------//int a,b;for(int i=n+1;i<=m;i++){select(HT,i-1,a,b);HT[a].parent=i;HT[b].parent=i;HT[i].lchild=a;HT[i].rchild=b;HT[i].weight=HT[a].weight+HT[b].weight;}for(int a=1;a<=2*n-1;a++){printf("下標為%d的權為 %d 父親節點:%d,左孩子:%d,右孩子:%d\n",HT[a].index,HT[a].weight,HT[a].parent,HT[a].lchild,HT[a].rchild);}}//為每一個字符創建好各自的二進制編碼 void CreatHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n) {HC=new char*[n+1];char *cd;cd=new char[n];cd[n-1]='\0';int start;int c;int f;for(int i=1;i<=n;i++){start=n-1;c=i,f=HT[i].parent;while(f!=0){--start;if(HT[f].lchild==c)cd[start]='0';else cd[start]='1';c=f,f=HT[f].parent;}HC[i]=new char[n-start];strcpy(HC[i],&cd[start]);}delete cd;for(int i=1;i<=n;i++)printf("%c:%s ",alphabet2[i-1],HC[i]);printf("\n"); }//為字符串進行編碼 void encode(SqString &S,HuffmanCode HC,int n,HuffmanTree HT,char *sum) {for(int i=0;S.String[i]!='\0';i++){for(int j=1;j<=n;j++){if(S.String[i]==HT[j].info){strcat(sum,HC[j]);strcpy(HT[j].code,HC[j]);break;}}}printf("%s\n",sum); }//對已經編碼好的字符串進行解碼 void decode(char *sum,int n,HuffmanTree HT) {int index=2*n-1;//根節點開始 int j=0;while(sum[j]!='\0'){if(sum[j]=='0')index=HT[index].lchild;else index=HT[index].rchild;if(HT[index].lchild==0&&HT[index].rchild==0){printf("%c",HT[index].info);index=2*n-1;}j++;}}int main() {SqString S;do{gets(S.String);HuffmanTree HT;char sum[100]={""};int num=0;char alphabet[26]={0};char_statiscal(S,alphabet,num,alphabet2);createHuffmanTree(HT,num,alphabet);HuffmanCode HC;CreatHuffmanCode(HT,HC,num);encode(S,HC,num,HT,sum);decode(sum,num,HT);printf("\n"); }while(S.String!="00");}







    關于n個字符的哈弗曼編碼的計算時間復雜度為(nlogn)
    因為最小堆的插入和刪除都需要(logn)的時間,而n-1次的合并就需要n(logn)

    總結

    以上是生活随笔為你收集整理的数据结构——哈弗曼编码问题的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。