ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

05-树9 Huffman Codes (30 分)

2021-08-24 01:31:39  阅读:199  来源: 互联网

标签:Codes return struct int root 30 data code Huffman


In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am encountering a big problem: the Huffman codes are NOT unique. For example, given a string "aaaxuaxz", we can observe that the frequencies of the characters 'a', 'x', 'u' and 'z' are 4, 2, 1 and 1, respectively. We may either encode the symbols as {'a'=0, 'x'=10, 'u'=110, 'z'=111}, or in another way as {'a'=1, 'x'=01, 'u'=001, 'z'=000}, both compress the string into 14 bits. Another set of code can be given as {'a'=0, 'x'=11, 'u'=100, 'z'=101}, but {'a'=0, 'x'=01, 'u'=011, 'z'=001} is NOT correct since "aaaxuaxz" and "aazuaxax" can both be decoded from the code 00001011001001. The students are submitting all kinds of codes, and I need a computer program to help me determine which ones are correct and which ones are not.

Input Specification:

Each input file contains one test case. For each case, the first line gives an integer N (2≤N≤63), then followed by a line that contains all the N distinct characters and their frequencies in the following format:

 

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

where c[i] is a character chosen from {'0' - '9', 'a' - 'z', 'A' - 'Z', '_'}, and f[i] is the frequency of c[i] and is an integer no more than 1000. The next line gives a positive integer M (≤1000), then followed by M student submissions. Each student submission consists of N lines, each in the format:

c[i] code[i]
 

where c[i] is the i-th character and code[i] is an non-empty string of no more than 63 '0's and '1's.

Output Specification:

For each test case, print in each line either "Yes" if the student's submission is correct, or "No" if not.

Note: The optimal solution is not necessarily generated by Huffman algorithm. Any prefix code with code length being optimal is considered correct.

Sample Input:

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
  结尾无空行

Sample Output:

Yes
Yes
No
No
  结尾无空行 提交代码:
//构建哈夫曼树求最小长度 
//构建最小堆
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MIN 0

//保存编码和频率
typedef struct CodeFrequency* CF;
struct CodeFrequency{
    char code;
    unsigned long frequency;
};

typedef char DataType;
typedef struct HTreeNode* HuffmanTree;
struct HTreeNode{
    DataType data;
    int weight;
    HuffmanTree left;
    HuffmanTree right;
};

typedef HuffmanTree ElemType;
typedef struct HeapStruct *MinHeap;
struct HeapStruct{
    ElemType* data;
    int size;//大小
    int capacity;//容量
};

MinHeap CreateHeap(int size){
    MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct));
    H->data = (ElemType*)malloc((size+1)*sizeof(ElemType));
    H->size = 0;
    H->capacity = size;
    H->data[0] = (ElemType)malloc(sizeof(struct HTreeNode));
    H->data[0]->weight = MIN;
    return H;
}
int IsFull(MinHeap H){
    if(H && H->size == H->capacity){
        return 1;
    }
    return 0;
}

void Insert(MinHeap H, ElemType item){
    int i;
    if(IsFull(H)){
        return;
    }
    i = ++H->size;
    for( ; H->data[i/2]->weight > item->weight; i/=2){
        H->data[i] = H->data[i/2];
    }
    H->data[i] = item;
}

int IsEmpty(MinHeap H){
    if(H->size == 0){
        return 1;
    }
    return 0;
}


ElemType DeleteMin(MinHeap H){
    if(IsEmpty(H)){
        return NULL;
    }
    ElemType min, X;
    min = H->data[1];
    X = H->data[H->size--];
    int parent, child;
    for(parent = 1; parent * 2 <= H->size; parent = child){
        child = parent*2;
        if((child != H->size) && (H->data[child]->weight >= H->data[child+1]->weight))
            child++;  /* child指向左右子结点的较小者 */
        if( X->weight <= H->data[child]->weight ){
            break; /* 找到了合适位置 */
        } 
        else  /* 下滤X */
            H->data[parent] = H->data[child];
    }
    H->data[parent] = X;
    return min;
}

HuffmanTree GetHuffmanTree(MinHeap H){
    int i;
    HuffmanTree T;
    while(H->size > 1){
        T = (HuffmanTree)malloc(sizeof(struct HTreeNode));
        memset(T, 0, sizeof(struct HTreeNode));
        T->left = DeleteMin(H);
        T->right = DeleteMin(H);
        T->weight = T->left->weight + T->right->weight;
        Insert(H, T);
    }
    T = DeleteMin(H);
    return T;
}

//在最小堆的基础上构Haffman树
HuffmanTree BuildHuffmanTree(MinHeap H, int N, CF* cf){
    *cf = (CF)malloc(N*sizeof(struct CodeFrequency));
    memset(*cf, 0, N*sizeof(struct CodeFrequency));
    for(int i = 0; i < N; ++i){
        ElemType item = (ElemType)malloc(sizeof(struct HTreeNode));
        item->left = NULL;
        item->right = NULL;
        if(i == 0){
            scanf("%c %d",&item->data, &item->weight);
        }
        else{
            scanf(" %c %d",&item->data, &item->weight);
        }
        (*cf)[i].code = item->data;
        (*cf)[i].frequency = item->weight;
        Insert(H, item);
    }
    return GetHuffmanTree(H);
}

//中序遍历哈夫曼树求得编码的最小长度
void InOrder(HuffmanTree root, int pathLen, int *totalLen){
    if(root->left == NULL && root->right == NULL){
        (*totalLen) += pathLen*root->weight;
        return;
    }
    if(root->left){
        InOrder(root->left, pathLen+1, totalLen);
    }
    if(root->right){
        InOrder(root->right, pathLen+1, totalLen);
    }
}

typedef struct TreeNode* Tree;
struct TreeNode{
    Tree left;
    Tree right;
};

//插入树,传入根结点root,字符ch,编码s
Tree TreeInsert(Tree root, char ch, char* code, int* flag){
    //如果最后一个结点不是新分配出来的就不符合前缀码的特征
    if(root != NULL && *code == '\0')
    {
        *flag = 0;
        return root;
    }
    if(root == NULL){
            root = (Tree)malloc(sizeof(struct TreeNode));
            root->left = NULL;
            root->right = NULL;
    }
    //编码0代表左子结点,编码1代表右子节点
    if(*code == '0'){
        root->left = TreeInsert(root->left, ch, code + 1, flag);
    }
    else if(*code == '1'){
        root->right = TreeInsert(root->right, ch, code + 1, flag);
    }
    return root;
}

//检查一个学生的答案
int SingleCheck(int N, unsigned long totalLen, CF *cf){
    Tree root = NULL;
    int flag = 1;
    unsigned long len = 0;
    for(int i = 0; i < N; ++i){
        char ch;
        char code[64];
        scanf("\n");
        scanf("%c", &ch);
        scanf("%s", code);
        if(flag){
            root = TreeInsert(root, ch, code, &flag);
        }
        len += strlen(code)*((*cf)[i].frequency);
    }
    if(totalLen != len){
        flag = 0;
    }
    return flag;
}

//检查答案
void CheckAnswers(int N, unsigned long totalLen, CF* cf){
    int M;
    scanf("%d", &M);
    for(int i = 0; i < M; ++i){
        if(SingleCheck(N, totalLen, cf))
        {
            printf("Yes\n");
        }
        else{
            printf("No\n");
        }
    }
}

//解题思路
//1.判断编码是不是最小长度(保证长度最小)
//2.判断编码是不是前缀码(保证唯一性)
int main(){
    int N;
    CF cf = NULL;
    scanf("%d\n", &N);
    MinHeap H = CreateHeap(N);
    //构建HaffmanTreee 求得最小长度
    HuffmanTree huffman = BuildHuffmanTree(H, N, &cf);
    //中序遍历求得最小长度
    int totalLen = 0;
    InOrder(huffman, 0, &totalLen);
    //检查答案
    CheckAnswers(N, totalLen, &cf);
    
    return 0;
}

 

 

标签:Codes,return,struct,int,root,30,data,code,Huffman
来源: https://www.cnblogs.com/2018shawn/p/15178460.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有