1 概述
Huffman壓縮算法是一種基于字符出現頻率的編碼算法,通過構建Huffman樹,將出現頻率高的字符用短編碼表示,出現頻率低的字符用長編碼表示,從而實現對數據的壓縮。以下是Huffman壓縮算法的詳細流程:
統計字符頻率:遍歷待壓縮的數據,統計每個字符出現的頻率。
構建優先隊列:將每個字符及其頻率作為一個結點放入優先隊列(或最小堆)中,根據字符頻率構建一個按頻率大小排序的優先隊列。
構建Huffman樹:不斷地從優先隊列中取出頻率最小的兩個結點,合并為一個新結點,并將新結點重新插入到優先隊列中,直到隊列只剩下一個結點,即Huffman樹的根結點。
生成Huffman編碼:通過遍歷Huffman樹,從根結點到每個葉子結點的路徑上的左右分支分別對應編碼0和1,根據路徑生成每個字符的Huffman編碼。
壓縮數據:根據生成的Huffman編碼,將待壓縮數據中的每個字符替換為對應的Huffman編碼,得到壓縮后的數據。
存儲壓縮表:將字符與對應的Huffman編碼關系存儲為壓縮表,以便解壓縮時使用。
存儲壓縮數據:將壓縮后的數據以二進制形式存儲。
在解壓縮時,需要根據存儲的Huffman編碼表和壓縮數據,使用相同的Huffman樹結構進行解碼,將壓縮數據解壓縮成原始數據,并輸出原始數據。
Huffman壓縮算法的優勢在于可以根據數據的特征自適應地確定編碼,使得出現頻率高的字符擁有更短的編碼,從而實現高效的數據壓縮。然而,Huffman算法對于小規模數據壓縮效果不佳,適用于處理較大規模的數據壓縮。
2 huffman壓縮算法過程詳細演示
下面將通過一個簡單的例子來演示Huffman壓縮算法的壓縮過程,假設有一個字符串 “ABRACADABRA” 需要進行壓縮。
統計字符頻率:
A: 5 次
B: 2 次
R: 2 次
C: 1 次
D: 1 次
2) 構建優先隊列:
構建一個優先隊列,按照字符頻率排序:
(C, 1), (D, 1), (B, 2), (R, 2), (A, 5)
3) 構建Huffman樹:
不斷地從優先隊列中取出頻率最小的兩個結點,合并為一個新節點,并重新插入隊列中,直到隊列只剩下一個節點,作為Huffman樹的根節點。
合并過程:
(C, 1)和(D, 1) -> (CD, 2)
(B, 2)和(R, 2) -> (BR, 4)
((CD, 2) 和 (BR, 4)) -> ((CD)BR, 6)
((A, 5) 和 ((CD)BR, 6)) -> (((CD)BR)A, 11)
最終得到的Huffman樹如下:
(((CD)BR)A)
/
(CD)BR A
/
CD BR
/ /
C D B R
生成Huffman編碼:
從根節點開始,左分支為0,右分支為1,生成每個字符的Huffman編碼:
A: 0
B: 101
R: 100
C: 1100
D: 1101
6) 壓縮數據:
將原始數據字符串 “ABRACADABRA” 中的每個字符使用對應的Huffman編碼替換,得到壓縮后的數據。
原始數據:ABRACADABRA
Huffman編碼:010110011001011010001011110
壓縮后數據:010110011001011010001011110
在實際壓縮過程中,還需要將Huffman編碼表(字符與編碼的映射關系)一并存儲,以便在解壓縮時使用。通過上述過程,原始數據被成功壓縮,并且根據Huffman編碼,高頻字符編碼較短,低頻字符編碼較長,實現了數據的有效壓縮。
3 c語言Huffman壓縮代碼示例
以下是一個簡單的C語言示例代碼,實現了Huffman算法進行數據壓縮和解壓縮的功能:
#include#include #include #define MAX_TREE_HT 100 // 結點結構體 typedef struct MinHeapNode { char data; unsigned freq; struct MinHeapNode *left, *right; } MinHeapNode; // 最小堆結構體 typedef struct MinHeap { unsigned size; unsigned capacity; MinHeapNode **array; } MinHeap; // 創建新結點 MinHeapNode* newNode(char data, unsigned freq) { MinHeapNode* node = (MinHeapNode*)malloc(sizeof(MinHeapNode)); node->left = node->right = NULL; node->data = data; node->freq = freq; return node; } // 創建最小堆 MinHeap* createMinHeap(unsigned capacity) { MinHeap* minHeap = (MinHeap*)malloc(sizeof(MinHeap)); minHeap->size = 0; minHeap->capacity = capacity; minHeap->array = (MinHeapNode**)malloc(minHeap->capacity * sizeof(MinHeapNode*)); return minHeap; } // 交換兩個結點 void swapMinHeapNodes(MinHeapNode** a, MinHeapNode** b) { MinHeapNode* t = *a; *a = *b; *b = t; } // 最小堆調整 void minHeapify(MinHeap* minHeap, int idx) { int smallest = idx; int left = 2 * idx + 1; int right = 2 * idx + 2; if (left < minHeap->size && minHeap->array[left]->freq < minHeap->array[smallest]->freq) smallest = left; if (right < minHeap->size && minHeap->array[right]->freq < minHeap->array[smallest]->freq) smallest = right; if (smallest != idx) { swapMinHeapNodes(&minHeap->array[smallest], &minHeap->array[idx]); minHeapify(minHeap, smallest); } } // 獲取最小結點 MinHeapNode* extractMin(MinHeap* minHeap) { MinHeapNode* temp = minHeap->array[0]; minHeap->array[0] = minHeap->array[minHeap->size - 1]; --minHeap->size; minHeapify(minHeap, 0); return temp; } // 插入結點 void insertMinHeap(MinHeap* minHeap, MinHeapNode* minHeapNode) { ++minHeap->size; int i = minHeap->size - 1; while (i && minHeapNode->freq < minHeap->array[(i - 1) / 2]->freq) { minHeap->array[i] = minHeap->array[(i - 1) / 2]; i = (i - 1) / 2; } minHeap->array[i] = minHeapNode; } // 創建和構建最小堆 MinHeap* buildMinHeap(char data[], int freq[], int size) { MinHeap* minHeap = createMinHeap(size); for (int i = 0; i < size; ++i) minHeap->array[i] = newNode(data[i], freq[i]); minHeap->size = size; for (int i = size / 2 - 1; i >= 0; --i) minHeapify(minHeap, i); return minHeap; } // 檢查結點是否是葉子結點 int isLeaf(MinHeapNode* root) { return !(root->left) && !(root->right); } // 構建霍夫曼樹 MinHeapNode* buildHuffmanTree(char data[], int freq[], int size) { MinHeapNode *left, *right, *top; MinHeap* minHeap = buildMinHeap(data, freq, size); while (minHeap->size != 1) { left = extractMin(minHeap); right = extractMin(minHeap); top = newNode('$', left->freq + right->freq); top->left = left; top->right = right; insertMinHeap(minHeap, top); } return extractMin(minHeap); } // 打印霍夫曼編碼 void printCodes(MinHeapNode* root, int arr[], int top) { if (root->left) { arr[top] = 0; printCodes(root->left, arr, top + 1); } if (root->right) { arr[top] = 1; printCodes(root->right, arr, top + 1); } if (isLeaf(root)) { printf("%c: ", root->data); for (int i = 0; i < top; ++i) printf("%d", arr[i]); printf(" "); } } // 壓縮數據 void huffmanCompression(char data[]) { int freq[256] = {0}; int n = strlen(data); for (int i = 0; i < n; ++i) ++freq[data[i]]; char arr[256]; int freq2[256]; int size = 0; for (int i = 0; i < 256; ++i) { if (freq[i] != 0) { arr[size] = (char)i; freq2[size] = freq[i]; ++size; } } MinHeapNode* root = buildHuffmanTree(arr, freq2, size); int arr2[MAX_TREE_HT], top = 0; printCodes(root, arr2, top); } int main() { char data[] = "hello world"; huffmanCompression(data); return 0; }
這個示例代碼演示了使用Huffman算法對輸入的數據進行壓縮,并打印出各個字符的Huffman編碼。huffmanCompression 函數首先統計輸入數據中每個字符的出現頻率,并構建Huffman樹,然后通過遞歸遍歷Huffman樹獲取每個字符的Huffman編碼并打印出來。在 main 函數中,我們對一個簡單的字符串進行了壓縮,并輸出了每個字符的Huffman編碼。
需要注意的是,這個示例代碼僅演示了Huffman算法的基本壓縮原理,實際應用中可能需要對數據內容、編碼方式等進行更多處理和優化。
4 C語言Huffman解壓縮算法示例
以下是一個簡單的C語言示例代碼,實現了Huffman算法進行數據解壓縮的功能:
#include#include #include // 結點結構體 typedef struct MinHeapNode { char data; struct MinHeapNode *left, *right; } MinHeapNode; // 解壓縮數據 void huffmanDecompression(char data[], MinHeapNode* root) { int n = strlen(data); MinHeapNode* current = root; for (int i = 0; i < n; ++i) { if (data[i] == '0') { current = current->left; } else { current = current->right; } if (current->left == NULL && current->right == NULL) { printf("%c", current->data); current = root; } } } int main() { // 構造Huffman樹 MinHeapNode *root = (MinHeapNode*)malloc(sizeof(MinHeapNode)); root->left = root->right = NULL; MinHeapNode *A = (MinHeapNode*)malloc(sizeof(MinHeapNode)); A->data = 'A'; A->left = A->right = NULL; MinHeapNode *B = (MinHeapNode*)malloc(sizeof(MinHeapNode)); B->data = 'B'; B->left = B->right = NULL; MinHeapNode *C = (MinHeapNode*)malloc(sizeof(MinHeapNode)); C->data = 'C'; C->left = C->right = NULL; root->left = A; root->right = B; A->left = C; A->right = NULL; B->left = B->right = NULL; C->left = C->right = NULL; // 待解壓縮的數據 char data[] = "00100110001"; // 解壓縮數據 huffmanDecompression(data, root); return 0; }
在這個簡單的示例代碼中,我們首先構建了一個簡單的Huffman樹,然后定義了一個待解壓縮的數據字符串。huffmanDecompression 函數接受壓縮后的數據和Huffman樹的根結點作為參數,通過逐位解析壓縮后的數據,按照Huffman樹逐步走到葉子結點,從而解壓縮出原始數據并打印。
在 main 函數中,我們構造了一個簡單的Huffman樹,并指定了一個簡單的待解壓縮的數據字符串,然后調用 huffmanDecompression 函數進行解壓縮操作。解壓縮過程中,輸出的字符序列應該是根據Huffman樹進行解碼后的原始數據。
需要注意的是,這個示例代碼中的Huffman樹和待解壓縮的數據都是固定的,實際應用中可能需要根據具體的壓縮數據和Huffman樹結構進行相應的解壓縮處理。
-
算法
+關注
關注
23文章
4607瀏覽量
92837 -
C語言
+關注
關注
180文章
7604瀏覽量
136692 -
函數
+關注
關注
3文章
4327瀏覽量
62571 -
Huffman
+關注
關注
0文章
4瀏覽量
6352
原文標題:Huffman算法壓縮解壓縮(C)
文章出處:【微信號:leezym0317,微信公眾號:FPGA開源工作室】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論