美文网首页
哈夫曼算法简介

哈夫曼算法简介

作者: 秸秆混凝烧结工程师 | 来源:发表于2021-02-15 17:58 被阅读0次

    看官们建议在看我的这篇文章之前,先看一下RlE算法  这个是计算机压缩算法的入门级,如果连这个算法的思想都不清楚的,请私聊我,单独讲解

    简单说一下rle=字符乘以重复数量

    举个例子,aaaaaabbbbbb的rlu就是a6b6

    说回哈夫曼算法


    第一  统计每个字符出现的次数

    第二  将出现次数最少的字符连线并求数量和

    第三  重复第二步完成哈夫曼树

    第四  将哈夫曼树的左边的边写上0,右边的边也写上  1 

    第五  从根节点开始沿着边去将数字写在对应的字符下面

    这样一个哈夫曼编码就完成了

    #include <iostream>

    #include <iomanip>

    using namespace std;

    //哈夫曼树的存储表示

    typedef struct

    {

        int weight;    // 权值

        int parent, lChild, rChild;    // 双亲及左右孩子的下标

    }HTNode, *HuffmanTree;

    // 选择权值最小的两颗树

    void SelectMin(HuffmanTree hT, int n, int &s1, int &s2)

    {

        s1 = s2 = 0;

        int i;

        for(i = 1; i < n; ++ i){

            if(0 == hT[i].parent){

                if(0 == s1){

                    s1 = i;

                }

                else{

                    s2 = i;

                    break;

                }

            }

        }

        if(hT[s1].weight > hT[s2].weight){

            int t = s1;

            s1 = s2;

            s2 = t;

        }

        for(i += 1; i < n; ++ i){

            if(0 == hT[i].parent){

                if(hT[i].weight < hT[s1].weight){

                    s2 = s1;

                    s1 = i;

                }else if(hT[i].weight < hT[s2].weight){

                    s2 = i;

                }

            }

        }

    }

    // 构造有n个权值(叶子节点)的哈夫曼树

    void CreateHufmanTree(HuffmanTree &hT)

    {

        int n, m;

        cin >> n;

        m = 2*n - 1;

        hT = new HTNode[m + 1];    // 0号节点不使用

        for(int i = 1; i <= m; ++ i){

            hT[i].parent = hT[i].lChild = hT[i].rChild = 0;

        }

        for(int i = 1; i <= n; ++ i){

            cin >> hT[i].weight;    // 输入权值

        }

        hT[0].weight = m;    // 用0号节点保存节点数量

        /****** 初始化完毕, 创建哈夫曼树 ******/

        for(int i = n + 1; i <= m; ++ i){

            int s1, s2;

            SelectMin(hT, i, s1, s2);

            hT[s1].parent = hT[s2].parent = i;

            hT[i].lChild = s1; hT[i].rChild = s2;    // 作为新节点的孩子

            hT[i].weight = hT[s1].weight + hT[s2].weight;    // 新节点为左右孩子节点权值之和

        }

    }

    int HuffmanTreeWPL_(HuffmanTree hT, int i, int deepth)

    {

        if(hT[i].lChild == 0 && hT[i].rChild == 0){

            return hT[i].weight * deepth;

        }

        else{

            return HuffmanTreeWPL_(hT, hT[i].lChild, deepth + 1) + HuffmanTreeWPL_(hT, hT[i].rChild, deepth + 1);

        }

    }

    // 计算WPL(带权路径长度)

    int HuffmanTreeWPL(HuffmanTree hT)

    {

        return HuffmanTreeWPL_(hT, hT[0].weight, 0);

    }

    // 输出哈夫曼树各节点的状态

    void Print(HuffmanTree hT)

    {

        cout << "index weight parent lChild rChild" << endl;

        cout << left;    // 左对齐输出

        for(int i = 1, m = hT[0].weight; i <= m; ++ i){

            cout << setw(5) << i << " ";

            cout << setw(6) << hT[i].weight << " ";

            cout << setw(6) << hT[i].parent << " ";

            cout << setw(6) << hT[i].lChild << " ";

            cout << setw(6) << hT[i].rChild << endl;

        }

    }

    // 销毁哈夫曼树

    void DestoryHuffmanTree(HuffmanTree &hT)

    {

        delete[] hT;

        hT = NULL;

    }

    int main()

    {

        HuffmanTree hT;

        CreateHufmanTree(hT);

        Print(hT);

        cout << "WPL = " << HuffmanTreeWPL(hT) << endl;

        DestoryHuffmanTree(hT);

        return 0;

    }

    相关文章

      网友评论

          本文标题:哈夫曼算法简介

          本文链接:https://www.haomeiwen.com/subject/mlzpxltx.html