1. 程式人生 > >請設計一個演算法,給一個字串進行二進位制編碼,使得編碼後字串的長度最短。(哈弗曼編碼)

請設計一個演算法,給一個字串進行二進位制編碼,使得編碼後字串的長度最短。(哈弗曼編碼)

美團點評2016研發工程師程式設計題(二)

請設計一個演算法,給一個字串進行二進位制編碼,使得編碼後字串的長度最短。


輸入描述:
每組資料一行,為待編碼的字串。保證字串長度小於等於1000。


輸出描述:
一行輸出最短的編碼後長度。

輸入例子:
MT-TECH-TEAM

輸出例子:

33

分析:哈夫曼編碼的過程,用一個最小堆實現,將當前最小的兩個數取出來,求和後繼續推入堆中。

程式碼:

  1. #include <iostream>
  2. #include <queue>
  3. #include <algorithm>
  4. #include <functional>
  5. #include <string>
  6. usingnamespace std;  
  7. int main() {  
  8.     string s;  
  9.     while (getline(cin, s)) {  
  10.         int ret=0;  
  11.         int n = s.size();  
  12.         sort(s.begin(), s.end());  
  13.         int cnt = 0;  
  14.         priority_queue<int, vector<int>, greater<int> > heap;  
  15.         for
     (int i = 0, j; i < n;) {  
  16.             j = i;  
  17.             while (j < n && s[j] == s[i]) ++j;  
  18.             heap.push(j - i);  
  19.             i = j;  
  20.             ++cnt;  
  21.         }  
  22.         for (int i = 0; i < cnt-1; i++) {  
  23.             int a = heap.top();  
  24.             heap.pop();  
  25.             int b = heap.top();  
  26.             heap.pop();  
  27.             heap.push(a+b);  
  28.             ret += a + b;  
  29.         }  
  30.         cout << ret << endl;  
  31.     }  
  32.     return 0;  
  33. }  

  1. #include<map>
  2. #include<iostream>
  3. #include<string>
  4. usingnamespace std;  
  5. struct BTreeNode    
  6. {    
  7.     int weight;    
  8.     char value;  
  9.     struct BTreeNode* left;    
  10.     struct BTreeNode* right;    
  11. };    
  12. struct BTreeNode* CreateHuffman(int weight[],char value[], int n)  
  13. {  
  14.     int i, j;  
  15.     struct BTreeNode **b, *q;  
  16.     b = (BTreeNode **) malloc(n*sizeof(struct BTreeNode));  
  17.     for (i = 0; i < n; i++) //初始化b指標陣列,使每個指標元素指向a陣列中對應的元素結點
  18.     {  
  19.         b[i] = (BTreeNode *) malloc(sizeof(struct BTreeNode));  
  20.         b[i]->weight= weight[i];  
  21.         b[i]->value=value[i];  
  22.         b[i]->left = b[i]->right = NULL;  
  23.     }  
  24.     for (i = 1; i < n; i++)//進行 n-1 次迴圈建立哈夫曼樹
  25.     {  
  26.         //k1表示森林中具有最小權值的樹根結點的下標,k2為次最小的下標
  27.         int k1 = -1, k2;  
  28.         for (j = 0; j < n; j++)//讓k1初始指向森林中第一棵樹,k2指向第二棵
  29.         {  
  30.             if (b[j] != NULL && k1 == -1)  
  31.             {  
  32.                 k1 = j;  
  33.                 continue;  
  34.             }  
  35.             if (b[j] != NULL)  
  36.             {  
  37.                 k2 = j;  
  38.                 break;  
  39.             }  
  40.         }  
  41.         for (j = k2; j < n; j++)//從當前森林中求出最小權值樹和次最小
  42.         {  
  43.             if (b[j] != NULL)  
  44.             {  
  45.                 if (b[j]->weight < b[k1]->weight)  
  46.                 {  
  47.                     k2 = k1;  
  48.                     k1 = j;  
  49.                 }  
  50.                 elseif (b[j]->weight < b[k2]->weight)  
  51.                     k2 = j;  
  52.             }  
  53.         }  
  54.         //由最小權值樹和次最小權值樹建立一棵新樹,q指向樹根結點
  55.         q = (BTreeNode *) malloc(sizeof(struct BTreeNode));  
  56.         q->weight = b[k1]->weight + b[k2]->weight;  
  57.         q->value='\0';  
  58.         q->left = b[k1];  
  59.         q->right = b[k2];  
  60.         b[k1] = q;//將指向新樹的指標賦給b指標陣列中k1位置
  61.         b[k2] = NULL;//k2位置為空
  62.     }  
  63.     free(b); //刪除動態建立的陣列b
  64.     return q; //返回整個哈夫曼樹的樹根指標
  65. };  
  66. int HuffManCoding(struct BTreeNode* FBT, int len)//len初始值為0  
  67. {    
  68.     if (FBT != NULL)//訪問到葉子結點時輸出其儲存在陣列a中的0和1序列編碼  
  69.     {    
  70.         if (FBT->left == NULL && FBT->right == NULL)    
  71.         {    
  72.            return FBT->weight*len;   
  73.         }    
  74.         else//訪問到非葉子結點時分別向左右子樹遞迴呼叫,並把分支上的0、1編碼儲存到陣列a  
  75.         {   //的對應元素中,向下深入一層時len值增1  
  76.             return HuffManCoding(FBT->left, len + 1)+  HuffManCoding(FBT->right, len + 1);    
  77.         }    
  78.     }    
  79. }   
  80. int getMinCode(string s)  
  81. {  
  82.     map<char,int> m;  
  83.     map<char,int>::iterator it;;  
  84.     int len=s.length();  
  85.     //統計每個字元的頻率
  86.     for(int i=0;i<len;i++)  
  87.     {  
  88.         it=m.find(s[i]);//返回的是一個指標
  89.         if(it==m.end())//沒找到
  90.         {  
  91.             m.insert(pair<char,int> (s[i],1));  
  92.         }else
  93.         {  
  94.             m[s[i]]=m.find(s[i])->second+1;  
  95.         }  
  96.     }  
  97.     //構建哈夫曼樹
  98.     int size=m.size();  
  99.     int* weight=(int *)malloc(size*sizeof(int));  
  100.     char* value=(char *)malloc(size*sizeof(char));  
  101.     int j=0;  
  102.     for ( it = m.begin( ) ; it != m.end() ; it++ )  
  103.     {  
  104.         weight[j]=it->second;  
  105.         value[j]=it->first;  
  106.         j++;  
  107.     }  
  108.     BTreeNode* root= CreateHuffman(weight,value, size);  
  109.     //深度優先遍歷
  110.     return HuffManCoding(root,0);  
  111. }  
  112. int main()  
  113. {  
  114.     string s;  
  115.     cin>>s;  
  116.     cout<<getMinCode(s);  
  117.     return 0;  
  118. }  

我的程式碼:

#include<iostream>
#include<string>
#include<queue>
using namespace std;


class Node {
public: int data;
Node* lchild;
Node* rchild;


Node(int data_input) {
data = data_input;
lchild = NULL;
rchild = NULL;
}
~Node() {
if(lchild == NULL) {
delete lchild;
}<