ACM Haffman編碼

OpenSoucre發表於2014-04-13

Haffman編碼

時間限制:1000 ms  |  記憶體限制:65535 KB
難度:3
 
描述

哈弗曼編碼大家一定很熟悉吧(不熟悉也沒關係,自己查去。。。)。現在給你一串字元以及它們所對應的權值,讓你構造哈弗曼樹,從而確定每個字元的哈弗曼編碼。當然,這裡有一些小規定:

1.規定哈弗曼樹的左子樹編碼為0,右子樹編碼為1;

2.若兩個字元權值相同,則ASCII碼值小的字元為左孩子,大的為右孩子;

3.建立的新節點所代表的字元與它的左孩子的字元相同;

4.所有字元為ASCII碼錶上32-96之間的字元(即“ ”到“`”之間的字元)。

 
輸入
輸入包含多組資料(不超過100組)
每組資料第一行一個整數n,表示字元個數。接下來n行,每行有一個字元ch和一個整數weight,表示字元ch所對應的權值,中間用空格隔開。
輸入資料保證每組測試資料的字元不會重複。
輸出
對於每組測試資料,按照輸入順序輸出相應的字元以及它們的哈弗曼編碼結果,具體格式見樣例。
樣例輸入
3
a 10
b 5
c 8
4
a 1
b 1
c 1
d 1
樣例輸出
a:0
b:10
c:11
a:00
b:01
c:10
d:11

注意題目要求是按照按照輸入順序輸出相應的字元以及它們的哈弗曼編碼結果

 

#include <iostream>
#include <queue>
#include <string>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <sstream>
using namespace std;

struct HuffManTree;
struct HuffManTreeCmp;
typedef HuffManTree* HuffManTreePtr;
typedef priority_queue<HuffManTreePtr,vector<HuffManTreePtr>,HuffManTreeCmp> HuffManQueue;

struct HuffManTree{
    int freq;
    char key;
    HuffManTree *left,*right;
    HuffManTree(int freq_ = 0, char key_='\0'):freq(freq_),key(key_),left(NULL),right(NULL){}
};

struct HuffManTreeCmp{
    bool operator()(const HuffManTreePtr &a, const HuffManTreePtr &b)
    {
        if(a->freq !=b->freq) return a->freq > b->freq;
        else return a->key > b->key;
        return a->freq > b->freq;
    }
};

HuffManTree* huffman(HuffManQueue& huffmanQueue){
    while(huffmanQueue.size() > 1){
        HuffManTree *leftNode = huffmanQueue.top(); huffmanQueue.pop();
        HuffManTree *rightNode = huffmanQueue.top();huffmanQueue.pop();
        if(leftNode->freq == rightNode->freq && leftNode->key > rightNode->key) swap(leftNode->key,rightNode->key);
        HuffManTree *node= new HuffManTree(leftNode->freq+rightNode->freq,leftNode->key);
        node->left = leftNode;node->right = rightNode;
        huffmanQueue.push(node);
    }
    return huffmanQueue.top();
}

void print_huffman(vector<string>& res,HuffManTree *root, string code=""){
    if(NULL == root) return;
    if(root->left) code+='0';
    print_huffman(res,root->left,code);
    if(!root->left && ! root->right){
        string tmpRes(1,root->key);
        tmpRes+=":"+code;
        res.push_back(tmpRes);
    }
    code = code.substr(0,code.length()-1);
    if(root->right) code+='1';
    print_huffman(res,root->right,code);
}

int main(){
    int n;
    while(cin >> n){
        HuffManQueue huffmanQueue;
        vector<char> record;
        cin.ignore();
        for(int i = 0 ; i < n; ++ i){
            string input;
            getline(cin,input);
            char ch = input[0];
            int freq = atoi(input.substr(2).c_str()) ;
            record.push_back(ch);
            huffmanQueue.push(new HuffManTree(freq,ch));
        }
        HuffManTree *root = huffman(huffmanQueue);
       vector<string> res;
       print_huffman(res,root);
       for(int i = 0 ; i< record.size(); ++ i){
            for(int j = 0 ; j < res.size(); ++ j){
                if(res[j][0]== record[i]){
                     cout<<res[j]<<endl;
                     break;
                }
            }
       }
    }
}