การเข้ารหัส Huffman เป็นอัลกอริธึมการบีบอัดข้อมูลแบบไม่สูญเสียข้อมูล ในอัลกอริธึมนี้ โค้ดความยาวผันแปรถูกกำหนดให้ป้อนอักขระต่างๆ ความยาวของโค้ดสัมพันธ์กับความถี่ในการใช้อักขระ อักขระที่ใช้บ่อยส่วนใหญ่มีรหัสที่เล็กที่สุด และรหัสที่ยาวกว่าสำหรับอักขระที่ใช้บ่อยน้อยที่สุด
ส่วนใหญ่มีสองส่วน อันแรกให้สร้าง Huffman tree และอีกอันให้สำรวจต้นไม้เพื่อค้นหารหัส
ตัวอย่างเช่น ลองพิจารณาสตริงบางสตริง "YYYZXXYYX" ความถี่ของอักขระ Y มากกว่า X และอักขระ Z มีความถี่น้อยที่สุด ดังนั้นความยาวของโค้ดสำหรับ Y จะน้อยกว่า X และโค้ดสำหรับ X จะเล็กกว่า Z
-
ความซับซ้อนในการกำหนดรหัสสำหรับอักขระแต่ละตัวตามความถี่คือ O(n log n)
ป้อนข้อมูล − สตริงที่มีอักขระต่างกัน พูดว่า “ACCEBFFFFAAXXBLKE”
ผลผลิต − รหัสสำหรับอักขระต่างๆ:
Data: K, Frequency: 1, Code: 0000 Data: L, Frequency: 1, Code: 0001 Data: E, Frequency: 2, Code: 001 Data: F, Frequency: 4, Code: 01 Data: B, Frequency: 2, Code: 100 Data: C, Frequency: 2, Code: 101 Data: X, Frequency: 2, Code: 110 Data: A, Frequency: 3, Code: 111
อัลกอริทึม
huffmanCoding(สตริง)
ป้อนข้อมูล − สตริงที่มีอักขระต่างกัน
ผลผลิต − รหัสสำหรับอักขระแต่ละตัว
Begin define a node with character, frequency, left and right child of the node for Huffman tree. create a list ‘freq’ to store frequency of each character, initially all are 0 for each character c in the string do increase the frequency for character ch in freq list. done for all type of character ch do if the frequency of ch is non zero then add ch and its frequency as a node of priority queue Q. done while Q is not empty do remove item from Q and assign it to left child of node remove item from Q and assign to the right child of node traverse the node to find the assigned code done End
traverseNode(n:โหนด รหัส)
ป้อนข้อมูล − โหนด n ของ Huffman tree และรหัสที่ได้รับจากการเรียกครั้งก่อน
ผลผลิต − รหัสที่กำหนดให้กับตัวละครแต่ละตัว
if left child of node n ≠ φ then traverseNode(leftChild(n), code+’0’) //traverse through the left child traverseNode(rightChild(n), code+’1’) //traverse through the right child else display the character and data of current node.
ตัวอย่าง
#include<iostream> #include<queue> #include<string> using namespace std; struct node{ int freq; char data; const node *child0, *child1; node(char d, int f = -1){ //assign values in the node data = d; freq = f; child0 = NULL; child1 = NULL; } node(const node *c0, const node *c1){ data = 0; freq = c0->freq + c1->freq; child0=c0; child1=c1; } bool operator<( const node &a ) const { //< operator performs to find priority in queue return freq >a.freq; } void traverse(string code = "")const{ if(child0!=NULL){ child0->traverse(code+'0'); //add 0 with the code as left child child1->traverse(code+'1'); //add 1 with the code as right child }else{ cout << "Data: " << data<< ", Frequency: "<<freq << ", Code: " << code<<endl; } } }; void huffmanCoding(string str){ priority_queue<node> qu; int frequency[256]; for(int i = 0; i<256; i++) frequency[i] = 0; //clear all frequency for(int i = 0; i<str.size(); i++){ frequency[int(str[i])]++; //increase frequency } for(int i = 0; i<256; i++){ if(frequency[i]){ qu.push(node(i, frequency[i])); } } while(qu.size() >1){ node *c0 = new node(qu.top()); //get left child and remove from queue qu.pop(); node *c1 = new node(qu.top()); //get right child and remove from queue qu.pop(); qu.push(node(c0, c1)); //add freq of two child and add again in the queue } cout << "The Huffman Code: "<<endl; qu.top().traverse(); //traverse the tree to get code } main(){ string str = "ACCEBFFFFAAXXBLKE"; //arbitray string to get frequency huffmanCoding(str); }
ผลลัพธ์
The Huffman Code: Data: K, Frequency: 1, Code: 0000 Data: L, Frequency: 1, Code: 0001 Data: E, Frequency: 2, Code: 001 Data: F, Frequency: 4, Code: 01 Data: B, Frequency: 2, Code: 100 Data: C, Frequency: 2, Code: 101 Data: X, Frequency: 2, Code: 110 Data: A, Frequency: 3, Code: 111