Algoritma Pemrograman
[BS204]
Tujuan Perkuliahan
Menekankan gagasan cara kita
mewakili objek dalam koleksi yang
efisien untuk berbagai operasi.
Memperkenalkan iterasi generics dan
konstruksi dasar yang substansial
untuk menyederhanakan kode klien.
Memperkenalkan dan menunjukkan
pentingnya struktur data linked. Secara
khusus, struktur data klasik yang
dikenal sebagai linked list
memungkinkan pelaksanaan Bags,
Queue, dan Stack yang efisien.
Items Collection
Kumpulan data-data yang disimpan dalam satu buah
atribut/variabel.
Himpunan nilai-nilai adalah Items Collection, dan
operasi yang mungkin terjadi yaitu: menambah,
menghapus, atau memeriksa item dalam collections.
3 jenis collections : Bags, Queue, Stack. Perbedaan
dari 3 jenis items collection ini adalah spesifikasi
objek yang akan dihapus/diperiksa.
Generics
Karakteristik penting dari ADT Collections adalah harus dapat
digunakan untuk semua jenis data yang dinamakan Generics.
Kelas generic: kelas yang masih “umum”, belum spesifik ketika
didefinisikan
Pada saat deklarasi objek, hal yang umum harus dibuat spesifik–
Setelah dibuat spesifik, baru bisa dipakai
Biasanya yang “umum” adalah “type”-nya, dipakai untuk membungkus
“operasi” yang sama
Kelas generic pada Java diimplementasikan sebagai tipe parameter.
Hasil kompilasi kode kelas generic tetap hanya satu kelas, dengan
type parameter yang diganti dengan type yang seharusnya pada saat
runtime.
Sintaks Generic
Mendefinisikan kelas dan interface:
◦ class NamaKelas <TypeGeneric> { ... }
◦
interface NamaInterface <TypeGeneric> { ... }
◦
class NamaKelas <TypeGeneric1, TypeGeneric2> { ... }
◦
interface NamaInterface <TypeGeneric1, TypeGeneric2> { ... }
Nama untuk type generic sebaiknya menggunakan karakter huruf
besar, misalnya E dan T
Kita dapat mendefinisikan type generic lebih dari Satu
Kelas dapat digunakan untuk membuat kelas baru dengan
Konvensi Penamaan Type
E –Element (digunakan pada Java Collections
Framework)
K –Key
N –Number
T –Type
V –Value
S, U, V, etc. –2nd, 3rd, 4th types
Autoboxing
Otomatis Konversi dari tipe data primitif ke tipe data
Class/Wrapper. (byte : Byte; short : Short; int : Integer; long : Long;
float : Float; double : Double; boolean : Boolean; char : Char)
Secara otomatis konversi tipe primitif ke tipe wrapper dikenal
sebagai autoboxing,
Dan secara otomatis konversi tipe wrapper untuk tipe primitif
dikenal sebagai auto-unboxing.
Stack<Integer> stack = new Stack<Integer>();
stack.push(17); // auto-boxing (int -> Integer)
Iterabel Collections
Untuk banyak aplikasi, kebutuhan klien hanya untuk memproses
setiap item dalam beberapa cara atau iterate melalui item dalam
koleksi.
For-each.
Contoh :
Queue<
Transaction
> collection = new Queue<>();
Cara untuk melakukan akses iterasi ke collection dapat
menggunakan loop dan loop yang baik adalah for-each :
for (
Transaction
t
: collection)
{
StdOut.println(
t
);
}
Bags
Tipe Collection yang tidak mendukung
penghapusan item tujuannya adalah
menyediakan kumpulan items dan
kemudian di-iterate melalui items
collection untuk klien(klien juga dapat
menguji bag empty dan index item di
bag).
FIFO Queues – Antrian First In First Out
Kebijakan melakukan tugas-tugas dalam
urutan yang sama dimana item tiba adalah salah satu yang sering kita jumpai dalam kehidupan sehari-hari : orang-orang yang menunggu dalam antrean di teater, mobil yang menunggu dalam antrean di pintu tol, tugas-tugas yang menunggu untuk dilayani oleh aplikasi pada komputer Anda.
Salah satu prinsip dasar kebijakan layanan
apapun adalah persepsi keadilan.
Ide pertama yang terlintas dalam pikiran
ketika kebanyakan orang berpikir tentang keadilan adalah bahwa siapa pun telah menunggu paling lama harus dilayani pertama.
Alasan khas untuk menggunakan queue
dalam aplikasi adalah untuk menyimpan item dalam koleksi sementara pada saat yang
Pushdown Stacks
Kumpulan item yang didasarkan pada kebijakan
Last-In-First-Out(LIFO).
Item akan dimasukkan ke tumpukan teratas; Item
akan dikeluarkan dari tumpukan yang teratas.
Keuntungan : item yang menarik sesegera
mungkin didapat;
Kegurian : beberapa item lama mungkin tidak
akan pernah diakses jika tidak pernah mengosongkan stack.
Implementing collections
Untuk mengatasi masalah pelaksanaan Bag, Stack
dan Queue, kita mulai dengan implementasi klasik
yang sederhana :
◦
Fixed - capacity stack
◦
Generics
◦
Array resizing
◦
Loitering
Fixed – Capacity Stack
ADT untuk kapasitas tumpukan yang berukuran tetap.
Fixed Stack API pada Algorithms 4ed:
◦
Bekerja hanya untuk nilai-nilai String,
◦
Memerlukan klien untuk menentukan kapasitas,
◦
Tidak mendukung iterasi.
Operasi ini melestarikan sifat sebagai berikut:
◦
Array digunakan untuk menyisipkan item.
◦
Tumpukan kosong ketika N adalah 0.
Array Resizing (1)
Memilih array untuk mewakili isi tumpukan mengharuskan klien
memperkirakan ukuran maksimum tumpukan sebelumnya.
Pada Java, kita tidak bisa mengubah ukuran array setelah diciptakan
kecuali diciptakan kembali, sehingga ukuran stack menjadi fixed.
Semakin besar ukuran stack yang diciptakan maka semakin besar juga
penggunaan memori pada komputer.
Jadi pada saat sebelum push() item ke Stack, sebaiknya client
mengecek kondisi Stack, jika sudah penuh maka item tidak dapat di
push(). Pengecekan penuh atau tidak nya suatu Stack dinamakan
isFull().
Pada buku Algorithms 4ed, kode isFull() dihilangkan, karena
berkeinginan untuk meringankan klien untuk berurusan dengan
konsep tumpukan penuh, sebagaimana yang diuraikan dalam Stack
API yang dimiliki Java.
Array Resizing (II)
Mencapai tujuan menyesuaikan ukuran array sangat mudah, yaitu:
Pertama, menerapkan metode yang move stack ke array dari ukuran
yang berbeda:
private void resize(int max)
{ // Move stack of size N <= max to a new array of size max. Item[] temp = (Item[]) new Object[max];
for (int i = 0; i < N; i++) temp[i] = a[i]; a = temp;
}
Kemudian dalam push(), kita cek apakah array terlalu kecil. Secara
khusus, kita cek apakah ada ruang untuk item baru dalam array dengan
memeriksa apakah ukuran stack N sama dengan ukuran array a.length.
Jika tidak ada ruang, maka ukuran array digandakan. Kemudian kita hanya
memasukkan item baru dengan kode [N++] = item, seperti sebelumnya:
public void push(String item){ // Add item to top of stack.
if (N == a.length) resize(2*a.length); a[N++] = item;
Array Resizing (III)
Kemudian dalam pop(), kita mulai dengan menghapus item,
maka kita membagi dua ukuran array jika terlalu besar.
Apakah ukuran stack kurang dari 1/4 dari ukuran array.
Setelah array dibelah dua maka array menjadi sekitar
setengah penuh dan dapat menampung sejumlah operasi
push() dan pop() sebelum harus mengubah ukuran array lagi.
public String pop()
{ // Remove item from top of stack. String item = a[--N];
a[N] = null; // Avoid loitering (see text).
if (N > 0 && N == a.length/4) resize(a.length/2); return item;
}
Loitering
Java Garbage Collector akan mencari
objek-objek yang sudah tidak digunakan di memori
dan akan menghancurkan objek-objek
tersebut agar memori dapat digunakan oleh
objek-objek lain yang akan digunakan.
Iteration (I)
Salah satu operasi mendasar pada koleksi adalah untuk memproses setiap item
dengan iterasi melalui koleksi menggunakan pernyataan for-each.
Paradigma ini adalah algoritma yang bersih dan kompak serta bebas dari
ketergantungan pada implementasi koleksi.
Contoh :
Stack<String> collection = new Stack<String>(); ...
for (String s : collection) StdOut.println(s); ...
Sekarang, for-each statement diganti dengan Iterator :
Iterator<String> i = collection.iterator(); while (i.hasNext()) { String s = i.next(); StdOut.println(s); }
Kode ini menggambarkan operasi-operasi yang kita butuhkan untuk
mengimplementasi setiap koleksi:
◦ Koleksi harus menerapkan metode iterator() yang mengembalikan sebuah Iterator Object.