題目描述
已知某段通信封包内容,對該封包進行哈弗曼編碼,并計算平均碼長。
(1)統計封包中各字元出現的頻度。(字元集範圍為52個英文字母,空格,英文句号。封包長度<=200)
(2)構造一棵哈弗曼樹,依次給出各字元編碼結果。
(3)給字元串進行編碼。
(4)給編碼串進行譯碼。
(5)計算平均碼長。
規定:
(1)結點統計:以ASCII碼的順序依次排列,例如:空格,英文句号,大寫字母,小寫字母。
(2)建構哈弗曼樹時:左子樹根結點權值小于等于右子樹根結點權值。
(3)選擇的根節點權值相同時,前者建構為雙親的左孩子,後者為右孩子。
(4)生成編碼時:左分支标0,右分支标1。
輸入
第一部分:封包内容,以’#'結束。
第二部分:待譯碼的編碼串。
輸出
依次輸出封包編碼串、譯碼串、平均碼長,三者之間均以換行符間隔。
平均碼長,保留小數點2位。
樣例輸入 Copy
Data structure is the way of computer storage and organization data. A data structure is a collection of data elements that exist between one or more specific relationships.#
000111111110101111110100101010000110111100010011011000001110011110011100101011010011100001101111011001011010101011001101110010101011101011110110101000110001101001010101010001111000101001110111111101000001101010100000010111111110101110110011111101001111010111011100000011110101111000100110000111011000000111101011111101001010100001101111000100110110000011100111100111011111101110010100000100001001111000100111101011101110101010110011000000111101011111100010000100110111000111101010100111001010110111110101100010110001011110010101100110000001010000110001001111011101010111010011101010100011010111010101000001110100110111100111100011110110001111110011010000010000111110100111101011101100110110101111011111001000100
樣例輸出 Copy
000111111110101111110100101010000110111100010011011000001110011110011100101011010011100001101111011001011010101011001101110010101011101011110110101000110001101001010101010001111000101001110111111101000001101010100000010111111110101110110011111101001111010111011100000011110101111000100110000111011000000111101011111101001010100001101111000100110110000011100111100111011111101110010100000100001001111000100111101011101110101010110011000000111101011111100010000100110111000111101010100111001010110111110101100010110001011110010101100110000001010000110001001111011101010111010011101010100011010111010101000001110100110111100111100011110110001111110011010000010000111110100111101011101100110110101111011111001000100
Data structure is the way of computer storage and organization data. A data structure is a collection of data elements that exist between one or more specific relationships.
4.11
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct hafutree
{
char ch;
int parent;
int weight;
int lchild;
int rchild;
}hafutree;
float wt[200];
char ch_ch[200];
///初始化哈夫曼樹
hafutree **inithafutree(int wet[],char diff_zf[],int n)
{
//printf("初始化哈夫曼樹\n");
//getchar();
hafutree **head;
head=(hafutree **)malloc(sizeof(hafutree *)*n*2);
for(int i=1;i<=n;i++)
{
head[i]=(hafutree *)malloc(sizeof(hafutree));
head[i]->ch=diff_zf[i-1];
head[i]->weight=wet[i-1];
head[i]->parent=0;
head[i]->lchild=0;
head[i]->rchild=0;
}
for(int i=n+1;i<2*n;i++)
{
head[i]=(hafutree *)malloc(sizeof(hafutree));
head[i]->ch='#';
head[i]->weight=0;
head[i]->parent=0;
head[i]->lchild=0;
head[i]->rchild=0;
}
return head;
}
///建立好哈夫曼樹
void create_hafutree(hafutree **head,int x)
{
//printf("建立哈弗樹\n");
//getchar();
int m,n;//m第一個最小,n第二個最小
int k=x;//記錄下一次存放位置
while(k<2*x-1)
{
for(int j=1;j<=k;j++)
{
if(head[j]->parent==0)
{
m=j;
break;
}
}
for(int i=1;i<=k;i++)
{
if(head[m]->weight>head[i]->weight&&head[i]->parent==0)
{
m=i;
}
}
for(int j=1;j<=k;j++)
{
if(head[j]->parent==0&&m!=j)
{
n=j;
break;
}
}
for(int i=1;i<=k;i++)
{
if(i==m)
{
continue;
}
if(head[n]->weight>head[i]->weight&&head[i]->parent==0)
{
n=i;
}
}
head[++k]->weight=head[m]->weight+head[n]->weight;
head[k]->lchild=m;
head[k]->rchild=n;
head[m]->parent=k;
head[n]->parent=k;
}
/*getchar();
printf("完成哈夫曼樹\n");
for(int i=1;i<2*x;i++)
{
//printf("%d",head[i]->weight);
printf("%d-節點值%c-",i,head[i]->ch);
printf("父親%d-",head[i]->parent);
printf("左孩子%d-",head[i]->lchild);
printf("右孩子%d\n",head[i]->rchild);
}
getchar();*/
}
//對預處理的權值和資訊進行排序
void paixu(int getwt[],char getch[])
{
int a;
char b;
for(int i=0;i<strlen(getch)-1;i++)
{
for(int j=0;j<strlen(getch)-1-i;j++)
{
if(getch[j]>getch[j+1])
{
b=getch[j+1];
getch[j+1]=getch[j];
getch[j]=b;
a=getwt[j+1];
getwt[j+1]=getwt[j];
getwt[j]=a;
}
}
}
for(int i=0;i<strlen(getch);i++)
{
wt[i]=getwt[i];
}
}
//計算碼長
/*void vacaluct(char **ch,int getwt[],char getch[],int n,int m)
{
printf("%d,%d",n,m);
getchar();
int sum=0;
for(int i=1;i<=n;i++)
{
printf("%d",getwt[i-1]);
sum=sum+(getwt[i-1]/m)*strlen(ch[i]);
}
printf("%d",sum);
}*/
//得到不同字元資訊(名稱和權值)
hafutree **getdifferentchar(char *text,int *number)
{
hafutree **head;//傳回初始化後的哈弗樹
int m=0;//表示text的總數
int n=0;//記錄不同字元
//int k=0;
int flog=0;//用來做判斷不同字元條件
char *getch;//儲存不同字元
int *getwt;//儲存不同字元的權值
for(int i=0;text[i]!='#';i++)
{
m++;
}
text[m]='\0';
getch=(char *)malloc(sizeof(char)*m);
getwt=(int *)malloc(sizeof(int)*m);
for(int i=0;i<=m;i++)//初始化權值數組
{
getwt[i]=0;
}
getch[n]=text[n];
getch[++n]='\0';
for(int i=0;text[i]!='\0';i++)
{
flog=0;
for(int j=0;getch[j]!='\0';j++)
{
if(text[i]==getch[j])
{
getwt[j]++;
flog=1;
break;
}
else
{
continue;
}
}
if(flog==0)
{
getch[n]=text[i];
getwt[n]++;
getch[++n]='\0';
}
}
//調用初始化函數
*number=strlen(getch);
paixu(getwt,getch);
//strcpy(getch,".ADabcdefghilmnoprstuwxyz");
//puts(getch);
head=inithafutree(getwt,getch,strlen(getch));
return head;
}
進行哈夫曼編碼
char **makecode(hafutree **head,int n)
{
char a[n];
int start;
int p;
int k;
char **ch;
ch=(char **)malloc(sizeof(char *)*n);
ch[0]=(char *)malloc(sizeof(char)*5);
for(int i=1;i<=n;i++)
{
start=n-1;
a[start]='\0';
p=head[i]->parent;
k=i;
while(p)
{
if(head[p]->lchild==k)
{
a[--start]='0';
}
else if(head[p]->rchild==k)
{
a[--start]='1';
}
k=p;
p=head[p]->parent;
}
ch[i]=(char *)malloc(sizeof(char)*(n-start));
strcpy(ch[i],&a[start]);
}
return ch;
}
///進行哈夫曼譯碼
char *translatecode(hafutree **head,char hafu_number[],int y)
{
int k=0;//記錄邊緣後位置
int m,x,n;
char *tr;
tr=(char *)malloc(sizeof(char)*500);
x=0;
for(int i=k;hafu_number[i]!='\0';)
{
m=2*y-1;
n=i;
while(head[m]->lchild&&head[m]->rchild)
{
if(hafu_number[n]=='0')
{
m=head[m]->lchild;
}
else if(hafu_number[n]=='1')
{
m=head[m]->rchild;
}
n++;
i++;
}
tr[x++]=head[m]->ch;
tr[x]='\0';
}
return tr;
}
int main()
{
char hafuch[500];//待編譯碼
char hafu_number[1000];//待解譯碼
char hafuch_num[1000]="";
hafutree **head;
char *tr;//儲存譯碼後的資訊;
char **ch;
int n;//記錄不同字元個數
int j;
gets(hafuch);
gets(hafu_number);
//初始化哈弗樹
head=getdifferentchar(hafuch,&n);
//建立好哈弗樹.
create_hafutree(head,n);
//哈弗編碼ch[]儲存資訊
ch=makecode(head,n);
//哈弗譯碼
//puts(hafuch);
for(int i=0;hafuch[i]!='\0';i++)
{
j=1;
while(j<=n)
{
if(head[j]->ch==hafuch[i])
{
strcat(hafuch_num,ch[j]);
break;
}
j++;
}
}
puts(hafuch_num);
// getchar();
tr=translatecode(head,hafu_number,n);
puts(tr);
// getchar();
float sum=0;
for(int i=0;i<n;i++)
{
//printf("%f,%d,%d,%f\n",wt[i],strlen(hafuch),strlen(ch[i+1]),wt[i]*strlen(ch[i+1])/strlen(hafuch));
// getchar();
sum=sum+wt[i]*strlen(ch[i+1])/strlen(hafuch);
// getchar();
}
printf("%0.2f",sum);
// printf("%f",sum);
}