不定长哈夫曼树

Posted dalgleish

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了不定长哈夫曼树相关的知识,希望对你有一定的参考价值。

原理参考《算法导论》,我借用了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
", 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) :root(NULL) {
        Huffman_init(keys, freqs, n);
    }
    Huffman *Huffman_init(int *keys, int *freqs, int n);
    ~Huffman(){
        Huffman_empty(root);
    }
    Huffnode *Huffman_root();
    void Huffman_print(Huffnode *x, std::string str);
    void Huffman_empty(Huffnode *x);
private:
    Huffnode *root;
    std::deque<Huffnode *> Q;//优先队列
};

对应的成员函数实现

 Huffman_init成员函数,构建Huffman树

Huffman *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);//从小到大的排序
    }
    while (Q.size() != 1) {//至少保证有两个节点
        left = Q.front();
        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);//加入到队列
    }
    root = Q.front();
    Q.pop_front();
    return this;
}

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

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

Huffman_empty成员函数,像二叉树一样,采用后续删除节点

void Huffman::Huffman_empty(Huffnode *x) {
    if (x != NULL) {
        if (x != NULL) {
            Huffman_empty(x->l);
            Huffman_empty(x->r);
            delete x;//后续删除
        }
    }
}

数据录入

技术分享图片

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(key, freq, sizeof(key) / sizeof(key[0]));
    huff.Huffman_print(huff.Huffman_root()," ");
    return 0;
}

结果图

技术分享图片

对应树上的结果

技术分享图片

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

以上是关于不定长哈夫曼树的主要内容,如果未能解决你的问题,请参考以下文章

(哈夫曼树)HuffmanTree的java实现

构造一棵哈夫曼树

51nod 1117 聪明的木匠:哈夫曼树

构造一棵哈夫曼树

构造一棵哈夫曼树

构造一棵哈夫曼树