7-1 Huffman Codes (30 分)

7-1 Huffman Codes (30 分)(谷歌翻譯的)

1953年,David A. Huffman發表了他的論文「構建最小冗餘碼的方法」,所以在計算機科學史上印刷了他的名字。做爲給霍夫曼代碼提出期末考試問題的教授,我遇到了一個大問題:霍夫曼代碼並非惟一的。例如,給定一個字符串「aaaxuaxz」,咱們能夠觀察到字符「a」,「x」,「u」和「z」的頻率分別爲4,2,1和1。咱們能夠將符號編碼爲{'a'= 0,'x'= 10,'u'= 110,'z'= 111},或者換句話爲{'a'= 1,'x'= 01 ,'u'= 001,'z'= 000},都將字符串壓縮爲14位。另外一組代碼能夠給出{'a'= 0,'x'= 11,'u'= 100,'z'= 101},但{'a'= 0,html

輸入規格:

每一個輸入文件包含一個測試用例。對於每種狀況,第一行給出一個整數N≤ Ñ ≤ 3),再其次是一個包含全部的線N個不一樣的字符及其頻率採用如下格式:算法

c[1] f[1] c[2] f[2] ... c[N] f[N]

  其中c[i]是從{'0' - '9','a' - 'z','A' - 'Z','_'}中選擇的字符,而且f[i]c[i]而且是不超過1000的整數的頻率。下一行給出正整數M≤ 0),則接着M學生提交。每一個學生提交的內容包括N行,每行格式:測試

c[i] code[i]

  其中c[i]i-th字符,code[i]是一個非空字符串,不超過63'0和'1'。編碼

輸出規格:

對於每一個測試用例,若是學生的提交正確,則在每行打印「是」,不然打印「否」。spa

注意:最優解不必定是由霍夫曼算法生成的。任何代碼長度最佳的前綴代碼都被認爲是正確的。翻譯

樣本輸入:

7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11

  

樣本輸出:

Yes
Yes
No
No

  

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<string.h>
typedef struct HFTNode
{
    char Data;
    int Parent;
    int Lchild;
    int Rchild;
    int Weight;
}HFTNode, *HFTree;
typedef struct CNode
{
    char Data;
    char Code[100];
}CNode;
HFTree T;
void AddNode(int N)
{
    int min1 = 0, min2 = 0;
    for(int i=1; i<N; i++){//找到兩個沒父母的節點
        if(T[i].Parent == 0 && min1 == 0)
            min1 = i;
        else if(T[i].Parent == 0 && min1 != 0)
            min2 = i;
    }
    if(T[min1].Weight > T[min2].Weight){
        int temp = min1;
        min1 = min2;
        min2 = temp;
    }
    for(int i=1; i<N; i++){//找到兩個沒父母的最小節點
        if(T[i].Parent == 0 && T[i].Weight < T[min1].Weight){
            min2 = min1;
            min1 = i;
        }
        else if(T[i].Parent == 0 && T[i].Weight < T[min2].Weight && i!=min1 )
            min2 = i;
    }
    T[N].Weight = T[min1].Weight + T[min2].Weight;
    T[N].Lchild = min1;
    T[N].Rchild = min2;
    T[N].Parent = 0;
    T[min1].Parent = N;
    T[min2].Parent = N;
}
int JuChild(int m1, int m2, CNode *Code)
{
    int len = strlen(Code[m1].Code);
    int flag = 0;
    for(int i=0; i<len; i++){
        if(Code[m1].Code[i] != Code[m2].Code[i])//存在不相等的則賦1
            flag = 1;
    }
    if(flag == 0)//說明是子序列
        return 1;
    else
        return 0;
}
int main()
{
    int N, M, Weight=0;
    scanf("%d", &N);getchar();
    T = (HFTNode*)malloc(sizeof(HFTNode)*(2*N));
    for(int i=1; i<=N; i++){
        scanf("%c %d", &T[i].Data, &T[i].Weight);getchar();
        T[i].Parent = 0;
        T[i].Lchild = 0;
        T[i].Rchild = 0;
    }
    for(int i=N+1; i<2*N; i++){//帶權路徑爲非葉節點權值之和
        AddNode(i);
        Weight += T[i].Weight;

    }
    scanf("%d", &M);
    for(int i=0; i<M; i++){
        CNode Code[100];
        int weight = 0;
        for(int j=1; j<=N; j++){
            scanf("%c%*c%s", &Code[j].Data, &Code[j].Code);
            weight += T[j].Weight * strlen(Code[j].Code);
        }
        if(weight != Weight)//帶權路徑不一致
            printf("No\n");
        else{
                int flag = 1;
            for(int j=N; j>=1 && flag; j--){//判斷某個序列是不是另外一個編碼的子序列
                for(int i=1; i<j; i++){
                    int is = JuChild(j, i, Code);
                    if(is){
                        printf("No\n");
                        flag = 0;
                        break;
                    }
                }
            }
            if(flag)
                printf("Yes\n");
        }

    }
}
相關文章
相關標籤/搜索