Huffman-kódolás
Kiejtés
- IPA: [ ˈhufmɒŋkoːdolaːʃ]
Főnév
A Huffman-kódolás egy veszteségmentes adatkompressziós technika, amelyet David A. Huffman fejlesztett ki. A módszer az egyes szimbólumok előfordulási gyakoriságán alapuló bináris kódokat rendel az adatokhoz, a gyakoribb szimbólumok rövidebb kódot kapnak, míg a ritkább szimbólumok hosszabbat.
Elméleti leírás
A Huffman-kódolás alapvető lépései: 1. Gyakoriság meghatározása: Határozzuk meg minden szimbólum gyakoriságát az adott adatfolyamban. 2. Prioritási sorrend: Készítsünk egy prioritási sort a szimbólumok gyakoriságának megfelelően (általában egy prioritási sor vagy verem formájában). 3. Faépítés: - Minden szimbólumot egy levélcsomópontként kezelünk. - A két legkisebb gyakoriságú csomópontot összevonjuk, és új belső csomópontot hozunk létre, amelynek a súlya az összevont csomópontok súlyainak összege. - Addig ismételjük az összevonást, amíg egyetlen gyökércsomópont nem marad. 4. Kód hozzárendelése: A létrejött fán keresztül minden szimbólumhoz hozzárendeljük a bináris kódját: - Balra haladva 0
, jobbra haladva 1
. 5. Kódolt adat előállítása: Az eredeti adatot az így generált bináris kódokkal helyettesítjük.
Példa
Tegyük fel, hogy a következő karaktereket szeretnénk kódolni a megadott gyakorisággal: - a: 5
, b: 9
, c: 12
, d: 13
, e: 16
, f: 45
Faépítés lépései:
- Kezdeti sorrend:
a(5)
,b(9)
,c(12)
,d(13)
,e(16)
,f(45)
- Összevonjuk
a(5)
ésb(9)
csomópontokat:ab(14)
- Sorrend:
c(12)
,d(13)
,ab(14)
,e(16)
,f(45)
- Összevonjuk
c(12)
ésd(13)
:cd(25)
- Sorrend:
ab(14)
,e(16)
,cd(25)
,f(45)
- Összevonjuk
ab(14)
ése(16)
:abe(30)
- Sorrend:
cd(25)
,abe(30)
,f(45)
- Összevonjuk
cd(25)
ésabe(30)
:cdeab(55)
- Összevonjuk
cdeab(55)
ésf(45)
:gyökér(100)
Bináris kód hozzárendelése:
A fa bejárása után az alábbi kódokat kapjuk: - f: 0
- c: 100
- d: 101
- a: 1100
- b: 1101
- e: 111
Pszeudokód
függvény HuffmanKodolás(szimbólumok, gyakoriságok): Hozz létre egy prioritási sort, ahol minden szimbólum egy levélcsomópont a gyakoriságával. amíg egynél több csomópont van a prioritási sorban: Vedd ki a két legkisebb gyakoriságú csomópontot. Hozz létre egy új belső csomópontot ezekkel a csomópontokkal gyerekként, az új csomópont gyakorisága legyen a két csomópont gyakoriságának összege. Tedd be az új csomópontot a prioritási sorba. Az utolsó megmaradt csomópont lesz a Huffman-fa gyökere. Járd be a fát, hogy bináris kódokat rendelj minden szimbólumhoz.
Python implementáció
import heapq
class Node:
def __init__(self, char, freq):
self.char = char
self.freq = freq
self.left = None
self.right = None
def __lt__(self, other):
return self.freq < other.freq
def huffman_coding(char_freq):
heap = [Node(char, freq) for char, freq in char_freq.items()]
heapq.heapify(heap)
while len(heap) > 1:
left = heapq.heappop(heap)
right = heapq.heappop(heap)
merged = Node(None, left.freq + right.freq)
merged.left = left
merged.right = right
heapq.heappush(heap, merged)
root = heap[0]
codes = {}
generate_codes(root, "", codes)
return codes
def generate_codes(node, current_code, codes):
if node is None:
return
if node.char is not None:
codes[node.char] = current_code
return
generate_codes(node.left, current_code + "0", codes)
generate_codes(node.right, current_code + "1", codes)
# Példa használat
char_freq = {'a': 5, 'b': 9, 'c': 12, 'd': 13, 'e': 16, 'f': 45}
codes = huffman_coding(char_freq)
print("Huffman-kódok:", codes)
C++ implementáció
#include <iostream>
#include <queue>
#include <unordered_map>
#include <string>
using namespace std;
struct Node {
char ch;
int freq;
Node *left, *right;
Node(char ch, int freq) : ch(ch), freq(freq), left(nullptr), right(nullptr) {}
};
struct Compare {
bool operator()(Node* l, Node* r) {
return l->freq > r->freq;
}
};
void generateCodes(Node* root, string code, unordered_map<char, string>& codes) {
if (!root)
return;
if (root->ch != '\0')
codes[root->ch] = code;
generateCodes(root->left, code + "0", codes);
generateCodes(root->right, code + "1", codes);
}
unordered_map<char, string> huffmanCoding(const unordered_map<char, int>& charFreq) {
priority_queue<Node*, vector<Node*>, Compare> pq;
for (auto& pair : charFreq) {
pq.push(new Node(pair.first, pair.second));
}
while (pq.size() > 1) {
Node* left = pq.top(); pq.pop();
Node* right = pq.top(); pq.pop();
Node* merged = new Node('\0', left->freq + right->freq);
merged->left = left;
merged->right = right;
pq.push(merged);
}
Node* root = pq.top();
unordered_map<char, string> codes;
generateCodes(root, "", codes);
return codes;
}
int main() {
unordered_map<char, int> charFreq = {{'a', 5}, {'b', 9}, {'c', 12}, {'d', 13}, {'e', 16}, {'f', 45}};
unordered_map<char, string> codes = huffmanCoding(charFreq);
cout << "Huffman-kódok:" << endl;
for (auto& pair : codes) {
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}
Összegzés
A Huffman-kódolás hatékony módszer az adatok tömörítésére, különösen szövegfájlok esetén, ahol egyes karakterek gyakrabban fordulnak elő, mint mások. Az algoritmus garantáltan optimális, ha az előfordulási gyakoriságok ismertek.
Fordítások
- Huffman-kódolás - Értelmező szótár (MEK)
- Huffman-kódolás - Etimológiai szótár (UMIL)
- Huffman-kódolás - Szótár.net (hu-hu)
- Huffman-kódolás - DeepL (hu-de)
- Huffman-kódolás - Яндекс (hu-ru)
- Huffman-kódolás - Google (hu-en)
- Huffman-kódolás - Helyesírási szótár (MTA)
- Huffman-kódolás - Wikidata
- Huffman-kódolás - Wikipédia (magyar)