貪心算法(求解最優化問題)及其應用赫夫曼編碼

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、哈夫曼編碼通過將出現頻率高的字符用少數二進制位表示,從而降低使用空間,實現壓縮編碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章