# Huffman Code (Priority Queue) ## Huffman code tree 統計字元(串)出現的次數(頻率)做成node,存入priorty queue裡。每次取出前兩個頻率低的node,結合成一個新的node並push回priorty queue裡。push回去之前要記得將left, right child的指標接好。如此操作每次queue中node的數量會少1,因此執行node_num-1次,queue中就會剩下一個root node,huffman code tree也隨之建好。下圖是一個huffman code tree範例。 ![](https://i.imgur.com/9Nwd28t.png) 上圖表示a這個元素要用4個bits(tree depth = 4)、pen則要用2 bits(tree depth = 2)。 ## Priorty Queue用法整理 預設由大排到小: ``` priority_queue<T> pq; ``` 改成由小排到大: ``` priority_queue<T, vector<T>, greater<T> > pq; ``` 自定義cmp排序: ``` priority_queue<T, vector<T>, cmp> pq; ``` cmp寫法: ``` struct cmp{ bool operator()(T a, T b){ return ...; } }; ``` ## 範例code ``` #include<bits/stdc++.h> using namespace std; typedef long long ll; class Node{ public: int freq; Node* left_child; Node* right_child; Node* parent; string str; bool is_leaf; Node(string s1, int n, bool b){ left_child = nullptr; right_child = nullptr; parent = nullptr; is_leaf = b; str = s1; freq = n; } }; struct cmp{ bool operator()(Node* a, Node* b){ if(a->freq != b->freq){ return a->freq > b->freq; } return a->str > b->str; } }; void compress(unordered_map<string,int> &m, Node *r, int d){ if(r->is_leaf){ m[r->str] = d; return ; } if(r->left_child != nullptr){ compress(m, r->left_child, d+1); } if(r->right_child != nullptr){ compress(m, r->right_child, d+1); } } int main(){ ios_base::sync_with_stdio(false); cin.tie(0); int n; cin >> n; cin.ignore(); unordered_map<string, int> m; vector<vector<string>> input(n); for(int i=0;i<n;++i){ string s; getline(cin, s); stringstream ss(s); string tmp; while(ss >> tmp){ input[i].push_back(tmp); if(m.count(tmp) == 0){ m[tmp] = 1; }else{ m[tmp]++; } } } int len = m.size(); priority_queue<Node*,vector<Node*>,cmp> pq; for(const auto &v: m){ Node* node = new Node(v.first, v.second, 1); pq.push(node); } for(int i=0;i<len-1;++i){ Node* t1 = pq.top(); pq.pop(); Node* t2 = pq.top(); pq.pop(); string s_tmp = t1->str < t2->str ? t1->str: t2->str; Node* new_node = new Node(s_tmp, t1->freq+t2->freq, 0); new_node -> left_child = t1; new_node -> right_child = t2; pq.push(new_node); } Node* root = pq.top(); unordered_map<string,int> res; compress(res, root, 0); for(int i=0;i<n;++i){ ll cnt = 0; ll l = input[i].size(); for(int j=0;j<l;++j){ cnt += res[input[i][j]]; } printf("%.10f\n", (double)cnt / (l * ceil(log2(len)))); } return 0; } ```