貪心 哈夫曼編碼

2021-09-27 11:59:25 字數 3119 閱讀 6190

哈夫曼編碼:

所謂編碼就是對於任意給定的文字,通過查閱編碼表逐一將其中的字元轉譯為二進位制編碼,這些編碼依次串接起來即得到了全文的編碼。

編碼方案確定後,儘管編碼結果必然確定,但解碼過程和結果卻不見得唯一。例如,字元a的編碼為01,b的編碼為011,c的編碼為11,d的編碼為101。當給定一串字元011101,結果可以編譯為aca,也可以編譯為bd。從而導致歧義。分析不難發現,出現歧義的原因是a的編碼是b編碼的字首。

為了避免歧義的出現,在制定編碼方案時,我們應該保證每乙個編碼節點不能是另乙個編碼節點的父節點。

2023年,數學家d.a.huffman提出了根據字元在檔案**現的頻率,用0/1的數字串表示各字元的最佳編碼方式。

演算法思想:

哈夫曼編碼:根據字元的使用頻率作為權值構建一棵哈夫曼樹,然後利用哈夫曼樹對字元進行編碼。構造一棵哈夫曼樹,是將所要編碼的字元作為葉子節點,該字元的使用頻率作為葉子節點的權值,以自底向上的方式,通過不斷合併後構造出的一棵樹。

演算法採用的貪心策略是:在森林中不斷尋找兩個權值最小且沒有父節點的節點,然後將其合併為一棵二叉樹,直至森林中僅剩一棵樹。

構造步驟:

獲取字元及其出現的頻率,將這樣的數值作為樹節點放入森林

遍歷森林,找到節點權值最小且沒有父節點的兩個節點

合併2中的兩個節點,權值較小的作為左孩子,另乙個作為右孩子

將新生成的樹放入森林,且轉至2,繼續查詢,直至森林中僅剩一棵樹

實現思路:

為了操作方便,我們宣告乙個節點結構體,包含父節點、左孩子、右孩子、字元、以及出現的頻率等資料域,並且採用陣列儲存這些節點。

初始狀態下(節點沒有父節點、左孩子、右孩子、出現頻率),因此我們首先對儲存陣列初始化,初始化標準:父節點、左孩子、右孩子均為-1,出現頻率為0。

初始結束後,獲取各個節點的資料(字元、出現頻率)。通過遍歷儲存陣列,不斷從其中找到權重較小的兩個節點合併。但是由於數值獲取的隨機性即權重較小的節點在陣列中儲存的位置隨機,因此我們不得不每次都對整個儲存陣列進行遍歷,此外為了避免已經合併過的節點再次合併,我們在查詢過程中還需要加上乙個條件-節點的父節點域為-1(即不存在父節點)。

合併過程:因為採用陣列儲存,所以每次合併後,只需要將新合成的節點放入陣列末尾即可。

**示例:

void

create_huff_tree

(int n)

else

if(huffnode[j]

.weight < m2)}}

huffnode[x1]

.parent = n + i;

//更新找到的兩個節點父節點

huffnode[x2]

.parent = n + i;

huffnode[n+i]

.weight = m1 + m2;

//生成新節點,且加入森林

huffnode[n+i]

.left = x1;

huffnode[n+i]

.right = x2;

}

編碼步驟:

分析:編碼過程中,每個待編碼字元都是樹的葉子節點,並且樹的節點採用陣列儲存。因此,我們可以遍歷0-n號元素(0-n,為待編碼字元節點),從葉子節點向根編碼。

為了對應每乙個待編碼節點,我們宣告乙個結構體,包含記錄二進位制資訊的陣列以及陣列的開始位置。

因為葉子節點的深度可能不一致,因此宣告乙個臨時變數儲存編碼資訊

遍歷葉子節點到根節點中間的節點。在此規定,左子樹為0,右子樹為1,因此遍歷過程中需要判斷是左子樹還是右子樹。

**示例:

void

huff_coding

(int n)

for(

int j = temp.start+

1; j < n; j++

)//臨時變數賦值給對應變數儲存編碼

huffcode[i]

.bit[j]

= temp.bit[j]

; huffcode[i]

.start = temp.start;

}}

完整**:
#include

using

namespace std;

#define max_value 1e7

#define max_size 100

struct node

;struct code

;node huffnode[max_size]

;code huffcode[max_size]

;void

create_huff_tree

(int n)

else

if(huffnode[j]

.weight < m2)}}

huffnode[x1]

.parent = n + i;

huffnode[x2]

.parent = n + i;

huffnode[n+i]

.weight = m1 + m2;

huffnode[n+i]

.left = x1;

huffnode[n+i]

.right = x2;}}

void

huff_coding

(int n)

for(

int j = temp.start+

1; j < n; j++

) huffcode[i]

.bit[j]

= temp.bit[j]

; huffcode[i]

.start = temp.start;}}

intmain()

for(

int i =

0; i < n; i++

)create_huff_tree

(n);

huff_coding

(n);

for(

int i =

0; i < n; i++

) cout << endl;

}return0;

}

貪心 哈夫曼編碼 哈夫曼樹

解決問題 哈夫曼樹 眾所周知,計算機以01串來儲存和運算。所以,如果我們想要存乙個字元或漢字,例如a,計算機會將它變為乙個01串,這個串就是a的編碼。如果我們輸入了乙個詞 cat。如果a的編碼是1,c的編碼是10,t的編碼是11,那麼 cat 對應的編碼就是 10111 好了,那麼問題來了 1011...

哈夫曼編碼(貪心)

題目描述 給定乙隻含有小寫字母的字串 輸出其哈夫曼編碼的長度 輸入第一行乙個整數t,代表樣例的個數,接下來t行,每行乙個字串,0輸出 對於每個字串,輸出其哈夫曼編碼長度 樣例輸入 3hrvsh lcxea dphiopd mntflolfbtbpplahqolqykrqdnwdoq 樣例輸出 105...

經典貪心,哈夫曼編碼。

include include include include using namespace std vectorv struct node class op priority queue,op q int dfs node p,int level void destroy node p int ...