Sunday, May 17, 2020

Heap & Tries

Sekarang kita akan membahas dua materi yakni, Heap dan Tries. Kita langsung masuk ke penjelasannya aja yuk.

1. Heap

Heap itu adalah struktur data berbasis pohon khusus dimana pohon itu adalah pohon biner lengkap. Heap itu juga merupakan pohon yang isi dari root hingga leaf berurut dari index pada array.
contoh : kita memiliki array[] : {4 3 2 6 5}, maka kita akan memiliki pohon heap seperti :         
 
                4
              /   \
            3     2
          /   \
        6     5

Dari contoh itu kita dapat melihat bahwa setiap node dari heap tree tersebut itu sesuai urutannya dengan value dari index pada array yang kita miliki.

Heap juga memiliki tiga macam, yaitu min heap, max heap, dan min-max heap.
Saya hanya akan membahas min heap dan max heap saja, karena min-max heap itu jarang digunakan.

A. Min Heap

1. Insertion Dalam Min Heap

Min heap adalah heap yang data di parent atau root memiliki value yang lebih kecil dari childnya.

contoh : kita memiliki value dalam array[] : {7 4 3 8 2 6 5}

langkah pertama yang kita lakukan adalah memasukan semua value dalam array itu seperti contoh diatas saat saya menjelaskan tentang heap, yaitu masukan value kedalam tree sesuai dengan urutan indexnya. 

               7
      /   \
    4     3
   / \    /  \
         8  2  6   5

Setelah kita memasukkan value tersebut menjadi bentuk tree, sekanjutnya kita akan membandingkan child dengan parentnya. Jika value dari child lebih kecil dari parentnya maka akan kita swap.

                7                                          2
      /   \                                       /   \
    4     3               =>               4      3
   / \    /  \                                /  \    /  \
         8  2  6   5                             8   7 6   5

Saya akan menjelaskan cara melakukan swapping heap untuk min heap dari tree tersebut.
  1. Kita akan bandingkan value 2 dan 4, karena yang lebih kecil adalah 2 maka kita akan swapping 2 dengan 4.
  2. Lalu, saat 2 sudah di posisi 4, kita akan bandingkan kembali 2 dengan 7, karena yang lebih kecil 2 maka kita akan melakukan swapping 2 dengan 7 sehingga kita mendapatkan value root baru yaitu 2.
  3. Dan yang terakhir, kita akan menukar 7 dengan 4 karena 4 lebih kecil kita akan melakukan swapping sehingga tree akan terbentuk seperti urutan yang sebelah kanan. 

2. Deletion Dalam Min Heap

Untuk deletion kita memakai cara yang sama seperti Binary Search Tree. Saya akan langsung menjelaskan caranya. Anggap saja kita memiliki array yang sama seperti array saat insertion min heap yaitu, array[] : {7 4 3 8 2 6 5} tetapi saya akan mengambil tree yang sudah memenuhi syarat min heap.

                          2
                /   \
                      4      3
                     /  \    /  \
                   8   7  6   5

Dari tree tersebut, misalnya saya ingin mendelete value 2 yang terletak di root. Nah untuk menggantinya kita ambil dari value urutan terakhir di index array (lebih mudahnya lagi, value yang terakhir dimasukkan kedalam tree) yaitu 5. 

                          5
                /   \
                      4      3
                     /  \    /  
                   8   7  6   

Setelah digantikkan root pada tree akan menjadi 5. setelah itu kita akan melakukan teknik heapify untuk mengganti / swapping dengan child yang memiliki nilai terkecil yaitu 3. 

                          3
                /   \
                      4      5
                     /  \    /  
                   8   7  6 

Bentuk tree akan menjadi seperti ini.

B. Max Heap

1. Insertion Dalam Max Heap

Cara melakukan insertion dalam max heap sama seperti min heap, tetapi untuk swapping sedikit berbeda, pada min heap semua parent valuenya akan lebih kecil daripada child, pada max heap valuenya akan lebih besar dari pada childnya.

contoh : kita memiliki tree sebagai berikut

               5
     /   \
   10    3
   /  \   /  \
          7  4 6   8

Kita akan melakukan swapping yang sama seperti min heap, tetapi bedanya adalah parent harus lebih besar daripada childnya. 
  1. Dari tree tersebut kita akan melakukan swapping 3 dengan 8 karena 8 merupakan anak terbesar dari 3.
  2. Setelah itu kita akan melakukan swapping 10 dengan 5 karena 10 merupakan anak terbesar dari 5.
  3. setelah ditukar, 5 akan kita tukar kembali dengan 7 karena valuenya lebih besar.
Setelah melakukan semua itu kita mendapatkan tree sebagai berikut.

              10
     /    \
   7      8
  /  \    /  \
         5  4  6   3

2. Deletion Dalam Max Heap

Untuk deletion dalam max heap pun sama seperti min heap. Untuk contoh treenya saya akan ambil dari tree max heap yang sudah sesuai dengan syarat tree max heap.

              10
     /    \
   7      8
  /  \    /  \
         5  4  6   3

Lalu saya ingin mendelete value 8. Kita hanya langsung mendelete 8 dan menggantikannya dengan 3 setelah itu kita akan melakukan heapify dengan 6 dan langsung mendapatkan tree sebagai berikut.

              10
     /    \
   7      6
  /  \    /  
         5  4  3


C. Min-Max Heap

Untuk mempelajari min-max heap, saya akan mencantumkan sumbernya disini agar kalian bisa pelajari sendiri.

Sumber : 


2. Tries

Trie adalah struktur data pencarian informasi yang efisien. Menggunakan Trie, kompleksitas pencarian dapat dibawa ke batas optimal (panjang kunci). Jika kita menyimpan kunci dalam pohon pencarian biner, BST yang seimbang akan membutuhkan waktu yang proporsional dengan M * log N, di mana M adalah panjang string maksimum dan N adalah jumlah key dalam pohon. Dengan menggunakan Trie, kita dapat mencari key dalam waktu O (M). Namun penalti ada pada persyaratan penyimpanan Trie (Silakan merujuk Aplikasi Trie untuk detail lebih lanjut).


  

Setiap simpul Trie terdiri dari banyak cabang. Setiap cabang mewakili karakter kunci yang memungkinkan. Kita perlu menandai simpul terakhir dari setiap key sebagai simpul kata akhir. Bidang simpul Trie isEndOfWord digunakan untuk membedakan simpul tersebut sebagai simpul akhir kata. Struktur sederhana untuk mewakili simpul dari alfabet bahasa Inggris dapat sebagai berikut,

// Trie node
struct TrieNode
{
     struct TrieNode *children[ALPHABET_SIZE];
     // isEndOfWord is true if the node
     // represents end of a word
     bool isEndOfWord;
};
Memasukkan key ke Trie adalah pendekatan sederhana. Setiap karakter key input dimasukkan sebagai simpul Trie individual. Perhatikan bahwa anak-anak adalah array pointer (atau referensi) ke node trie level berikutnya. Karakter key bertindak sebagai indeks ke dalam array anak-anak. Jika kunci input adalah baru atau ekstensi dari kunci yang ada, kita perlu membangun simpul kunci yang tidak ada, dan menandai akhir kata untuk simpul terakhir. Jika key input adalah awalan dari key yang ada di Trie, kami cukup menandai simpul terakhir kunci sebagai akhir kata. Panjang key menentukan kedalaman Trie.
Mencari key mirip dengan memasukkan operasi, namun, kami hanya membandingkan karakter dan bergerak ke bawah. Pencarian dapat diakhiri karena akhir string atau kurangnya key dalam trie. Dalam kasus sebelumnya, jika bidang isEndofWord dari simpul terakhir benar, maka key ada di trie. Dalam kasus kedua, pencarian berakhir tanpa memeriksa semua karakter kunci, karena key tidak ada dalam trie.
Gambar berikut menjelaskan konstruksi trie menggunakan kunci yang diberikan dalam contoh di bawah ini,
                       root
                    /   \    \
                    t   a     b
                    |   |     |
                    h   n     y
                    |   |  \  |
                    e   s  y  e
                 /  |   |
                 i  r   w
                 |  |   |
                 r  e   e
                        |
                        r

Dalam gambar, setiap karakter bertipe trie_node_t. Sebagai contoh, root adalah tipe trie_node_t, dan itu anak-anak a, b dan t diisi, semua node root lainnya adalah NULL. Demikian pula, "a" di tingkat berikutnya hanya memiliki satu anak ("n"), semua anak lainnya adalah NULL. Node daun yang berwarna biru.



Sekian dari penjelasan saya mengenai Heap dan Tries. Semoga bermanfaat untuk kalian semua.





Nama : Reinhart Perbowo Pujo Leksono
NIM : 2301857254

Source:



                                

























 

Sunday, May 3, 2020

AVL Tree

Pengertian AVL Tree

AVL Tree adalah tree yang hanya boleh memiliki perbedaan tinggi/height maksimal satu antara subtree di kiri dan di kanan. Dengan adanya AVL tree, waktu pencarian akan dipersingkat dan lebih sederhana.



STRUKTUR DATA - Balanced Binary Search Tree (AVL and RBT) and 2-3 Tree

Gambar tersebut merupakan contoh dari AVL Tree karena perbedaan tinggi dari subtree kanan dan subtree kiri adalah 1.

Insertion

Insertion pada AVL tree sama seperti insertion pada BST, yang lebih kecil dari pada root akan berada di sebelah kiri dan yang lebih besar akan berada di sebelah kanan. Masalah yang biasa terjadi pada insertion di sini adalah bisa saja treenya tidak akan seimbang. Pada syarat AVL kita hanya diperbolehkan memiliki tinggi maksimal 1/-1 saja. Untuk membuat AVL tree tetap seimbang kita akan menggunakan dua teknik yaitu, single rotation dan double rotation. Jangan lupa untuk arah rotasi juga ada dua ya! right rotate dan left rotate.

1. Single Rotation
T1, T2, T3 and T4 are subtrees.
         z                        z                  
        / \                      / \                   
       y   T4                  T1   y
      / \           atau           / \
     x   T3                       T2  x             
    / \                              / \
  T1   T2                           T3  T4
Kita diperbolehkan menggunakan single rotation jika bentuk dari AVL tree seperti diatas. Jadi, dari root lurus kekiri bawah (leaf) ataupun dari root lurus ke kanan bawah (leaf). Cara untuk melakukan rotasinya adalah sebagai berikut.

T1, T2, T3 and T4 are subtrees.
         z                                      y 
        / \                                   /   \
       y   T4      Right Rotate (z)          x      z
      / \          - - - - - - - - ->      /  \    /  \ 
     x   T3                               T1  T2  T3  T4
    / \
  T1   T2
Dari tulisan tersebut kira dapat lihat cara untuk menggunakan single rotation. Pada tree yang pertama kita lihat bahwa disana terdapat perbedaan 2 level lebih banyak di subtree kiri. Oleh karena itu, kita harus rotasikan z yang awalannya adalah root dari tree (dan juga merupakan poros untuk dirotasikan), menjadi subtree di kanan. Sehingga y akan menjadi root baru dan semuanya akan kembali seimbang antara subtree kanan dan kiri. 

Permasalahan selanjutnya adalah bagaimana dengan T3 jika subtree kanan dan kiri y sudah terisi karena y telah menjadi root baru? Jawabannya adalah kita masukkan T3 kedalam subtree kiri z, mengapa? karena sebelumnya T3 merupakan anak kanan dari y yang nilainya lebih besar dari x tetapi lebih kecil dari z, sehingga saat single rotation telah dilakukan T3 akan pindah kedalam subtree kiri dari z.


2. Double Rotation
     z                  z           
    / \                / \         
   y   T4             T1  y
  / \        atau        / \
T1   x                  x   T2                  
    / \                / \    
  T2   T3             T3  T4    
Untuk double rotation kita hanya diperbolehkan memakainya jika bentuk tree seperti diatas, dari root sampai leaf bengkok dan tidak lurus kebawah. Cara untuk merotasikannya adalah sebagai berikut.

     z                               z                           x
    / \                            /   \                        /  \ 
   y   T4  Left Rotate (y)        x    T4  Right Rotate(z)    y      z
  / \      - - - - - - - - ->    /  \      - - - - - - - ->  / \    / \
T1   x                          y    T3                    T1  T2 T3  T4
    / \                        / \
  T2   T3                    T1   T2

Dari tulisan diatas kita dapat melihat bahwa bentuk tree dari root sampai leaf bengkok. Perbedaan level pada subtree di kiri dan subtree di kanan adalah dua. Untuk melakukan double rotation kita harus mengetahui porosnya terlebih dahulu. Karena namanya saja double rotation berarti kita juga memiliki 2 poros yang harus dirotasikan. Poros pertama yang harus di rotasikan pada tree diatas adalah y karena y merupakan awalan yang membuat tree menjadi bengkok. Kita rotasikan y ke kiri sehingga memiliki bentuk tree baru seperti gambar kedua. Jika dilihat lebih baik lagi, kita dapat melihat bahwa gambar kedua mirip sekali dengan tree yang sudah kita bahas di single rotation. Oleh karena itu, poros kedua adalah rootnya yaitu z, z di rotasikan ke kanan sehingga x menjadi root yang baru dan z menjadi subtree bagian kanan dari x. Jangan lupa untuk memindahkan T3 ke subtree kiri dari z!

Deletion

Jika kita ingin menghapus suatu node dalam AVL tree kita dan kita ingin memastikan agar tree tersebut masih memenuhi syarat AVL, kita harus menambahkan operasi penghapusan BST standar untuk melakukan beberapa penyeimbangan ulang.

avl-delete1



avl-delete1

Dari dua gambar diatas kita dapat mengetahui jika node 32 sedang dihapus dan setelah dihapus kita akan kembali melihat bentuk tree itu lagi dan perbaiki tree tersebut jika ada yang tidak seimbang. Dari tree tersebut yang menjadi tidak seimbang adalah 44 yang akan ditandai dengan z, 62 akan ditandai dengan y dan 78 akan ditandai dengan x. Setelah itu kita dapat melihat jika dari root sampai leaf memiliki jalur lurus, sehingga kita akan melakukan single rotation dan porosnya berada pada z / node 44 yang akan kita rotate ke kiri sehingga, kita mendapatkan tree yang sama seperti gambar kedua. Sama seperti sebelumnya, 50 akan menjadi anak kanan dari z/node 44 karena node 50 sebelumnya merupakan anak kiri dari node 66 sehingga saat node 66 menjadi root yang baru, node 50 akan pindah menjadi anak kanan dari node 44 karena nilainya lebih besar dan node 62 subtree kanan dan kirinya sudah full.


Sekian penjelasan tentang AVL tree dari saya, semoga dapat membantu kalian semua. Terima kasih


Nama : Reinhart Perbowo Pujo Leksono
NIM ; 2301857254

Source :