哈夫曼编码,应用模板特化递归+bind函数绑定

来源:互联网 发布:java windows api 编辑:程序博客网 时间:2024/06/09 02:22

  • 文件列表
    • BTreehpp
    • HuffmanTreehpp
    • HuffmanTreecpp
    • Testcpp
  • 模板特化递归
  • bind 函数绑定
  • 后记


文件列表

BTree.hpp

#ifndef __BTREE__#define __BTREE__#include <iostream>#include <functional>template <typename K,typename V>class BTree{public:    BTree()    {        is_leaf = false;        parent = nullptr;        left_child = nullptr;        right_child = nullptr;    }    BTree(bool _is_leaf)    {        is_leaf = _is_leaf;        parent = nullptr;        left_child = nullptr;        right_child = nullptr;    }    void Set_Parent(BTree<K,V>* _parent);    void Set_Left_Child(BTree<K,V>* _left_child);    void Set_Right_Child(BTree<K,V>* _right_child);    BTree<K,V>* Get_Parent();    BTree<K,V>* Get_Left_Child();    BTree<K,V>* Get_Right_Child();    void Set_Key(K _key);    void Set_Value(V _value);    K Get_Key();    V Get_Value();    bool Is_Leaf()    {        return is_leaf;    }private:    BTree<K,V>* parent;    BTree<K,V>* left_child;    BTree<K,V>* right_child;    K key;    V value;    bool is_leaf;};template <typename K,typename V>void BTree<K,V>::Set_Parent(BTree<K,V>* _parent){    parent = _parent;}template <typename K,typename V>void BTree<K,V>::Set_Left_Child(BTree<K,V>* _left_child){    left_child = _left_child;}template <typename K,typename V>void BTree<K,V>::Set_Right_Child(BTree<K,V>* _right_child){    right_child = _right_child;}template <typename K,typename V>BTree<K,V>* BTree<K,V>::Get_Parent(){    return parent;}template <typename K,typename V>BTree<K,V>* BTree<K,V>::Get_Left_Child(){    return left_child;}template <typename K,typename V>BTree<K,V>* BTree<K,V>::Get_Right_Child(){    return right_child;}template <typename K,typename V>void BTree<K,V>::Set_Key(K _key){    key = _key;}template <typename K,typename V>void BTree<K,V>::Set_Value(V _value){    value = _value;}template <typename K,typename V>K BTree<K,V>::Get_Key(){    return key;}template <typename K,typename V>V BTree<K,V>::Get_Value(){    return value;}template <typename K,typename V>void Traverse(BTree<K,V>* _btree){    if(_btree->Is_Leaf())    {        // std::cout << _btree->Get_Key() << " " << _btree->Get_Value() << std::endl;        return;    }    else    {        if(_btree->Get_Left_Child())        {            // std::cout << "push_back 0" << std::endl;            Traverse(_btree->Get_Left_Child());            // std::cout << "pop_back 0" << std::endl;        }        if(_btree->Get_Right_Child())        {            // std::cout << "push_back 1" << std::endl;            Traverse(_btree->Get_Right_Child());            // std::cout << "pop_back 1" << std::endl;        }    }}template <typename K,typename V>void Traverse(BTree<K,V>* _btree,std::function<void(char)> _operation_push,std::function<void(char)> _operation_pop,std::function<void(char)> _operation_check){    if(_btree->Is_Leaf())    {        _operation_check(_btree->Get_Key());        return;    }    else    {        if(_btree->Get_Left_Child())        {            _operation_push('0');            Traverse(_btree->Get_Left_Child(),_operation_push,_operation_pop,_operation_check);            _operation_pop('0');        }        if(_btree->Get_Right_Child())        {            _operation_push('1');            Traverse(_btree->Get_Right_Child(),_operation_push,_operation_pop,_operation_check);            _operation_pop('1');        }    }}#endif

HuffmanTree.hpp

#ifndef __HUFFMANTREE__#define __HUFFMANTREE__#include "BTree.hpp"#include <string>#include <vector>#include <stack>#include <queue>#include <map>using namespace std;class HuffmanTree{public:    HuffmanTree();    HuffmanTree(string _info);    void Set_Info(string _info);    string Encode(string _str);    string Decode(string _code);private:    void Build_Tree();    void Encode_Assistant_Push(char _code);    void Encode_Assistant_Pop(char _code);    void Encode_Assistant_Check(char _original_char,char _tree_char);    string info;    string encode;    string sub_code;    string decode;    BTree<char,unsigned int>* huffman_tree;};#endif

HuffmanTree.cpp

#include "HuffmanTree.hpp"using namespace std;HuffmanTree::HuffmanTree(){    huffman_tree = nullptr;}HuffmanTree::HuffmanTree(string _info){    huffman_tree = nullptr;    info = _info;    Build_Tree();}void HuffmanTree::Set_Info(string _info){    info = _info;    Build_Tree();}void HuffmanTree::Build_Tree(){    map<char,unsigned int> key_value;    for(auto i:info)    {        bool inside = false;        for(auto index_map = key_value.begin();index_map != key_value.end();++index_map)        {            if(i == index_map->first)            {                index_map->second++;                inside = true;                break;            }        }        if(inside)        {            continue;        }        key_value.insert(pair<char,unsigned int>(i,1));    }    vector<char> key_vector;    for(auto i = key_value.begin();i != key_value.end();++i)    {        key_vector.push_back(i->first);    }    stack<char> key_stack;    while(!key_vector.empty())    {        auto it = vector<char>::iterator();        char key;        int max_time = 0;        for(auto i = key_vector.begin();i != key_vector.end();++i)        {            if(key_value[*i] > max_time)            {                key = *i;                it = i;                max_time = key_value[*i];            }        }        key_stack.push(*it);        key_vector.erase(it);    }    queue<BTree<char,unsigned int>*> sum_node_queue;    while(!key_stack.empty())    {        BTree<char,unsigned int>* left_node = new BTree<char,unsigned int>(true);        left_node->Set_Key(key_stack.top());        left_node->Set_Value(key_value[key_stack.top()]);        key_stack.pop();        if(key_stack.empty())        {            sum_node_queue.push(left_node);            break;        }        BTree<char,unsigned int>* right_node = new BTree<char,unsigned int>(true);        right_node->Set_Key(key_stack.top());        right_node->Set_Value(key_value[key_stack.top()]);        key_stack.pop();        BTree<char,unsigned int>* sum_node = new BTree<char,unsigned int>();        sum_node->Set_Key(0);        sum_node->Set_Left_Child(left_node);        sum_node->Set_Right_Child(right_node);        sum_node_queue.push(sum_node);    }    while(!sum_node_queue.empty())    {        BTree<char,unsigned int>* left_node = sum_node_queue.front();        sum_node_queue.pop();        BTree<char,unsigned int>* right_node = sum_node_queue.front();        sum_node_queue.pop();        BTree<char,unsigned int>* sum_node = new BTree<char,unsigned int>();        sum_node->Set_Left_Child(left_node);        sum_node->Set_Right_Child(right_node);        sum_node_queue.push(sum_node);        if(!(right_node != nullptr && left_node != nullptr))        {            huffman_tree = left_node;        }    }}string HuffmanTree::Encode(string _str){    encode.clear();    for(auto i:_str)    {        Traverse(huffman_tree,            bind(&HuffmanTree::Encode_Assistant_Push,this,placeholders::_1),            bind(&HuffmanTree::Encode_Assistant_Pop,this,placeholders::_1),            bind(&HuffmanTree::Encode_Assistant_Check,this,i,placeholders::_1));    }    return encode;}string HuffmanTree::Decode(string _code){    decode.clear();    auto node = huffman_tree;    for(auto i = _code.begin();i != _code.end();++i)    {        if(node->Is_Leaf())        {            decode.push_back(node->Get_Key());            node = huffman_tree;            i--;        }        else        {            if(*i == '0')            {                node = node->Get_Left_Child();            }            else if(*i == '1')            {                node = node->Get_Right_Child();            }        }    }    return decode;}void HuffmanTree::Encode_Assistant_Push(char _code){    sub_code.push_back(_code);}void HuffmanTree::Encode_Assistant_Pop(char _code){    sub_code.pop_back();}void HuffmanTree::Encode_Assistant_Check(char _original_char,char _tree_char){    if(_original_char == _tree_char)    {        encode += sub_code;    }}

Test.cpp

#include "BTree.hpp"#include "HuffmanTree.hpp"#include <iostream>#include <string>using namespace std;int main(int argc, char const *argv[]){    // Test BTree    // BTree<char,int>* huffman_tree = new BTree<char,int>();    // huffman_tree->Set_Key('a');    // huffman_tree->Set_Value(3);    // cout << huffman_tree->Get_Key() << " " << huffman_tree->Get_Value() << " " << huffman_tree->Is_Leaf() << endl;    // BTree<char,int>* huffman_tree_left_child = new BTree<char,int>(true);    // huffman_tree_left_child->Set_Key('b');    // huffman_tree_left_child->Set_Value(2);    // BTree<char,int>* huffman_tree_right_child = new BTree<char,int>(true);    // huffman_tree_right_child->Set_Key('c');    // huffman_tree_right_child->Set_Value(2);    // huffman_tree->Set_Left_Child(huffman_tree_left_child);    // huffman_tree->Set_Right_Child(huffman_tree_right_child);    // cout << huffman_tree->Get_Left_Child()->Get_Key() << " " << huffman_tree->Get_Left_Child()->Get_Value() << " " << huffman_tree->Get_Left_Child()->Is_Leaf() << endl;    // cout << huffman_tree->Get_Right_Child()->Get_Key() << " " << huffman_tree->Get_Right_Child()->Get_Value() << " " << huffman_tree->Get_Right_Child()->Is_Leaf() << endl;    // Traverse(huffman_tree);    // Test HuffmanTree    string test_string1 = "In computer science and information theory, ";    string test_string2 = "a Huffman code is a particular type of optimal prefix code that is commonly used for lossless data compression. ";    string test_string3 = "The process of finding and/or using such a code proceeds by means of Huffman coding, ";    string test_string4 = "an algorithm developed by David A. Huffman while he was a Ph.D. student at MIT, and published in the 1952 paper ";    string test_string5 = "\"A Method for the Construction of Minimum-Redundancy Codes\".[1] ";    string test_string6 = "The output from Huffman's algorithm can be viewed as a variable-length code table for encoding a source symbol ";    string test_string7 = "(such as a character in a file). The algorithm derives this table from the estimated probability or frequency of occurrence";    string test_string8 = " (weight) for each possible value of the source symbol. As in other entropy encoding methods, more common symbols are generally ";    string test_string9 = "represented using fewer bits than less common symbols. Huffman's method can be efficiently implemented, ";    string test_string10 = "finding a code in linear time to the number of input weights if these weights are sorted.[2] However, ";    string test_string11 = "although optimal among methods encoding symbols separately, Huffman coding is not always optimal among all compression methods.";    string test_string = test_string1 + test_string2 + test_string3 + test_string4 + test_string5 + test_string6 + test_string7 + test_string8 + test_string9 + test_string10 + test_string11;    HuffmanTree huffman_tree(test_string);    cout << "\"" << test_string << "\"" << " has been encoded as:" << endl;    cout << huffman_tree.Encode(test_string) << endl;    cout << "\"" << huffman_tree.Encode(test_string) << "\"" << " has been decoded as:" << endl;    cout << huffman_tree.Decode(huffman_tree.Encode(test_string)) << endl;    return 0;}

模板特化递归

template <typename K,typename V>void Traverse(BTree<K,V>* _btree){    if(_btree->Is_Leaf())    {        // std::cout << _btree->Get_Key() << " " << _btree->Get_Value() << std::endl;        return;    }    else    {        if(_btree->Get_Left_Child())        {            // std::cout << "push_back 0" << std::endl;            Traverse(_btree->Get_Left_Child());            // std::cout << "pop_back 0" << std::endl;        }        if(_btree->Get_Right_Child())        {            // std::cout << "push_back 1" << std::endl;            Traverse(_btree->Get_Right_Child());            // std::cout << "pop_back 1" << std::endl;        }    }}template <typename K,typename V>void Traverse(BTree<K,V>* _btree,std::function<void(char)> _operation_push,std::function<void(char)> _operation_pop,std::function<void(char)> _operation_check){    if(_btree->Is_Leaf())    {        _operation_check(_btree->Get_Key());        return;    }    else    {        if(_btree->Get_Left_Child())        {            _operation_push('0');            Traverse(_btree->Get_Left_Child(),_operation_push,_operation_pop,_operation_check);            _operation_pop('0');        }        if(_btree->Get_Right_Child())        {            _operation_push('1');            Traverse(_btree->Get_Right_Child(),_operation_push,_operation_pop,_operation_check);            _operation_pop('1');        }    }}

bind 函数绑定

string HuffmanTree::Encode(string _str){    encode.clear();    for(auto i:_str)    {        Traverse(huffman_tree,            bind(&HuffmanTree::Encode_Assistant_Push,this,placeholders::_1),            bind(&HuffmanTree::Encode_Assistant_Pop,this,placeholders::_1),            bind(&HuffmanTree::Encode_Assistant_Check,this,i,placeholders::_1));    }    return encode;}

后记

学校里的老师基本看不懂,因为他们不懂模板特化,不懂C++11,不懂泛型思维

于是在检查的时候狠狠地装了一回逼:)


CSDN 辣鸡 MD 编辑器,无序列表格式全丢