哈夫曼樹編碼__c

來源:互聯網
上載者:User


對輸入的英文大寫字母進行統計機率 然後構建哈夫曼樹,輸出是按照機率降序排序輸出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]='\0';
        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;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.