Algoritma Pemrograman [BS204] [1.3] Bag, Queue, Stack Robert Sedgewick, Kevin Wayne, Algorithms 4 th Ed., Chapter 1, Addison-Wesley Professional, 2011 1
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. 2
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. 3
APIs pada buku Algorithms 4 ed 4
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. Keuntungan generic: Meningkatkan expressiveness power Meningkatkan type safety Mengeksplisitkan parameter type dan mengimplisitkan type casting 5
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 menggunakan template kelas generic 6
Contoh Generic 7
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 8
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) int i = stack.pop(); // auto-unboxing (Integer -> int) 9
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); 10
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). Urutan iterasi tidak ditentukan. 11
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 sama menjaga urutan relatif mereka(item) : item keluar dalam urutan yang sama di mana item ditempatkan. 12
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. Contoh : Tumpukan surat, Session pada browser. 13
Arithmetic Expression Evaluation 14
Implementing collections Untuk mengatasi masalah pelaksanaan Bag, Stack dan Queue, kita mulai dengan implementasi klasik yang sederhana : Fixed - capacity stack Generics Array resizing Loitering Iteration 15
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. Bagian atas tumpukan (jika tidak kosong) adalah pada [N-1]. 16
ADT Fixed-Capacity Stack of String 17
Generics 18
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. Jadi sebaliknya, kita memodifikasi implementasi array dinamis menyesuaikan ukuran array sehingga keduanya cukup besar untuk menampung semua item dan tidak begitu besar untuk membuang memori. 19
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; 20
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; Dengan implementasi ini, tumpukan tidak pernah meluap dan tidak pernah kurang dari 1/4 (kecuali stack kosong, ketika ukuran array 1). 21
Loitering Java Garbage Collector akan mencari objekobjek yang sudah tidak digunakan di memori dan akan menghancurkan objek-objek tersebut agar memori dapat digunakan oleh objek-objek lain yang akan digunakan. 22
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. Class Iterator harus menyertakan dua metode: hasnext() --> mengembalikan nilai boolean next() --> yang mengembalikan item generik dari koleksi. 23
Iteration (II) 24