Pertemuan 6 ASDL – Kompresi (Huffman)

Download Report

Transcript Pertemuan 6 ASDL – Kompresi (Huffman)

Algoritma dan Struktur Data Lanjut
Kompresi merupakan proses pengubahan
sekumpulan data menjadi suatu bentuk kode
untuk
menghemat
kebutuhan
tempat
penyimpanan dan waktu untuk transmisi data.
 Kompresi dapat diterapkan untuk:
- File Teks
- File Gambar
- File Audio
- File Video


Ada 3 metode yang digunakan dalam
kompresi:
- Kompresi Lossy
- Kompresi Lossless
- Kompresi Delta


Suatu metode kompresi data yang menghilangkan
sebagian “Informasi” dari file asli (file yang akan
dimampatkan) selama proses kompresi berlangsung
dengan tidak menghilangkan (secara signifikan) informasi
yang ada dalam file secara keseluruhan.
Contoh: pada kompresi file gambar.
Merubah detail dan warna sebuah file gambar menjadi
lebih sederhana dan mempunyai kapasitas file menjadi
lebih kecil tanpa terlihat perbedaan mencolok dari
pandangan manusia.

Metode kompresi data di mana tidak ada
“Informasi” / data yang hilang atau berkurang
jumlahnya selama proses kompresi, sehingga
pada proses dekompresi jumlah bit (byte) data
atau informasi dalam keseluruhan file hasil sama
persis dengan file aslinya.

Delta Comression mengirimkan semua informasi
state, memungkinkan hanya mengirim
perubahan/update (delta) dari state sebelumnya.
Efeknya, membutuhkan pengiriman data yang
reliable (contoh TCP). Efektif jika state game
world besar, namun perubahan yang ada kecil.




Algoritma Huffman
Algoritma LZW (Lempel-Ziv-Welch)
Algoritma DMC (Dynamic Marcov
Compression)
Dsb


Kompresi Teks menggunakan metode Lossless.
Karena jika menghilangkan beberapa karakter
akan merubah arti dari teks aslinya.
Kompresi Teks ada 2 macam:
 Character-based Frequency counting
▪ Huffman Encoding, Arithmetic Encoding
 Word-based Frequency counting
▪ Lempel-Ziv (LZ) algorithm
Dibuat oleh seorang mahasiswa MIT bernama
David Huffman.
 Merupakan salah satu metode paling lama dan
paling terkenal dalam kompresi teks.
 Metode ini adalah suatu teknik kompresi data
secara statistik yang bekerja dengan mereduksi
panjang kode rata-rata dan menghasilkan kode
prefiks yang digunakan untuk merepresentasikan
simbol-simbol dari suatu jenis huruf.


Algoritma Huffman menggunakan struktur pohon
dalam prosesnya.

Dalam struktur pohon dikenal dengan
terminologi parent (orang tua) dan child (anak).

Parent (orang tua) yaitu sebuah simpul yang
memiliki lintasan ke simpul lain dengan tingkatan
(level) di bawahnya.

Child (anak) yaitu sebuah simpul yang memiliki
lintasan ke simpul lain dengan tingktan (level) di
atasnya.

Beradasarkan jumlah anak pohon huffman
dikategorikan :
 Uner : pohon dengan orang tua yang hanya
memiliki satu anak
 Biner : pohon dengan orang tua yang memiliki
dua anak

Pengkodean dengan huffman coding
menggunakan panjang bit yang bervariasi dalam
pengkodean sebuah karakter.

Karakter dengan frekuensi kemunculan lebih
besar memiliki panjang bit yang lebih pendek.

Berlaku kebalikannya.
1.
Hitung statistik (frekuensi) jumlah kemunculan
masing-masing simbol.
2.
Simpan hasil informasi bobot masing-masing
simbol.
3.
Membangun pohon huffman berdasarkan larik
bobot dari masing-masing simbol.
4.
Konversi pohon huffman menjadi kode spesifik
untuk tiap simbol.
Berikut ini adalah sebuah contoh cara pengkodean
sebuah string. Misalkan kita akan mengkodekan sebuah
string “AABCABC”.
 Dalam kode ASCII string 7 huruf “AABCABC”
membutuhkan representasi 7 × 8 bit = 56 bit (7 byte),
dengan rincian sebagai berikut:








A
A
B
C
A
B
C
= 01000001
= 01000001
= 01000010
= 01000011
= 01000001
= 01000010
= 01000011
Berdasarkan algoritma yang telah disebutkan
sebelumnya, maka kita pertama kali akan
menghitung frekuensi kemunculan dari setiap
karakater.
 String: AABCABC

Simbol
Frekuensi
A
3
B
2
C
2

Berdasarkan tabel maka dapat disusun model
pohon Huffman-nya:

Berdasarkan pohon Huffman yang ditunjukan
pada hasil di atas maka dapat ditentukan kode
huffman untuk masing-masing setiap simbol
yang dalam string “AABCABC”.



Berdasarkan tabel Huffman maka
rangkaian bit dari string AABCABC adalah:
0 0 10 11 0 10 11
Jadi jumlah bit yang dipakai hanya 11 bit (2
byte), lebih hemat dari jumlah bit
sebelumnya (56 bit).
Dari Tabel Huffman tampak bahwa kode untuk
sebuah simbol/karakter tidak boleh menjadi
awalan dari kode simbol yang lain guna
menghindari keraguan (ambiguitas) dalam proses
dekompresi atau decoding.
 Karena tiap kode Huffman yang dihasilkan unik,
maka proses dekompresi dapat dilakukan dengan
mudah.

Saat membaca kode bit pertama dalam
rangkaian bit: 0 0 10 11 0 10 11 yaitu bit 0,
dapat langsung disimpulkan bahwa kode bit “0”
merupakan pemetaan dari simbol “A”. Bit kedua
juga “A”.
Kemudian baca kode bit selanjutnya, yaitu bit
“1”, tidak ada kode Huffman “1”, lalu baca kode
Huffman selanjutnya yaitu “0” sehingga menjadi
“10” yaitu karakter “B”.
Begitu seterusnya…
Hitung frekuensi untuk tiap simbol.
Urutkan dari yang paling kecil ke yang paling besar.
Setiap simbol mewakili satu node.
 Tambahkan kode ‘0’ untuk node terkecil pertama
dan ‘1’ untuk node terkecil kedua. Gabungkan kedua
node tersebut dan jumlahkan kedua frekuensinya.
Maka akan didapat node parent.
 Hapus kedua node terkecil tadi dari dalam list node,
lalu masukkan node parent tadi.
 Ulangi langkah ke-2 sampai ke-4 hingga semua
simbol habis dibangkitkan.



Buatlah kelas-kelas:
 Simbol
 Node
 HuffmanCode
Tambahkan atribut char karakter, int frekuensi,
String biner. Inisialisasi nilai biner dengan string
kosong (“”). Buat setter dan getter-nya.
 Buat 3 konstruktor, 1 konstruktor tanpa parameter,
1 konstruktor dengan parameter char karakter dan
int frekuensi, 1 konstruktor dengan parameter char
karakter, int frekuensi, dan String biner.
 Inisialisasi nilai-nilai parameter dari konstruktor di
dalam konstruktor.

Kelas Node adalah turunan dari kelas Simbol.
Tambahkan 3 atribut Node left, right, dan parent.
Buat setter dan getter-nya.
 Buat 3 konstruktor, 1 konstruktor tanpa parameter,
1 konstruktor dengan parameter Node left dan
right, 1 konstruktor dengan parameter char karakter
dan int frekuensi. Inisialisasi tiap nilai dari
parameter.
 Untuk konstruktor ketiga, inisialisasi nilai kelas
super dengan menggunakan fungsi setter dan
getter dari kelas super tersebut



Didalam fungsi setLeft dan setRight,
tambahkan sintaks berikut:
 left.setParent(this); (untuk setLeft)
 right.setParent(this); (untuk setRight)


Tambahkan fungsi hasChild untuk mengecek
apakah node ini memiliki anak atau tidak.
Tambahkan fungsi hasLeft dan hasRight
untuk mengecek apakah node ini memiliki
anak left atau right.
Tambahkan sebuah atribut static Vector<Simbol> listSimbol ke dalamnya, lalu
inisialisasi variabel tersebut.
 Buat sebuah fungsi static bernama urutSimbol dengan tipe Vector<Node> dan
berparameter Vector<Node> listNode.
 Tambahkan kode berikut ke dalamnya:

for (int i = 0; i < listNode.size() - 1; i++) {
Node s = listNode.get(i);
for (int j = i + 1; j < listNode.size(); j++) {
Node s2 = listNode.get(j);
if (s2.getFrekuensi() > s.getFrekuensi()) {
Node nB;
nB = listNode.get(i);
listNode.set(i, listNode.get(j));
listNode.set(j, nB);
}
}
}
return listNode;

Buat sebuah fungsi static bernama getTopParent dengan tipe Node dan
berparameter Vector<Node> listNode, lalu masukkan:
Node parent = null;
Vector<Node> listBuff = new Vector<Node>();
for (Node node : listNode) {
listBuff.add(node);
}
while (true) {
parent = new Node();
parent.setKarakter('p');
listBuff = urutSimbol(listBuff);
Node n1 = listBuff.get(listBuff.size() - 1);
Node n2 = listBuff.get(listBuff.size() - 2);
parent.setFrekuensi(n1.getFrekuensi() + n2.getFrekuensi());
parent.setLeft(n2);
parent.setRight(n1);
if (listBuff.size() <= 2) {
break;
}
listBuff.removeElementAt(listBuff.size() - 1);
listBuff.removeElementAt(listBuff.size() - 1);
listBuff.add(parent);
}
return parent;

Buat sebuah fungsi static bernama getCode dengan tipe void
dan berparameter Node parent, lalu masukkan:
if (parent.hasLeft()) {
parent.getLeft().setBiner(parent.getBiner() + "0");
getCode(parent.getLeft());
}
if (parent.hasRight()) {
parent.getRight().setBiner(parent.getBiner() + "1");
getCode(parent.getRight());
}
if (!parent.hasChild()) {
listSimbol.add((Simbol) parent);
}

Buat sebuah fungsi main, lalu masukkan:
String txt = "AABCABC";
Vector<Node> listNode = new Vector<Node>(); String buff = txt;
while (buff.length() > 0) {
char c = buff.charAt(0);
int f = 0;
String buff2 = "";
for (int j = 0; j < buff.length(); j++) {
if (c == buff.charAt(j))
f++;
else
buff2 += buff.charAt(j); }
buff = buff2;
listNode.add(new Node(c, f));
}
listNode = urutSimbol(listNode);
Node topParent = getTopParent(listNode);
getCode(topParent);
for (Simbol simbol : listSimbol)
System.out.println(simbol.getKarakter() + "|" +
simbol.getFrekuensi() + "|" + simbol.getBiner());



Buat paper tentang algoritma kompresi:
- Lempel-Ziv-Welch (LZW)
- Dymanic Markov Compression (DMC)
Jelaskan sejarahnya, aturannya, algoritma-nya.
Beri contoh penerapannya:
Misal untuk mengkompresi String/kalimat.
Beri penjelasan langkah per langkah untuk kompresi
dan dekompresi-nya.
Kumpul hardcopy minggu depan saat kuliah.
Dikerjakan maksimal 2 mahasiswa.
Tiap kelompok untuk penerapan-nya harus beda.



Sebutkan 3 jenis metode kompresi!
1 byte berapa bit?
Buatlah tabel Huffman untuk kompresi
string ABACCDA (Kerjakan dengan lengkap
tahap-tahapnya)!
Tulis nama dan NIM.