原理参考《算法导论》,我借用了stl中的deque类,这样方便构造书中说的有序队列Q。其次,本博客的所有代码都采用C和C++混编形式,所以建议使用VS2015及其以上版本编译代码。

代码如下

声明一个Huffman类以及对应的节点数据

typedef struct _Huffnode {
    _Huffnode(int _key, int _freq)
        :p(NULL), l(NULL), r(NULL), key(_key), freq(_freq) {}
    ~_Huffnode() {
        //printf("%c delete\n", key);
    }
    int freq, key;
    _Huffnode *l, *r, *p;
}Huffnode, *pHuffnode;

struct Compare {
    bool operator()(const  _Huffnode *lhs, const _Huffnode *rhs) {
        return lhs->freq < rhs->freq;
    }
};

class Huffman {
public:
    Huffman(int *keys, int *freqs, int n) :huffman_root(NULL) {
        Huffman_init(keys, freqs, n);
    }
    ~Huffman(){
        Huffman_empty(huffman_root);
    }
    Huffnode *Huffman_root();
    Huffnode *Huffman_init(int *keys, int *freqs, int n);
    void Huffman_print(Huffnode *x, std::string str);
    void Huffman_empty(std::deque<Huffnode *> x);
private:
    std::deque<Huffnode *> Q, huffman_root;//优先队列
};

对应的成员函数实现

 Huffman_init成员函数,构建Huffman树

Huffnode *Huffman::Huffman_init(int *keys, int *freqs, int n) {
    Huffnode *q, *left, *right;
    for (int i = 0; i < n; i++) {
        q = new Huffnode(keys[i], freqs[i]);
        Q.insert(std::upper_bound(Q.begin(), Q.end(), q, Compare()), q);//从小到大的排序
    }
    for (std::deque<Huffnode *>::iterator itr = Q.begin(); itr != Q.end(); itr++)
        printf("%c:%d ", (*itr)->key, (*itr)->freq);
    printf("\n");
    while (Q.size() != 1) {//至少保证有两个节点
        left = Q[0];
        Q.pop_front();
        right = Q.front();
        Q.pop_front();//两个次小节点
        q = new Huffnode('.', left->freq + right->freq);
        q->l = left;
        q->r = right;
        Q.insert(std::upper_bound(Q.begin(), Q.end(), q, Compare()), q);//加入到队列
        huffman_root.push_front(q->r);
        huffman_root.push_front(q->l);
    }
    q = Q.front();
    Q.pop_front();
    huffman_root.push_front(q);
    return huffman_root[0];
}

Huffman_print成员函数,输出对应的关键字key的变长字码

void Huffman::Huffman_print(Huffnode *x, std::string str) {
    if (x == NULL) return;
    if (x->key != '.')//跳过节点'.'
        printf("%c:%s\n", x->key, str.c_str());
    Huffman_print(x->l, str + "0");
    Huffman_print(x->r, str + "1");
}

Huffman_empty成员函数

void Huffman::Huffman_empty(std::deque<Huffnode *> x) {
    while (!x.empty()) {
        delete x.back();
        x.pop_back();
    }
}

数据录入

int key[] = { 'f','e','c','b','a','d' }, freq[] = { 5,9,12,13,45,16 };

Main函数

int main()
{
    int key[] = { 'f','e','c','b','a','d' }, freq[] = { 5,9,12,13,45,16 };
    Huffman *huff=new Huffman(key, freq, sizeof(key) / sizeof(key[0]));
    huff->Huffman_print(huff->Huffman_root()," ");
    printf("对象释放....\n");
    delete huff;
    if (_CrtDumpMemoryLeaks())
        printf("内存泄漏,请使用F5 debug模式查看!\n");//内存泄漏检测
    else
        printf("无内存泄漏!\n");
    return 0;
}

结果图

对应树上的结果

代码均经过测试,结果正确!

posted on 2018-06-15 13:27  dalgleish  阅读(176)  评论(0编辑  收藏  举报