Politeknik Elektronika Negeri Surabaya PRAKTIKUM 27-28 BINARY SEARCH TREE A. TUJUAN Mahasiswa diharapkan mampu : 1. Memahami dan mengimplementasaikan Konsep Binary Search Tree 2. Memahami keunggulan dari algoritma Binary Search Tree 3. Mampu mengimplementasikan algoritma Binary Search Tree B. DASAR TEORI Binary search tree adalah salah satu bentuk dari pohon.Di mana masing-masing pohon tersebut hanya memiliki dua buah upapohon, yakni upapohon kiri dan upapohon kanan.Ciri khas yang melekat pada binary search tree ini yang bisa juga dibilang sebagai keunggulan dari binary search tree adalah peletakan isi dari nodenya yang terurut berdasarkan besarnya dari isinya tersebut.Isinya bisa saja berupa integer, karakter, atau apapun sesuai dengan spesifikasi binary search tree yang ada. Operasi dasar dari binary search tree(BST) ini sendiri sangatlah sederhana, yakni hanya fungsi perbandingan dan fungsi rekursif. Di mana anak pohon sebelah kiri node adalah anak pohon yang lebih kecil dari node, sedangkan anak pohon sebelah kanan node memiliki isi yang lebih besar daripada isi node. Biasanya penyimpanan data di dalam binary search tree ini bisa juga berupa record di mana pengurutannya hanya tinggal melihat key dari record tersebut, missal nomor absen, NIM, tanggal, dll. Keunggulan Binary Search a. Search Method Metode search adalah penentu paling dalam program atau bisa dibilang nyawa dari programdatabase. Kenapa search sangat penting untuk efisien.?Bayangkan saja apabila ada miliaran data yang ada di dalam database pada sebuah komputer server dan harus diolah dan selalu harus diupdate setiap hari ataupun diakses pengguna untuk dicari isi data yang diinginkanya. Lalu, yang kita gunakan adalah struktur data yang tidak efisien, di mana suatu saat computer server akan mengalami minimal hang atau yang paling parah adalah server down sehingga tidak bisa diakses dan akhirnya justru membuang waktu bahkan lebih 198 Politeknik Elektronika Negeri Surabaya parahnya bisa menyebabkan data dalam harddisk server menghilang. Tentunya kita sangat menghindari hal semacam itu terjadi bukan. Metode Search sendiri ada banyak, seperti yang sudah sempat disinggung sedikit pada pendahuluan. Bahwa search macamnya ada linear search, binary search, binary search tree, dll. Di sini hanya akan dibahas 3 contoh tersebut. Linear search merupakan tipe search yang paling mendasar dalam dunia search. Pada dasarn linear search ini sangat sederhana.Yakni memulai pencarian dari elemen pertama kemudian bergeser terus ke elemen berikutnya hingga menemukan isi elemen yang dicari. Apabila elemen yang dicari tidak ada, maka linear search akan terus melakukan traversal hingga elemen terakhir. Mari kita bayangkan apabila terdapat banyak sekali data yang harus ditraversal dan data yang dicar itidak ada di dalam database(worst case possibility). Efektivitas dari linear search ini adalah dengan O(n) worst case tergantung dari jumlah elemen yang ada di dalam database tersebut. Metode search yang berikutnya yakni binary search, bedanya binary search dari linear search adalah dengan pembagian jumlah elemen menjadi dua bagian. Sehingga pencarian bisa lebih efektif dengan cara membagi pencarian ke dua arah. Worst case dari binary search ini adalah O(log n) sehingga cara ini bisa dibilang cukup efisien. Metode search yang terakhir adalah binary search tree (sebenarnya bukan merupakan metode search). binary search tree memiliki kompleksitas algoritma O(log n) yang tidak ada bedanya dengan metode binary search. Tetapi seharusnya metode search pada binary search tree bisa lebih singkat, karena jalur yang dipilih sudah tergolong spesifik, sehingga tidak perlu memeriksa semua elemen untuk mencari elemen tertentu. b. Struktur Data Struktur data merupakan keunggulan dari binary search tree jika kita bandingkan dengan array pada umunya.Mengapa hal tersebut bisa dibilang sebagai keunggulan? Karne struktur data dari binary search tree adalah linked list dengan elemennya terurut. Dengan demikian apabila struktur datanya sudah terurut maka pengaksesannya pun jauh lebih mudah.Hal yang diakibatkan dari struktur data tersebut adalah kita tidak perlu melakukan sorting terhadap data yang sudah ada. Berbeda dengan struktur data yang lain, seperti struktur data array, linked list biasa membutuhkan sebuah fungsi sort untuk mengurutkan datanya. Keunggulan lain yang disebabkan struktur data dari pohon ini adalah 199 Politeknik Elektronika Negeri Surabaya kemudahan insertion process. Pada proses pemasukan data padabinary search tree, sangatlah mudah, sama sekali tidak ada pergeseran data. Proses yang terjadi hanyalah pencarian lokasi yang tepat untuk data yang dimasukkan tersebut, kemudian dikaitkan ke data di atasnya sehingga dia menjadi anggota binary search tree yang baru Gambar 1.Binary Tree Kendati demikian, struktur data pada binary search tree menyebabkan proses penghapusan data pada binary search treetergolong cukup rumit. Mengapa rumit? Karena harus ada traversal data untuk mencari node tertentu untuk menggantikan posisi dari node yang telah dihapus(informasi akan diperjelas di dalam Gambar). Selain itu, kelemahan pemasukan data pada binary search tree jika dibandingkan dengan Tabel Eksplisit adalah table eksplisit tidak memerlukan pengulangan untuk penambahan elemen baru, sedangkan binary search tree membutuhkan proses sekuensial untuk menambahkan satu elemen baru. Namun hal tersebut dapat ditutupi dengan sorted element dari binary search tree. Gambar 2.Menghapus Node di Binary Tree 200 Politeknik Elektronika Negeri Surabaya C. TUGAS PENDAHULUAN Buatlah resume 1 halaman mengenai Binary Search Tree dan berikan penjelasannya.! D. PERCOBAAN Node.java 1. 2. 3. 4. 5. 6. class Node { int iData; // data yang digunakan sebagai nilai kunci. Node leftChild; // Simpul rujukan ke anak sebelah kiri. Node rightChild; // Simpul rujukan ke anak sebelah kanan. } BinaryTree.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. class BinaryTree { private Node root; // Membentuk akar (root) BinaryTree public Object find(int key) { Node current = root; // Mulai dari akar (root) while (current.iData != key) // Selama tidak sesuai { if (key < current.iData) // Pergi ke cabang kiri? { current = current.leftChild; } else { current = current.rightChild; // Atau pergi ke cabang kanan. } if (current == null) // Jika tidak memiliki anak. { return null; } } return current; // Data yang dicari ditemukan. } public void insert(int id) { { Node newNode = new Node(); // Membuat Node yang akan disisipkan. newNode.iData = id; // Menyisipkan data. if (root == null) // Jika tidak ada Node di akar (root). { root = newNode; } else { Node current = root; // Mulai dari akar (root). Node parent; while (true) // hadir secara internal. { parent = current; if (id < current.iData) // Pergi ke kiri. { 201 Politeknik Elektronika Negeri Surabaya 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. 91. current = current.leftChild; if (current == null) // Akhir cabang kiri. { // Sisipkan di kiri. parent.leftChild = newNode; return; } } // Akhir perjalanan ke kiri. else // Atau pergi ke kanan. { current = current.rightChild; if (current == null) // Akhir perjalanan cabang kanan. { // Sisipkan di kanan. parent.rightChild = newNode; return; } } // Akhir perjalanan ke kanan. } // Akhir while } // Akhir bukan akar (root). } // Akhir insert() } public boolean delete(int id) { // (Asumsi pohon tidak kosong) Node current = root; Node parent = root; boolean isLeftChild = true; while (current.iData != id) // Mencari Node yang akan dihapus. { parent = current; if (id < current.iData) // Pergi ke kiri? { isLeftChild = true; current = current.leftChild; } else // Atau pergi ke kanan? { isLeftChild = false; current = current.rightChild; } if (current == null) // Akhir baris { return false; // Node yang dicari tidak ditemukan. } } // end while // Node yang akan dihapus ditemukan. // Jika Node tidak memiliki anak, hapus! if (current.leftChild == null && current.rightChild == null) { if (current == root) // Jika Node yang dihapus merupakan akar (Node). { root = null; // Pohon biner menjadi kosong. } else if (isLeftChild) // Jika Node yang dihapus adalah anak sebelah kiri. { parent.leftChild = null; // Pemutusan koneksi. } else // Jika Node yang akan dihapus adalah anak sebelah kanan. { 202 Politeknik Elektronika Negeri Surabaya 92. parent.rightChild = null; 93. } 94. } // Jika tidak ada anak kanan, ganti dengan subpohon kiri. 95. else if (current.rightChild == null) { 96. if (current == root) { 97. root = current.leftChild; 98. } else if (isLeftChild) // Anak sebelah kiri induk. 99. { 100. parent.leftChild = current.leftChild; 101. } else // Anak sebelah kanan induk. 102. { 103. parent.rightChild = current.leftChild; 104. } 105. } // Jika tak ada anak kiri, gantikan dengan subpohon sebelah kanan. 106. else if (current.leftChild == null) { 107. if (current == root) { 108. root = current.rightChild; 109. } else if (isLeftChild) // Anak sebelah kiri induk. 110. { 111. parent.leftChild = current.rightChild; 112. } else // Anak sebelah kanan induk. 113. { 114. parent.rightChild = current.rightChild; 115. } 116. } else // Dua anak, gantikan dengan successor inorder. 117. { 118. // Mendapatkan successor Node untuk dihapus (current) 119. Node successor = getSuccessor(current); 120. // Menghubungkan induk Node saat ini ke successor. 121. if (current == root) { 122. root = successor; 123. } else if (isLeftChild) { 124. parent.leftChild = successor; 125. } else { 126. parent.rightChild = successor; 127. } 128. // connect successor to current's left child 129. successor.leftChild = current.leftChild; 130. } // end else two children 131. // (successor tidak mempunyai anak sebwlah kiri) 132. return true; 133. } // end delete() 134. // Mengembalikan Node yang memiliki nilai terbesar berikuntnya setelah delNode, 135. // pergi ke anak kanan, kemudian turunan kiri anak sebalah kanan. 136. private Node getSuccessor(Node delNode) { 137. Node successorParent = delNode; 138. Node successor = delNode; 139. Node current = delNode.rightChild; // Pergi ke anak sebelah kanan. 140. while (current != null) // Hingga habis. 141. { // Anak kiri. 142. successorParent = successor; 143. successor = current; 144. current = current.leftChild; // Pergi ke anak sebelah kiri. 203 Politeknik Elektronika Negeri Surabaya 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. } // Jika successor bukan anak seblah kanan. if (successor != delNode.rightChild) { // Buat hubungan. successorParent.leftChild = successor.rightChild; successor.rightChild = delNode.rightChild; } return successor; } //Mencari simpul (Node) yang memiliki nilai terkecil. public Node minimum() { Node current, last = null; // Mulai dari akar (root). current = root; // Hingga dasar pohon biner. while (current != null) { // Mencatat Node last = current; // Pergi ke anak kiri. current = current.leftChild; } return last; } } // end class BinaryTree TestBinaryTree.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; public class TestBinaryTree { private static int cari; private static int cacahData; public static void main(String[] args) { BinaryTree bt = new BinaryTree(); // Membuat objek bt bertipe BinaryTree. System.out.print("Berapa data yang akan dimasukkan ke BinaryTree? "); cacahData = inputData(); for (int i = 0; i < cacahData; i++) { System.out.print("Data ke-" + (i + 1) + " = "); bt.insert(inputData()); } System.out.print("Data yang Anda cari ? "); cari = inputData(); Node found = (Node) bt.find(cari); // find node with key 25 if (found != null) { System.out.println("Node dengan key " + cari + " ditemukan."); } else { System.out.println("Node key " + cari + " tidak dapat ditemukan."); } } private static int inputData() { BufferedReader bfr = new BufferedReader(new 204 Politeknik Elektronika Negeri Surabaya 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. InputStreamReader(System.in)); String angkaInput = null; try { angkaInput = bfr.readLine(); } catch (IOException e) { e.printStackTrace(); } int Data = Integer.valueOf(angkaInput).intValue(); return Data; } } E. LATIHAN Latihan 1 : buat class BinerySearchTree, kemudian analisa dan gambarkan pohonya sesuai code berikut : 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. import java.util.*; class Node{ int data; Node left; Node right; Node(int x){ this.data = x; } } public class BinarySearchTree{ private Node root; /** * Mengecek apakah tree masih kosong **/ private boolean isEmpty(){ return (root == null); } /** * Memasukkan suatu nilai ke dalam tree. * Jika nilai tersebut lebih kecil dari nilai node, maka bergerak ke kiri terus * hingga menjadi child, begitu juga sebaliknya. **/ public void insert(int input){ Node temp = new Node(input); if (isEmpty()) root = temp; else { Node cursor = root, parent = null; while (cursor != null){ parent = cursor; if (input < cursor.data) cursor = cursor.left; else cursor = cursor.right; } 205 Politeknik Elektronika Negeri Surabaya 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. /** * Menambahkan Node baru pada kiri/kanan Node parent bergantung * pada nilai input dan nilai yang disimpan Node parent **/ if (input < parent.data){ parent.left = temp; return; } else { parent.right = temp; return; } } } /* Mencari suatu nilai dalam tree berdasarkan prinsip : * Selama belum menemukan nilai yang sama, * Jika nilai yang dicari lebih kecil dari nilai yang disimpan dalam Node 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64. 65. 66. 67. 68. 69. 70. 71. 72. 73. 74. 75. 76. 77. 78. 79. 80. 81. 82. 83. 84. 85. 86. 87. 88. 89. 90. * maka bergerak ke left Child begitu juga sebaliknya. **/ public boolean delete(int key){ Node cursor = root, parent = null; boolean found = false, isLeftChild = true; //menandai apakah Node yang dihapus merupakan left child if (!isEmpty()){ while (cursor != null){ parent = cursor; if (key == cursor.data){ found = true; break; } else if (key < cursor.data){ isLeftChild = true; cursor = cursor.left; } else { isLeftChild = false; cursor = cursor.right; } } if (!found) return false; else { /** * Untuk menghapus leaf (tidak punya child) **/ if (cursor.left == null && cursor.right == null){ if (cursor == root) root = null; else if (isLeftChild) parent.left = null; else parent.right = null; 206 Politeknik Elektronika Negeri Surabaya 91. 92. 93. } /* Jika node yang akan dihapus hanya memiliki salah satu subtree 94. * maka tinggal memindahkan subtree menggantikan node yang dihapus 95. **/ 96. else if (cursor.left == null){ 97. if (cursor == root) 98. root = cursor.right; 99. else if (isLeftChild) 100. parent.left = cursor.right; 101. else 102. parent.right = cursor.right; 103. } 104. else if (cursor.right == null){ 105. if (cursor == root) 106. root = cursor.left; 107. else if (isLeftChild) 108. parent.left = cursor.left; 109. else 110. parent.right = cursor.left; 111. } 112. /** 113. * Jika node yang akan dihapus memiliki 2 child, maka cari successornya 114. * dengan fungsi getSuccessor kemudian hubungkan subtree bagian kanan 115. * dari node yang dihapus dengan successor 116. **/ 117. else { 118. Node successor = getSuccessor(cursor); 119. if (cursor == root) 120. root = successor; 121. else if (isLeftChild) 122. parent.left = successor; 123. else 124. parent.right = successor; 125. //menyambung successor dengan cursor.right 126. successor.right = cursor.right; 127. } 128. } 129. } 130. return true; 131. } 132. 133. private Node getSuccessor(Node localNode){ 134. Node parent = null, 135. successor = localNode, 136. cursor = localNode.left; 137. while (cursor != null){ 138. parent = successor; 139. successor = cursor; 140. cursor = cursor.right; 141. } 142. if (successor != localNode.left){ 143. parent.right = successor.left; 207 Politeknik Elektronika Negeri Surabaya 144. 145. 146. 147. 148. 149. 150. 151. 152. 153. 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167. 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181. 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195. 196. 197. 198. 199. successor.left = localNode.left; } return successor; } /** * Method traverse untuk mengelilingi Node-Node dalam tree **/ public void traverse(int tipe){ switch (tipe){ case 1: System.out.print("\nPreorder traversal:\n"); preOrder(root); break; case 2: System.out.print("\nInorder traversal:\n"); inOrder(root); break; case 3: System.out.print("\nPostorder traversal:\n"); postOrder(root); break; } System.out.println('\n'); } private void preOrder(Node localRoot){ if (localRoot == null) return; System.out.print(localRoot.data+" "); preOrder(localRoot.left); preOrder(localRoot.right); } private void inOrder(Node localRoot){ if (localRoot == null) return; inOrder(localRoot.left); System.out.print(localRoot.data+" "); inOrder(localRoot.right); } private void postOrder(Node localRoot){ if (localRoot == null) return; postOrder(localRoot.left); postOrder(localRoot.right); System.out.print(localRoot.data+" "); } public static void main(String[] args) { BinarySearchTree a = new BinarySearchTree(); //penambahan node pada binary tree a.insert(5); a.insert(4); a.insert(6); a.insert(1); a.insert(4); a.insert(9); //penelusuran node pada binary tree a.traverse(1); //pre-order a.traverse(2); //in-order 208 Politeknik Elektronika Negeri Surabaya 200. 201. 202. a.traverse(3); //post-order } } Latihan 2 :Dengan menggunakan class BinarySearchTree lakukan pemanggilan method insert() dengan mengirimkan input berturut-turut sesuai dengan deret berikut : {10, 5,20,2,6,19,25,21}, root adalah 10. Gambarkan hasil akhir binary search tree tersebut! F. LAPORAN RESMI Kerjakan hasil percobaan(D) dan latihan(E) di atas dan tambahkan analisa. 209