2011-11-20 89 views
1

我目前正在執行一個基於Java的huffman算法的程序,而且我正處於需要將編碼內容輸出到文件的階段。我對如何實現解碼所需的頭文件和eof有點困惑。對於我目前的頭文件,我擁有輸入文件中出現的所有唯一值及其頻率,但在一些文章中,我看到人們用0或1來表示節點,然後是頻率(這有點讓人困惑因爲它沒有說明符號是什麼)。霍夫曼編碼 - 頭文件&EOF

另外,對於EOF,據我瞭解,我將它編碼爲符號,因此它被讀取和解碼,但是我不確定我可以使用它的什麼值,肯定不會出現?我知道它需要1的權重,但不確定如何確保它實際上不在文件中。

+0

什麼文章?你能提供一些鏈接嗎? – svick

+0

我考慮的主要兩個是http://michael.dipperstein.com/huffman/和http://www.cs.duke.edu/csed/poop/huff/info/想到我可以看到的標題爲什麼他們現在這樣做我想(使用頭文件構造一個樹,然後通過讀取文件內容來獲取頻率?目前我的頭文件中有符號和頻率,這是錯誤的)這只是僞代碼我是困惑,因爲我不知道該如何使用它,因爲這不可能代碼可能已經在樹中的符號? – LDM91

回答

2

我必須這樣做一次作業,這是我們使用的方法。

通過使用0和1對樹的結構(而不​​是頻率)進行編碼,對頭進行編碼。表示沿着樹移動的「0」,表示我們在葉節點處的「1」。這導致了對樹進行唯一編碼的一種預先遍歷。

例如,就像一棵樹(((AB)C)(DE))將被編碼爲 「0001 」,其中a,b,C,d,e爲他們的ASCII形式。

這裏的圖形形式的樹:

/\ 
    /\ /\ 
/\ c d e 
a b 

對於我們所使用的文件中的最後3位指定多少所需的最後兩個字節的要讀的EOF。一旦我們讀到最後一個字節(因此我們正在處理第二個最後一個字節),我們檢查了最後3位:它們編碼了多少位讀取,減去6.因此110101xxxxxxx000意思是「讀取110101(6位)並放棄其他所有內容」。 1101011xxxxxx001意味着「讀1101011(7位)和丟棄其他」等

這樣做,這樣意味着我們沒有必須有一個特殊的值表示的EOF,我們仍然可以在讀取文件字節時間(儘管我們實際上需要在我們工作的地方之前閱讀一個字節)。

(對於EOF我沒有看過你的文章,所以我不知道我們的想法與你的方法工作。)

+0

我想我已經開始更好地理解頭文件了,但是您能否再澄清一下這個例子?我不確定我是否正確閱讀樹,是否:根節點,然後是超級節點與另一個超級節點裏面的A + B離開和一個C離開節點(在超級節點內部持有A + B的外部),那麼另一個有D和E的超級節點會離開?如果是這樣,那麼「0001a1b1c」是否表示在你讀完了你假設的下一個假期之後的兩片葉子? – LDM91

+0

我已經添加了一些樹的更直觀的表示,所以我希望有所幫助。你知道你放置樹葉的位置,它總是位於最左邊的位置,所以下一個最左邊的位置就是下一個「位」的操作位置。 000 - >向左下分支,1 - >將a放在當前位置,並移動到下一個最左邊的非葉節點等。 – mange

2

霍夫曼編碼指定如何從一串字符創建哈夫曼樹和那麼如何將它編碼爲一系列位。

它沒有指定你應該如何對樹進行編碼,或者如何確定要讀取多少位。確切的位數是一個問題,因爲您只能將整個字節保存到文件中。所以你需要一些方法來確切地確定在哪一點結束。

對於編碼樹,有幾個選項。其中一個是記錄每個字符的計數並讓解碼器從中重建樹。其他選項是以某種方式直接對樹進行編碼,例如使用0-1方法(我假設您提到的文章)描述。

然後有adaptive Huffman coding它根本不需要樹,但更復雜。

爲了決定何時結束,您可以在文件中寫入字符的總數,然後使用它來決定何時停止。或者,如果您使用字符計數對樹進行編碼,則可以免費獲得此計數。

另一種選擇是使用EOF字符。這是霍夫曼樹中的一個字符,但不會編碼任何正常值。您可以將其想象爲第257個值,假設您正在編碼字節。 (你可能使用EOF標記的一些正常值,如零字節,但這需要你絕對確定它不會出現在輸入文件中。)

+0

感謝您的回覆我認爲我現在可以做EOF,但是感謝總計數建議(可以不相信我沒有想到它!),如果它沒有。 – LDM91

+0

@svick我知道這個角色必須具有大於256的值,但如果它不是ASCII字符,我會如何將它放入文件中? –

+0

@C_B與其他字符一樣:通過在樹中對其位置進行編碼。 – svick