Handout No: 09
[Handout berikutnya, sebelumnya, atau kembali ke halaman utama]
Struktur Data Linear
8 Maret 1999
Goal: ADT Stack dan ADT Queue, contoh-contoh masalah,
serta implementasi sequential & berkait
Definisi
Struktur data linear adalah kumpulan komponen-komponen yang tersusun membentuk
satu garis linear. Bila komponen-komponen ditambahkan (atau dikurangi),
maka struktur-struktur tersebut berkembang (atau menyusut).
-
Stack: struktur data linear dimana penambahan atau pengurangan komponen
dilakukan di satu ujung saja.
-
Queue: struktur data linear dimana penambahan komponen dilakukan di satu
ujung, sementara pengurangan dilakukan di ujung lain (yang satu lagi).
Kedua struktur tersebut merupakan struktur data abstraks dimana
implementasi pada tingkat lebih rendah dapat menggunakan struktur sikuensial
(array) atau struktur berkait (linear linked-list).
Manfaat Stack:
-
pengolahan struktur yang "nested" (berisi salinan dirinya sendiri di dalam
dirinya), misalnya pengolahan ekspresi aljabar, himpunan dari himpunan.
-
implementasi algoritma parsing, evaluasi dan backtracking.
-
digunakan OS untuk memungkinkan pemanggilan prosedur secara nested.
-
digunakan untuk memungkinkan konversi program rekursif menjadi non-rekursif.
-
untuk mendukung mekanisme Pushdown Automata (PDA)
-
untuk medukung kompailer mengkonversi infix menjadi postfix dan kemudian
mengevaluasi postfix menjadi atomic (assembly) command
Manfaat Queue
-
digunakan OS untuk mengatur eksekusi task dalam suatu sistem untuk mencapai
perlakuan yang "adil" (seringkali queue disebut waiting line)
-
untuk mailbox dalam komunikasi antar proses
-
untuk buffer dalam mekanisme printspooler, komunikasi data
-
untuk simulasi dan modeling (misalnya simulasi sistem pengendali lalu lintas
udara) dalam memprediksi performance
Spesifikasi ADT Stack
-
Membuat dan menginisialisasi stack S
-
Pemeriksaan boolean yang benar jika stack S kosong
-
Menaruh item X paling atas dalam stack S
-
Mengambil item paling atas dari stack S dan merefernya oleh X
-
Mendapatkan salinan dari item teratas dari stack S dan merefernya oleh
X
Spesifikasi ADT Queue
-
Membuat dan menginisialisasi queue Q
-
Pemeriksaan boolean yang benar jika queue S kosong
-
Menaruh item X di belakang queue Q
-
Mengambil item paling depan dari queue Q dan merefernya oleh X
Implementasi ADT Stack
Spesifikasi stack tsb dapat diimplementasikan di level yang lebih rendah
baik dengan array ataupun linear linked-list.
Selain obyek array itu sendiri, dalam implementasi array diperlukan
suatu variabel yang menunjukkan jumlah sel dalam array yang telah terisi.
Variabel ini (kita namakan count)
diinisialisasi 0 dan akan bertambah setiap metoda
push()
dijalankan, dan akan berkurang satu setiap metoda
pop() dijalankan. Variable
count ini juga menunjukkan
sel mana dalam array yang akan diisi berikutnya. Untuk memungkinkan
array bersifat unbounded (tak berbatas) maka perlu ditambahkan suatu
mekanisme untuk memperbesar kapasitas Stack saat
count mencapai panjang array
saat itu. Perbesaran kapasitas stack dilakukan dengan men-create array
yang lebih panjang dari yang sekarang, mengcopy isi array yang sekarang
ke yang baru lalu yang baru menggantikan yang lama.
Dalam implementasi linear linked-list, operasi
push()
dan pop()
adalah operasi penyisipan dan penghapusan di awal linked-list.
Untuk mengetahui dengan
cepat jumlah item yang tersimpan dalam stack maka variabel
count
dapat pula digunakan disini.
Coding implementasi selengkapnya:
Implementasi ADT Queue
Seperti halnya stack spesifikasi queue tsb dapat diimplementasikan di level
yang lebih rendah baik dengan array ataupun linear linked list.
Dalam implementasi array, konsep circular-array dapat diaplikasikan
untuk menghindari operasi penggeseran isi array saat dilakukan
pop(). Dalam konsep circular
array, inkrementasi indeks array yang panjangnya n, selalu di modulo dengan panjang
array tsb. sehingga variabel indeks yang semula berharga n-1 jika
diinkremen akan "wrap-around" ke 0. Untuk mengetahui posisi ujung-ujung
dari item data yang disimpan dalam array, digunakan variabel indeks
front
(menunjuk ke posisi item yang akan diambil berikutnya) dan
rear
(posisi elemen array berikutnya yang akan ditempati). Suatu variabel
count
digunakan untuk mengetahui kasus khusus: apakah queue kosong atau penuh.
Jika penuh maka mekanisme memperbesar kapasitas queue dapat diaplikasikan
(lihat penjelasan Stack di atas).
Dalam implementasi linera linked-list, maka bagian muka dari queue
adalah awal dari list (di-pop dengan delete-first) dan bagian belakang
adalah akhir dari list (di-push dengan insert-last). Mengingat operasi
insert-last sering dilakukan maka digunakan dua variabel referensi
yang digunakan sebagai pointer:
front
untuk node pertama dari list dan
rear
utuk node paling akhir.
Coding implementasi selengkapnya:
Contoh penggunaan Stack: memeriksa keseimbangan tanda kurung dalam ekspresi
aljabar
Dalam metematika penulisan ekpresi aljabar bisa menggunakan tanda-tanda
kurung untuk memungkinkan struktur yang nested. Suatu substruktur di batasi
oleh pasangan tanda kurung "(" dengan ")", atau "{" dengan "}", atau "["
dengan "]". Kesalahan penulisan ekspresi terjadi jika pasangan tanda tersebut
tidak cocok atau salah satu dari pasangan tidak ada.
Pemeriksaan dilakukan dengan menyimpan kurung buka hingga muncul kurung
buka pasangannya. Karena suatu substruktur selalu berada di dalam suprastrukturnya
sehingga
-
kurung buka substruktur akan muncul setelah kurung buka suprastrukturnya,
dan
-
kurung tutup substruktur akan muncul sebelum kurung tutup suprastrukturnya
Maka, stack digunakan untuk menyimpan kurung buka suatu struktur hingga
diperoleh pasangan kurung tutupnya.
Untuk selengkapnya lihat source code
class program utamanya nya yang menggunakan class
yang melakukan proses tersebut.
Contoh: Interpreter Postfix
Contoh lain penggunaan stack adalah pemeriksaan dan eksekusi ekpresi postfix.
Ekspresi postfix merupakan ekpresi dengan aturan L R B dengan L adalah
operand kiri, R operand kanan dan B adalah operatornya. Ekspresi yang kita
biasa gunakan sehari-hari adalah ekspresi infix dengan aturan L B R. Contoh,
jika ekspresi infixnya "6*7-2" maka ekspresi postfixnya adalah "6 7 * 2
-".
Ekspresi postfix ini memiliki kelebihan, yaitu menyimpan urutan eksekusi
secara nested sementara pada ekspresi infix urutan eksekusi ini dinyatakan
dengan bantuan tanda kurung serta adanya tingkatan/orde dari operand. Kenyataan
ini menjadikan ekspresi postfix digunakan oleh compiler sebagai representasi
ekspresi aljabar sebelum diterjemahkan ke dalam unit-unit perintah level
bawah. Jadi biasanya copiler melakukan konversi dari infix ke postfix dan
kemudian ke assembler (atau langsung ke bahasa mesin).
Karena strukturnya "nested" maka stack digunakan untuk menyimpan operand
L dan R dan mengambilnya kembali saat ketemu operator B, mengeksekusinya
kemudian hasilnya (karena juga bisa merupakan operand pada supra strukturnya)
dikembalikan ke stack untuk memeriksa relasi postfix berikutnya.
Berikut ini adalah program code-nya.
Contoh: Program membaca & menulis pencetakan isi buffer
Buffer adalah queue yang akan menerima setiap apa yang "dituliskan" ke
bagian paling belakang dari queue sementara jika "dibaca" maka item yang
paling depan yang diambil.
void writeLineToBePrinted()
{ // the CPU's task
if ( (there is a line L to print) &&
(the print buffer is neither full nor busy) ) {
printBufferQueue.insert(L);
}
}
void readLineToBePrinted() { // the Printer's task
if (the print buffer is neither empty nor busy) {
L = printBufferQueue.remove();
(print line L on the Printer);
}
}
Bagaimana OS menangani pemanggilan rekursif
Berikut ini adalah suatu metoda rekursif.
double factorial( int
n) {
if (n <= 1) {
return 1.0;
} else {
return n * factorial( n - 1 );
}
}
Jika perintah factorial(3) hendak dieksekusi maka apa yang terjadi?
Keyword untuk diingat:
Handout berikutnya, sebelumnya, atau kembali ke halaman utama