實驗內容
某報文中共出現abdeoy 等6個字符,各字符出現頻度依次爲12 6 4 1 2 8。要求:
- 實現哈弗曼編碼算法,對這6個字符求出各自的編碼;
- 實現哈弗曼譯碼算法,對給定的一組編碼(110011111101110110),譯出其對應的報文部分 。
程序代碼
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXSIZE 100
typedef int ElemType;
typedef int Status;
typedef int Boolean;
typedef struct {
int weight,id;
unsigned int parent, lchild,rchild;
}HTNode, *HuffmanTree;
typedef char * * HuffmanCode;
typedef struct{
int w;
char c;
}temp;
void Select(HuffmanTree & HT, int tag, int & s1, int &s2)
{
int minnum = 1e9, pos = -1;
for(int i = 1; i<=tag;++i){
if(HT[i].weight<minnum && HT[i].parent == 0){
minnum = HT[i].weight;
pos = i;
}
}
s2 = pos;
HT[pos].parent = tag+1;
minnum = 1e9, pos = -1;
for(int i = 1;i<=tag;++i){
if(HT[i].weight<minnum && HT[i].parent == 0){
minnum = HT[i].weight;
pos = i;
}
}
s1 = pos;
HT[pos].parent = tag+1;
}
void output(HuffmanTree & HT, int m)
{
printf(" i w lc rc pa\n");
for(int i = 1 ;i<=m;++i){
printf("%5d %5d %5d %5d %5d\n",i,HT[i].weight,HT[i].lchild,HT[i].rchild,HT[i].parent);
}
}
bool cmp(HTNode h1, HTNode h2)
{
if(h1.weight<h2.weight) return true;
else return false;
}
bool cmpt(temp a, temp b)
{
if(a.w > b.w) return false;
else return true;
}
void HuffmanCoding(HuffmanTree & HT, HuffmanCode &HC, int *w , int n)
{
if(n<=1) return;
int m = 2 * n -1 ;
HT = (HuffmanTree)malloc((m+1) * sizeof(HTNode));
int i = 1;
HuffmanTree p = HT;
for(;i<=n; ++i,++p,++w){
HT[i] = {*w,i,0,0,0};
}
for(i = n+1 ;i<=m;++i,++p)
HT[i]= {0,i,0,0,0};
for(int i = n+1;i<=m;++i){
int s1, s2;
Select(HT,i-1,s1,s2);
if(s2<=n) swap(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;
}
HC = (HuffmanCode)malloc((n+1) * sizeof(char *));
char * cd = (char *)malloc( n * sizeof(char));
cd[n-1] = '\0';
for(int i = 1; i<=n;++i){
int start = n-1;
unsigned int f = HT[i].parent;
for( int 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]);
}
free(cd);
}
void uncoding(HuffmanTree & HT, int n,char * s)
{
char str[1000] = "110011111101110110";
printf("|"); printf(" 請輸入想要解碼的01串 ") ;printf("|\n");
scanf("%s",str);
printf("|"); printf(" 譯碼的結果爲 ") ;printf("|\n");
int len = strlen(str);
HuffmanTree t = &HT[2*n-1];
for(int i = 0; i<len;++i){
if(str[i] == '0'){
t = &HT[t->lchild];
}else{
t = &HT[t->rchild];
}
if(t->id<=n){
printf("%c",s[t->id-1]);
t = &HT[2*n-1];
continue;
}
}
printf("\n");
}
void Paint()
{
printf("|"); printf(" The Experiment Of Tree ") ;printf("|\n");
printf("|"); printf(" Huffman ") ;printf("|\n");
printf("|"); printf(" Author: Luo Peng Fei ") ;printf("|\n");
printf("|"); printf(" Date:2017/5/3 ") ;printf("|\n");
}
int main()
{
Paint();
HuffmanTree HT ;
HuffmanCode HC;
printf("|"); printf(" 請輸入想要編碼的字符 ") ;printf("|\n");
char str[30] = {'a','b','d','e','o','y'};
scanf("%s",str);
printf("|"); printf(" 請依次輸入字符的頻率 ") ;printf("|\n");
int fre[30] = {12, 6, 4, 1, 2, 8};
for(int i = 0; i<strlen(str);++i) scanf("%d",&fre[i]);
temp t[30];
for(int i = 0; i<strlen(str);++i){
t[i].w = fre[i];
t[i].c = str[i];
}
HuffmanCoding(HT,HC,fre,strlen(str));
printf("|"); printf(" 編碼的結果爲 ") ;printf("|\n");
for(int i = 1; i<=strlen(str) ;++i){
printf("%c : ",t[i-1].c);
printf("%s\n",HC[i]);
}
printf("\n");
uncoding(HT,strlen(str),str);
return 0;
}
運行結果
哈夫曼樹的結構