電文的編碼和譯碼(哈夫曼樹的應用)
阿新 • • 發佈:2019-02-03
一、 實驗環境
學寶虛擬機器,VC6.0
二、 實驗目的
從鍵盤接收一串電文字元,輸出對應的哈夫曼編碼,同時能翻譯哈夫曼編碼生成的程式碼串,輸出對應的電文字元。
三、 實驗內容
1.用C語言實現二叉樹的鏈式(二叉連結串列)儲存結構;
2.實現二叉樹的基本操作的有關演算法(二叉樹的建立、各種遍歷等);
3.定義二叉樹的靜態連結串列結構,並利用這種結構儲存哈夫曼樹,利用哈夫曼樹解決編碼及譯碼的實際應用問題。
四、 資料結構與演算法思想描述
(1)建立哈夫曼樹:
若已知n個字元的出現概率的“權值”,構造出具有2n-1個結點的哈夫曼樹(採用靜態連結串列儲存結構),
(2)編碼:
從哈夫曼樹的葉節點出發,通過雙親找到h[f],通過h[f]的左孩子和右孩子來判斷該葉子是左分支還是右分支。如果是右邊,則為‘1’。反之為‘0’。放入陣列cd[start]裡,重複上述過程,直至找到樹根。倒序輸出陣列的編碼值。
(3)譯碼:
步驟1:設計一迴圈結構接收使用者輸入的二進位制程式碼存入ch[1..m],每迴圈一次接收一個“0”或“1”,同時記錄程式碼的長度;最後將長度存入m中;設k指標的初值=1;
步驟2:將f指標指向根節點。利用指標k掃描到二進位制程式碼ch[]的第k位,若當前第k位二進位制數ch[k] =“0”則f往其左孩子移動,若ch[k]=“1”,則f往其右孩子移動;f每移動一步時執行一次k++;直到發現f的左孩子(或右孩子)為“空”時,則f遇到葉子結點,列印f所指葉子結點的data中存放的值;
步驟3:當k<=m時,則又轉步驟2,繼續掃描二進位制程式碼中的剩餘數字,否則譯碼完成,列印回車符後結束程式。
#include<stdio.h> typedef struct { char data; int w,l,r,p; }node; typedef struct{ char cd[50]; int start; }code; int create (node *h){ int i,k,n,m1,m2,p1,p2; printf("請輸入元素個數為:"); scanf("%d",&n); for(i=1;i<n+1;i++){ getchar(); printf("第%d個元素的節點值和權重:",i); scanf("%c %d",&h[i].data,&h[i].w); } for(i=1;i<=2*n-1;i++) h[i].p=h[i].l=h[i].r=0; for(i=n+1;i<=2*n-1;i++){ m1=m2=32767; p1=p2=i; for(k=1;k<i;k++){ if(h[k].p==0){ if(h[k].w<m1){ m2=m1; p2=p1; m1=h[k].w; p1=k; } else if(h[k].w<m2){ m2=h[k].w ; p2=k; } } } h[p1].p=i; h[p2].p=i; h[i].w=m1+m2; h[i].l=p1; h[i].r=p2; } printf("success for hufftree!\n"); return n; } void encoding(node h[],code co[],int n){ code d; int i,k,f,c; for(i=1;i<n+1;i++){ d.start=n+1; c=i; f=h[i].p; while(f!=0){ if(h[f].l==c) d.cd[--d.start]='0'; else d.cd[--d.start]='1'; c=f; f=h[f].p; } co[i]=d; } printf("輸出哈夫曼編碼:\n"); for(i=1;i<=n;i++){ printf("%c:",h[i].data); for(k=co[i].start;k<=n;k++){ printf("%c",co[i].cd[k]); } printf("\n"); } } void decoding(node h[],code co[],int n){ int f,m,k; char c,ch[200]; printf("請輸出電文(0或1),以‘#’為結束標誌:\n"); c=getchar(); k=1; while(c!='#'){ ch[k]=c; c=getchar(); k++; } m=k; f=2*n-1; k=1; printf("輸出哈夫曼編碼:\n"); while(k<m){ while(h[f].l!=0){ if(ch[k]=='0') f=h[f].l; if(ch[k]=='1') f=h[f].r; k++; } printf("%c",h[f].data); f=2*n-1; } printf("\n"); } int main(){ int flag=5,c; while(flag){ printf("\n****************************電文的編碼和譯碼********************\n"); printf("\n**********1,建立哈夫曼樹 2,編碼 3,譯碼 0,退出系統 ****\n"); printf("\n*提示:先建立哈夫曼樹,之後才能進行編碼或譯碼*\n"); printf("\n-------------------------------------------------------------------\n"); scanf("%d",&flag); if(flag==1){ node h[200]; code co[100]; int n; //節點數 n=create(h); scanf("%d",&c); while(c){ if(c==2){ encoding(h,co,n); } if(c==3){ decoding(h,co,n); } if(c==0) { printf("退出系統。\n"); break; } scanf("%d",&c); } } else if(flag==0){ printf("退出系統。\n"); break; } else{ printf("輸入錯誤,請重新輸入!\n"); } } return 0; }