05-树9 Huffman Codes (30 分)

05-树9 Huffman Codes (30 分)

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 
#include 
using namespace std;
#define MaxNum 64

struct TreeNode{
    int Weight = 0;
    TreeNode *Left = nullptr;
    TreeNode *Right = nullptr;
};

struct HeapNode{ // 堆
    TreeNode Data[MaxNum];
    int Size = 0;
};

HeapNode *CreateHeap(){
    HeapNode *H = new(HeapNode);
    H->Data[0].Weight = -1; // 哨兵设置为-1
    return H;
}

// 最小堆的删除
TreeNode *DeleteMin(HeapNode *H){
    int Parent = 0, Child = 0;
    TreeNode temp;
    TreeNode *MinItem = new(TreeNode);
    *MinItem = H->Data[1]; // 保存树根

    temp = H->Data[(H->Size)--]; // 拿到最后的数据,并将总容量size-1

    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 ++;
        }
        // 如果尾权重比左右儿子最小的那个还小, 不用改变
        if(temp.Weight <= H->Data[Child].Weight) break;
        else H->Data[Parent] = H->Data[Child];
    }
    H->Data[Parent] = temp;
    return MinItem;
}

// 最小堆的插入
void Insert(HeapNode *H, TreeNode *item){
    int i = 0;
    i = ++(H->Size); // i 为当前总容量
    for (; item->Weight < H->Data[i/2].Weight; i = i / 2) {
        H->Data[i] = H->Data[i/2];
    }
    H->Data[i] = *item;
}

HeapNode *ReadData(int N, HeapNode *H, int A[]){
    char s;
    int value;
    for (int i = 0; i < N; ++i) {
        cin >> s;
        cin >> value;
        A[i] = value;
        TreeNode* T = new(TreeNode);
        T->Weight = value;
        Insert(H, T);
    }
    return H;
}
// 下面构造哈夫曼树的过程是一个由Heap变哈夫曼树的过程
TreeNode *Huffman(HeapNode *H){
    TreeNode *T = nullptr;
    int num = H->Size;
    // 两两合并,必定是进行n - 1次
    for (int i = 0; i < num - 1; ++i) {
        T = new(TreeNode);
        T->Left = DeleteMin(H);
        T->Right = DeleteMin(H);
        T->Weight = T->Left->Weight + T->Right->Weight;
        Insert(H, T);
    }
    T = DeleteMin(H);
    return T;
}

// 计算Huffman树的权重
int WPL(TreeNode *H, int n){
    if (!H->Right) return H->Weight * n;
    else return WPL(H->Left, n + 1) + WPL(H->Right, n + 1);
}

struct JNode{
    // 每个点非0即1 flag为1代表这里已经有一个前辈住进去了只要我完全走了前辈走的路,就重复出现
    int Flag = 0;
    JNode *Left = nullptr;
    JNode *Right = nullptr;
};

// 判断编码是否符合前缀码要求
bool Judge(string s, JNode *J){
    int i = 0;
    for (; i < s.length(); ++i) {
        if (s[i] == '0'){
            if (J->Left == nullptr){
                JNode *j = new(JNode);
                J->Left = j;
            }else{
                if (J->Left->Flag == 1){
                    return false;
                }
            }
            J = J->Left;
        }else{
            if (J->Right == nullptr){
                JNode *j = new(JNode);
                J->Right = j;
            }else{
                if (J->Right->Flag == 1){
                    return false;
                }
            }
            J = J->Right;
        }
    }
    J->Flag = 1;
    if (J->Left == nullptr && J->Right == nullptr){
        return true;
    }else return false;
}

int main(){
    int N = 0, n = 0;
    cin >> N;
    HeapNode *H = CreateHeap();
    int Value[MaxNum] = {};
    ReadData(N, H, Value);
    TreeNode *T = Huffman(H);
    int CodeLen = WPL(T, 0);
    cin >> n;

    string temp;
    char c;
    bool result;
    for (int i = 0; i < n; ++i) {
        int count = 0, flag = 0;
        JNode *J = new(JNode);
        for (int j = 0; j < N; ++j) {
            cin >> c >> temp;
            count += temp.length() * Value[j]; // 这就是Value的作用啊
            // 开始判断是否符合前缀码要求
            if (!flag){
                result = Judge(temp, J);
                if (!result) {
                    flag = 1;
                }
            }
        }
        delete J;
        if (result && count == CodeLen){
            cout << "Yes" << endl;
        }else{
            cout << "No" << endl;
        }
    }
    return 0;
}

遗留问题

main函数最后,flag部分存在的意义

你可能感兴趣的:(05-树9 Huffman Codes (30 分))