現在我就來說明一下這個赫夫曼編碼/譯碼器實現方法吧。整個項目我就用win32控制台程序寫的。這樣可以方便測試,排除其他麻煩。
首先,我們來看看main函數:
- void main()
- {
- char choice=' ';
- while(choice!='q')
- { cout<<"\n******************************"< cout<<" 歡迎使用赫夫曼編碼譯碼系統"< cout<<"******************************"< cout<<"(1)要初始化赫夫曼鏈表請輸入'i'"< cout<<"(2)輸入要編碼的字符'w'"< cout<<"(3)要編碼請輸入'e'"< cout<<"(4)要譯碼請輸入'd'"< cout<<"(5)要打印編碼請輸入'p'"< cout<<"(6)要打印赫夫曼樹請輸入't'"< cout<<"(7)要離開請輸入'q'"< if(flag==0)cout<<"\n請先初始化赫夫曼鏈表,輸入'i'"< cin>>choice;
- switch(choice)
- {
- case 'i':
- Initialization();
- break;
- case 'w':
- InputCode();
- break;
- case 'e':
- Encoding();
- break;
- case 'd':
- Decoding();
- break;
- case 'p':
- Code_printing();
- break;
- case 't':
- Tree_printing(HT,2*n-1);
- break;
- case 'q':
- break;
- default:
- cout<<"input error"< }
- }
- free(z);
- free(w);
- free(HT);
- }
這個函數主要就是和用戶交互使用。這個過程我用switch case 來實現,你們也可以選擇其他的方式實現如if else ,這個就個人愛好選擇。下面我們來看看初始化赫夫曼樹的函數Initialization)。
- void Initialization()
- {
- flag=1;
- int num;
- int num2;
- cout<<"下面初始化赫夫曼鏈表"< cin>>num;
- n=num;
- w=(int*)malloc(n*sizeof(int));
- z=(char*)malloc(n*sizeof(char));
- cout<<"\n請依次輸入"< char base[2];
- for(i=0;i {
- cout<<"第"< gets(base);//這個地方有點小小的問題
- *(z+i)=*base;
- }
- for(i=0;i<=n-1;i++)
- {
- cout< }
- cout<<"\n請依次輸入"< for(i=0;i<=n-1;i++)
- {
- cout< cin>>num2;
- *(w+i)=num2;
- }
- HuffmanCoding(HT,HC,w,n);
- //------------------------打印編碼-------------------------------------------
- cout<<"字符對應的編碼為:"< for(i=1;i<=n;i++)
- {
- //cout<<"字符"<<*(z+i-1)<<"的編碼";
- puts(HC[i]);
- }
- //--------------------------將赫夫曼編碼寫入文件------------------------
- cout<<"下面將赫夫曼編碼寫入文件"<
- FILE *hfmTree;
- char r[]={' ','\0'};
- if((hfmTree=fopen("hfmTree.txt","w"))==NULL)
- {
- cout<<"can not open file"< return;
- }
- fputs(z,hfmTree);
- for(i=0;i {
- fprintf(hfmTree,"%6d",*(w+i));
- fputs(r,hfmTree);
- }
- for(i=1;i<=n;i++)
- {
- fputs(HC[i],hfmTree);
- fputs(r,hfmTree);
- }
- fclose(hfmTree);
- cout<<"已將字符與對應編碼寫入根目錄下文件hfmTree.txt中"<}
上述代碼中有個小問題,已經用紅色標示,這個地方獲取數據的時候有一次是沒有輸入就直接執行的。這個疑問我一直都沒想通。初始化的結果放入hfmTree.txt的文件中。
下面來看看輸入要編碼的字符的函數InputCode)
- void InputCode()
- {
- //cout<<"請輸入你想要編碼的字符"< FILE *tobetran;
- char str[100];
- if((tobetran=fopen("tobetran.txt","w"))==NULL)
- {
- cout<<"不能打開文件"< return;
- }
- cout<<"請輸入你想要編碼的字符"< cin>>str;
- fputs(str,tobetran);
- cout<<"獲取報文成功"< fclose(tobetran);
- }
這個函數裡我也碰到了一個問題,cin>>str;部分一開始的時候,我是用gets代替的,不過問題就是用gets我不用輸入就能直接執行完函數。這個郁悶啊。
下面來看看赫夫曼編碼/譯碼器函數
- //---------------------編碼函數---------------------------------
- void Encoding()
- {
- cout<<"下面對目錄下文件tobetran.txt中的字符進行編碼"<
- FILE *tobetran,*codefile;
- if((tobetran=fopen("tobetran.txt","rb"))==NULL)
- {
- cout<<"不能打開文件"< }
- if((codefile=fopen("codefile.txt","wb"))==NULL)
- {
- cout<<"不能打開文件"< }
- char *tran;
- i=99;
- tran=(char*)malloc(100*sizeof(char));
- while(i==99)
- {
- if(fgets(tran,100,tobetran)==NULL)
- {
- cout<<"不能打開文件"< break;
- }
- for(i=0;*(tran+i)!='\0';i++)
- {
- for(j=0;j<=n;j++)
- {
- if(*(z+j-1)==*(tran+i))
- {
- fputs(HC[j],codefile);
- if(j>n)
- {
- cout<<"字符錯誤,無法編碼!"< break;
- }
- }
- }
- }
- }
- cout<<"編碼工作完成"< fclose(tobetran);
- fclose(codefile);
- free(tran);
- }
- //-----------------譯碼函數---------------------------------
- void Decoding()
- {
- cout<<"下面對根目錄下文件codefile.txt中的字符進行譯碼"< FILE *codef,*txtfile;
- if((txtfile=fopen("\\Textfile.txt","w"))==NULL)
- {
- cout<<"不能打開文件"< }
- //txtfile=fopen("Textfile.txt","w");
- if ((codef=fopen("codefile.txt","r"))==NULL)
- {
- cout<<"不能打開文件"< }
- //codef=fopen("codefile.txt","r");
- char *work,*work2,i2;
- int i4=0,i,i3;
- unsigned long length=10000;
- work=(char*)malloc(length*sizeof(char));
- fgets(work,length,codef);
- work2=(char*)malloc(length*sizeof(char));
- i3=2*n-1;
- for(i=0;*(work+i)!='\0';i++)
- {
- i2=*(work+i);
- if(HT[i3].lchild==0)
- {
- *(work2+i4)=*(z+i3-1);
- i4++;
- i3=2*n-1;
- i--;
- }
- else if(i2=='0') i3=HT[i3].lchild;
- else if(i2=='1') i3=HT[i3].rchild;
- }
- *(work2+i4)='\0';
- fputs(work2,txtfile);
- cout<<"譯碼完成"<free(work);
- free(work2);
- fclose(txtfile);
- fclose(codef);
- }
整個赫夫曼編碼/譯碼器實現過程也就這樣了。
我沒有學過數據結構,我只是看過一些資料,這裡可能會有不好的地方,高手可以指點一下。