1、貪心算法求解流程:
通常自頂向下設計:做出一個選擇(做局部最優選擇),然後求解剩下的那個與原問題類似的子問題。
2、貪心算法設計步驟:
3、0-1揹包問題與分數揹包問題:
0-1揹包問題:【動態規劃】01揹包問題(通俗易懂,超基礎講解)
分數揹包問題:貪心算法,見算法導論16.2節
4、赫夫曼編碼: 目標:字符出現頻率高,使其二進制位數少
對於字符等數據,根據其出現頻率,通過赫夫曼貪心算法構造出字符的最優前綴碼(二進制表示),從而降低所佔空間。
前綴碼:沒有任何碼字是其他碼字的前綴。
最優前綴碼對應的樹有N個葉節點(字符個數),且恰有N-1個內部節點。
4.1、赫夫曼二進制編碼構造流程:
a)算法自底向上構造對應最優編碼的二叉樹T,從N個葉節點開始,執行N-1次合併操作創建最終二叉樹。
b)算法使用字符出現頻率爲關鍵字的最小優先隊列Q,以識別兩個最低頻率的對象將其合併,
c)合併兩對象時得到的新對象頻率設置爲兩原對象頻率之和。
流程圖如下:
4.2、赫夫曼二進制編碼構造C++代碼:
假設給定字符及其出現頻率組成結構的數組nodeArr
#include <queue>
struct node{
int num; // 字符出現頻率
char c; //字符
node* left;
node* right;
node(int x,char y):num(x),c(y),left(null),right(null){}
node():num(0),c('0'),left(null),right(null){}
bool operator< (const node& a){
return num>a.num; //從小到大排列
}
}
node* nodeArr[10]; // 假設已經給定,且存儲在動態內存
priority_queue<node*> q; // 按字符出現頻率由小到大排列
for(int i = 0;i<10;i++){
q.push(nodeArr[i]);
}
for(int i = 0;i<9;i++){ // 10個節點9條邊
node* z = new node;
node* tmp1 = q.front();
q.pop();
node* tmp2 = q.front();
q.pop();
z->left = tmp1;
z->right = tmp2;
z->num = tmp1->num +tmp2->num;
q.push(z);
}
node* root = q.front(); //樹的根節點
總結:
1、在構造哈夫曼編碼過程中,頻率低的放左節點,高的放右節點。
2、哈夫曼編碼通過將出現頻率高的字符用少數二進制位表示,從而降低使用空間,實現壓縮編碼。