請設計一個演算法,給一個字串進行二進位制編碼,使得編碼後字串的長度最短。(哈弗曼編碼)
阿新 • • 發佈:2019-02-10
美團點評2016研發工程師程式設計題(二)
請設計一個演算法,給一個字串進行二進位制編碼,使得編碼後字串的長度最短。
輸入描述:
每組資料一行,為待編碼的字串。保證字串長度小於等於1000。
輸出描述:
一行輸出最短的編碼後長度。
輸入例子:
MT-TECH-TEAM
輸出例子:
33
分析:哈夫曼編碼的過程,用一個最小堆實現,將當前最小的兩個數取出來,求和後繼續推入堆中。
程式碼:
- #include <iostream>
- #include <queue>
- #include <algorithm>
-
#include <functional>
- #include <string>
- usingnamespace std;
- int main() {
- string s;
- while (getline(cin, s)) {
- int ret=0;
- int n = s.size();
- sort(s.begin(), s.end());
- int cnt = 0;
- priority_queue<int, vector<int>, greater<int> > heap;
-
for
- j = i;
- while (j < n && s[j] == s[i]) ++j;
- heap.push(j - i);
- i = j;
- ++cnt;
- }
- for (int i = 0; i < cnt-1; i++) {
- int a = heap.top();
-
heap.pop();
- int b = heap.top();
- heap.pop();
- heap.push(a+b);
- ret += a + b;
- }
- cout << ret << endl;
- }
- return 0;
- }
- #include<map>
- #include<iostream>
- #include<string>
- usingnamespace std;
- struct BTreeNode
- {
- int weight;
- char value;
- struct BTreeNode* left;
- struct BTreeNode* right;
- };
- struct BTreeNode* CreateHuffman(int weight[],char value[], int n)
- {
- int i, j;
- struct BTreeNode **b, *q;
- b = (BTreeNode **) malloc(n*sizeof(struct BTreeNode));
- for (i = 0; i < n; i++) //初始化b指標陣列,使每個指標元素指向a陣列中對應的元素結點
- {
- b[i] = (BTreeNode *) malloc(sizeof(struct BTreeNode));
- b[i]->weight= weight[i];
- b[i]->value=value[i];
- b[i]->left = b[i]->right = NULL;
- }
- for (i = 1; i < n; i++)//進行 n-1 次迴圈建立哈夫曼樹
- {
- //k1表示森林中具有最小權值的樹根結點的下標,k2為次最小的下標
- int k1 = -1, k2;
- for (j = 0; j < n; j++)//讓k1初始指向森林中第一棵樹,k2指向第二棵
- {
- if (b[j] != NULL && k1 == -1)
- {
- k1 = j;
- continue;
- }
- if (b[j] != NULL)
- {
- k2 = j;
- break;
- }
- }
- for (j = k2; j < n; j++)//從當前森林中求出最小權值樹和次最小
- {
- if (b[j] != NULL)
- {
- if (b[j]->weight < b[k1]->weight)
- {
- k2 = k1;
- k1 = j;
- }
- elseif (b[j]->weight < b[k2]->weight)
- k2 = j;
- }
- }
- //由最小權值樹和次最小權值樹建立一棵新樹,q指向樹根結點
- q = (BTreeNode *) malloc(sizeof(struct BTreeNode));
- q->weight = b[k1]->weight + b[k2]->weight;
- q->value='\0';
- q->left = b[k1];
- q->right = b[k2];
- b[k1] = q;//將指向新樹的指標賦給b指標陣列中k1位置
- b[k2] = NULL;//k2位置為空
- }
- free(b); //刪除動態建立的陣列b
- return q; //返回整個哈夫曼樹的樹根指標
- };
- int HuffManCoding(struct BTreeNode* FBT, int len)//len初始值為0
- {
- if (FBT != NULL)//訪問到葉子結點時輸出其儲存在陣列a中的0和1序列編碼
- {
- if (FBT->left == NULL && FBT->right == NULL)
- {
- return FBT->weight*len;
- }
- else//訪問到非葉子結點時分別向左右子樹遞迴呼叫,並把分支上的0、1編碼儲存到陣列a
- { //的對應元素中,向下深入一層時len值增1
- return HuffManCoding(FBT->left, len + 1)+ HuffManCoding(FBT->right, len + 1);
- }
- }
- }
- int getMinCode(string s)
- {
- map<char,int> m;
- map<char,int>::iterator it;;
- int len=s.length();
- //統計每個字元的頻率
- for(int i=0;i<len;i++)
- {
- it=m.find(s[i]);//返回的是一個指標
- if(it==m.end())//沒找到
- {
- m.insert(pair<char,int> (s[i],1));
- }else
- {
- m[s[i]]=m.find(s[i])->second+1;
- }
- }
- //構建哈夫曼樹
- int size=m.size();
- int* weight=(int *)malloc(size*sizeof(int));
- char* value=(char *)malloc(size*sizeof(char));
- int j=0;
- for ( it = m.begin( ) ; it != m.end() ; it++ )
- {
- weight[j]=it->second;
- value[j]=it->first;
- j++;
- }
- BTreeNode* root= CreateHuffman(weight,value, size);
- //深度優先遍歷
- return HuffManCoding(root,0);
- }
- int main()
- {
- string s;
- cin>>s;
- cout<<getMinCode(s);
- return 0;
- }
我的程式碼:
#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;
}<