簡單快速的哈夫曼編碼

來源:互聯網
上載者:User

介紹 本文描述在網上能夠找到的最簡單,最快速的哈夫曼編碼。本方法不使用任何擴充動態庫,比如STL或者組件。只使用簡單的C函數,比如:memset,memmove,qsort,malloc,realloc和memcpy。 因此,大家都會發現,理解甚至修改這個編碼都是很容易的。 下載 (21.43 KB) 2010-7-10 22:04 背景 哈夫曼壓縮是個無損的壓縮演算法,一般用來壓縮文本和程式檔案。哈夫曼壓縮屬於可變代碼長度演算法一族。意思是個體符號(例如,文字檔中的字元)用一個特定長度的位序列替代。因此,在檔案中出現頻率高的符號,使用短的位序列,而那些很少出現的符號,則用較長的位序列。 編碼使用 我用簡單的C函數寫這個編碼是為了讓它在任何地方使用都會比較方便。你可以將他們放到類中,或者直接使用這個函數。並且我使用了簡單的格式,僅僅輸入輸出緩衝區,而不象其它文章中那樣,輸入輸出檔案。bool CompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen); bool DecompressHuffman(BYTE *pSrc, int nSrcLen, BYTE *&pDes, int &nDesLen); 複製代碼要點說明 速度 為了讓它(huffman.cpp)快速運行,我花了很長時間。同時,我沒有使用任何動態庫,比如STL或者MFC。它壓縮1M資料少於100ms(P3處理器,主頻1G)。 壓縮 壓縮代碼非常簡單,首先用ASCII值初始化511個哈夫曼節點:CHuffmanNode nodes[511]; for(int nCount = 0; nCount < 256; nCount++) nodes[nCount].byAscii = nCount; 複製代碼然後,計算在輸入緩衝區資料中,每個ASCII碼出現的頻率:for(nCount = 0; nCount < nSrcLen; nCount++) nodes[pSrc[nCount]].nFrequency++; 複製代碼然後,根據頻率進行排序: qsort(nodes, 256, sizeof(CHuffmanNode), frequencyCompare); 現在,構造哈夫曼樹,擷取每個ASCII碼對應的位序列: int nNodeCount = GetHuffmanTree(nodes); 構造哈夫曼樹非常簡單,將所有的節點放到一個隊列中,用一個節點替換兩個頻率最低的節點,新節點的頻率就是這兩個節點的頻率之和。這樣,新節點就是兩個被替換節點的父節點了。如此迴圈,直到隊列中只剩一個節點(樹根)。 // parent nodepNode = &nodes[nParentNode++]; // pop first child pNode->pLeft = PopNode(pNodes, nBackNode--, false); // pop second child pNode->pRight = PopNode(pNodes, nBackNode--, true); // adjust parent of the two poped nodes pNode->pLeft->pParent = pNode->pRight->pParent = pNode; // adjust parent frequency pNode->nFrequency = pNode->pLeft->nFrequency + pNode->pRight->nFrequency; 複製代碼這裡我用了一個好的訣竅來避免使用任何隊列組件。我先前就直到ASCII碼只有256個,但我分配了511個(CHuffmanNode nodes[511]),前255個記錄ASCII碼,而用後255個記錄哈夫曼樹中的父節點。並且在構造樹的時候只使用一個指標數組(ChuffmanNode *pNodes[256])來指向這些節點。同樣使用兩個變數來操作隊列索引(int nParentNode = nNodeCount;nBackNode = nNodeCount –1)。 接著,壓縮的最後一步是將每個ASCII編碼寫入輸出緩衝區中: int nDesIndex = 0;// loop to write codes for(nCount = 0; nCount < nSrcLen; nCount++) { *(DWORD*)(pDesPtr+(nDesIndex>>3)) |= nodes[pSrc[nCount]].dwCode << (nDesIndex&7); nDesIndex += nodes[pSrc[nCount]].nCodeLength; } 複製代碼(nDesIndex>>3): >>3 以8位為界限右移後到達右邊位元組的前面 (nDesIndex&7): &7 得到最高位. 注意:在壓縮緩衝區中,我們必須儲存哈夫曼樹的節點以及位序列,這樣我們才能在解壓縮時重新構造哈夫曼樹(只需儲存ASCII值和對應的位序列)。 解壓縮 解壓縮比構造哈夫曼樹要簡單的多,將輸入緩衝區中的每個編碼用對應的ASCII碼逐個替換就可以了。只要記住,這裡的輸入緩衝區是一個包含每個ASCII值的編碼的位流。因此,為了用ASCII值替換編碼,我們必須用位流搜尋哈夫曼樹,直到發現一個分葉節點,然後將它的ASCII值添加到輸出緩衝區中:int nDesIndex = 0; DWORD nCode; while(nDesIndex < nDesLen) { nCode = (*(DWORD*)(pSrc+(nSrcIndex>>3)))>>(nSrcIndex&7); pNode = pRoot; while(pNode->pLeft) { pNode = (nCode&1) ? pNode->pRight : pNode->pLeft; nCode >>= 1; nSrcIndex++; } pDes[nDesIndex++] = pNode->byAscii; } (nDesIndex>>3): >>3 以8位為界限右移後到達右邊位元組的前面 (nDesIndex&7): &7 得到最高位. 複製代碼源檔案: Huffman.cpp Huffman.h 請見本文提供的原始碼壓縮包。

 

轉載自http://www.topnetsecurity.com/viewthread.php?tid=124&extra=page%3D1

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.