• 哈夫曼树编码


     


    对输入的英文大写字母进行统计概率 然后构建哈夫曼树,输出是按照概率降序排序输出Huffman编码
    输入
      大写字母个数 n 第一个字母 第二个字母 第三个字母 ... 第n个字母
     
    输出
     字母1 出现次数 Huffman编码 
     字母2 出现次数 Huffman编码 
     字母3 出现次数 Huffman编码 
     … 
     字母n 出现次数 Huffman编码

    Sample In
    10
    I I U U U I U N U U
     
    Sample Out
    U 6 1
    I 3 01
    N 1 00

    解决此题首先要明白HuffmanTree的构造原理

    首先来看一个简单的例子:
    把某个班同学百分制的成绩转换成5分制,规则如下,
     
    90~100     5
    80~90       4
    70~80       3
    60~70       2
    <60           1
     
    看起来很容易实现
    即 if (score<60)
         grade=1;
         else if(score<70)
         grade=2;
         else if(score<80)
         grade=3;
         else if(score<90)
         grade=4;
         else
         grade=5;
    但是如果这个班的同学大多数都取得了90分以上的好成绩,那么前面4步的判断是很没必要且费时的。
    很明显,这种算法在面对大量数据的时候是比较不合理的。
    那么如何优化算法呢?
    假定我们目前已经知道了这个班成绩的分布律
     

    成绩

    <60

    60~70

    70~80

    80~90

    90~100

    比例

    0.05

    0.15

    0.33

    0.27

    0.20

     
    如果用刚才的办法,则算法的效率是多少呢,用比例乘上判断的次数0.05*1+0.15*2+0.33*3+0.27*4+0.20*4=3.22
    我们稍微修改一下算法,先判断比例最大的,
    即   if(score<80)
        {
            if(score<70)
                if(score<60)
                grade=1;
            else
                grade=2;
            else
                grade=3;
        }
        else if(score<90)
            grade=4;
        else
            grade=5;
          
    改良后的算法效率为0.05*3+0.15*3+0.33*2+0.27*2+0.2*2=2.2
    很明显,改良后的算法效率增加了很多。
    由树的定义可以把刚才的程序抽象成下图所示的"树":
     
     
    那么如何构造一个效率更好或者最好的搜索树呢,这就是哈夫曼树要解决的问题。
    构造HuffmanTree思想:把权值(频率)从小到大排序,把权值最小的两颗二叉树合并
    比如现有权值为1,2,3,4,5的节点(已经排好序)。
    1.选择最小的两个,即1和2,合并,权值之和为3,
    2.从刚才合并好的3和剩下的3,4,5里选择两个最小的,即3和3,合并,权值之和为6
    3.从6,4,5里选择两个最小的,即4和5,合并,权值之和为9
    4.将6和9合并,权值之和为15
    下图为形成的哈夫曼树:
     
    对于上面的问题,我们的思路之一应该是这样
    1.统计相同字符出现的次数并记录之
    2.根据统计好的结果构造哈夫曼树
    3.获得哈夫曼编码
    4.按题目要求格式打印
    那么写出代码就是轻而易举的事情了:
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    
    template<class T>
    struct StaFrequency
    {
        T data;
        int times;
        StaFrequency();
        StaFrequency(T data,int times) {this->data=data;this->times=times;}
    };
    template<class T>
    struct TriNode
    {
        T data;
        int parent,left,right;
    };
    template<class T>
    class HuffmanTree
    {
    private:
        int leafNum;
        TriNode<int> *huftree;
        char **hufcodes;
        void createHuffmanTree(T weight[],int n);
        void getHuffmanCode();
    public:
        HuffmanTree(T weight[],int n);
        ~HuffmanTree() {delete []huftree;delete []hufcodes;};
        void print(int i);
    };
    const int Max_Weight=9999;
    template <class T>
    HuffmanTree<T>::HuffmanTree(T weight[],int n)
    {
        createHuffmanTree(weight,n);
        getHuffmanCode();
    }
    //构造哈夫曼树
    template <class T>
    void HuffmanTree<T>::createHuffmanTree(T weight[],int n)
    {
        leafNum=n;
        huftree=new TriNode<int>[2*n-1];
        int i;
        for(i=0;i<n;i++)
        {
            huftree[i].data=weight[i];
            huftree[i].parent=huftree[i].left=huftree[i].right=-1;
        }
        for(i=0;i<n-1;i++)
        {
            int min1,min2,x1,x2;
            min1=min2=Max_Weight;
            x1=x2=-1;
            for(int j=0;j<n+i;j++)
            {
                if(huftree[j].data<min1&&huftree[j].parent==-1)
                {
                    min2=min1;
                    x2=x1;
                    min1=huftree[j].data;
                    x1=j;
                }
                else if(huftree[j].data<min2&&huftree[j].parent==-1)
                {
                    min2=huftree[j].data;
                    x2=j;
                }
            }
            huftree[x1].parent=n+i;
            huftree[x2].parent=n+i;
            huftree[n+i].data=huftree[x1].data+huftree[x2].data;
            huftree[n+i].parent=-1;
            huftree[n+i].left=x1;
            huftree[n+i].right=x2;
        }
    }
    //获得哈夫曼编码
    template <class T>
    void HuffmanTree<T>::getHuffmanCode()
    {
        int n=leafNum;
        hufcodes=new char *[n];
        for(int i=0;i<n;i++)
        {
            char * code=new char[n];
            code[n-1]='';
            int start=n-1;
            int child=i;
            int parent=huftree[child].parent;
            while(parent!=-1)
            {
                start--;
                if(huftree[parent].left==child)
                    code[start]='0';
                else
                    code[start]='1';
                child=parent;
                parent=huftree[child].parent;
            }
            hufcodes[i]=code+start;
        }
    }
    //打印哈夫曼编码
    template <class T>
    void HuffmanTree<T>::print(int i)
    {
        cout<<hufcodes[i]<<endl;
    }
    int main()
    {
        int m;
        cin>>m;
        char weight[m];
        for(int i=0;i<m;i++)
            cin>>weight[i];
    int i=0,n=0,sum=0,num=0,x=0;
    int s[m];
    char w[m];
    bool flag;
    for(i=0;i<m;i++)
    {
       flag=true;
       sum=0;
       for(int j=i-1;j>=0;j--)//检测是否有已经算过的字母
       {
          if(weight[j]==weight[i])
          {
          flag=false;
          break;
      }
    }
    for(n=i;n<m&&flag;n++)//若上一步没有,则算相同的个数
    {
    if(weight[i]==weight[n])
    {
    sum++;
    }
    }
    if(flag) //存储相同字符及个数
       {
      s[num++]=sum;
      w[x++]=weight[i];
    }
    }
        //就写个最简单的冒泡排序吧
        for(int k=0;k<num;k++)
        {
            for(int j=0; j<num-1-k; j++)
            {
                if(s[j]<s[j+1])
                {
                    swap(s[j],s[j+1]);
                    swap(w[j],w[j+1]);
                }
    
    
            }
        }
        HuffmanTree<int> htree(s,num);
        for(int i=0;i<num;i++)
        {
            cout<<w[i]<<" "<<s[i]<<" ";
            htree.print(i);
        }
        return 0;
    }
  • 相关阅读:
    leetcode 63 简单题
    leetcode 712
    500 问的数学基础
    转载一份kaggle的特征工程:经纬度、特征构造、转化率
    散度
    在线学习在CTR上应用的综述
    广告的计费方式
    矩阵2范数与向量2范数的关系
    text_CNN笔记
    F1
  • 原文地址:https://www.cnblogs.com/NikkiNikita/p/9450776.html
Copyright © 2020-2023  润新知