Panduan Lengkap Tree, Binary Tree, BST, dan AVL Tree: Struktur Data Fundamental

Tree (pohon) adalah salah satu struktur data non-linear yang paling penting dalam ilmu komputer. Berbeda dengan struktur data linear seperti array atau linked list, tree mengorganisir data dalam bentuk hierarkis yang menyerupai pohon terbalik. Struktur ini sangat efisien untuk operasi pencarian, penyisipan, dan penghapusan data, terutama ketika diimplementasikan dalam bentuk Binary Search Tree (BST) dan AVL Tree.

Dalam artikel ini, kita akan mempelajari secara mendalam tentang konsep tree dasar, berbagai jenis binary tree, implementasi Binary Search Tree, hingga optimasi dengan AVL Tree yang menjaga keseimbangan tinggi pohon secara otomatis.

1. Pengertian Tree (Pohon)

Definisi Tree

Tree adalah kumpulan node yang dapat berupa:

  • Empty (kosong) - tidak memiliki node sama sekali
  • Node Root (r) dengan nol atau lebih subtree T₁, T₂, ..., Tₖ, dimana setiap root subtree terhubung dengan edge (garis) ke r

Secara matematis, sebuah tree dengan n node memiliki tepat (n-1) edge.

Tree adalah struktur data hierarkis yang terdiri dari node-node yang saling terhubung. Struktur ini sangat berguna dalam berbagai aplikasi seperti sistem file komputer, database indexing, representasi ekspresi matematika, dan algoritma pencarian.

💡 Karakteristik Utama Tree

  • Memiliki satu root node yang unik (tidak memiliki predecessor)
  • Setiap node kecuali root memiliki tepat satu parent
  • Tidak memiliki cycle (siklus) - tidak ada jalur yang kembali ke node asal
  • Terdapat jalur unik dari root ke setiap node

2. Terminologi dan Konsep Dasar Tree

Untuk memahami tree dengan baik, kita perlu mengenal berbagai istilah yang digunakan:

🔝 Root (Akar)

Node paling atas yang tidak memiliki predecessor. Root adalah titik awal dari seluruh struktur tree.

🍃 Leaf (Daun)

Node yang tidak memiliki successor (children). Leaf adalah node terminal di ujung tree.

👨‍👦 Parent-Child

Parent adalah predecessor langsung dari suatu node. Child adalah successor langsung dari parent.

👫 Sibling

Node-node yang memiliki parent yang sama. Mereka adalah saudara dalam hierarki tree.

⬆️ Ancestors

Semua node dalam jalur dari suatu node ke root, termasuk parent, grandparent, dan seterusnya.

⬇️ Descendants

Semua node yang dapat dicapai dari suatu node, termasuk children, grandchildren, dan seterusnya.

Konsep Path, Depth, dan Height

📏 Path (Jalur)

Path dari node n₁ ke nₖ adalah urutan node n₁, n₂, ..., nₖ dimana nᵢ adalah parent dari nᵢ₊₁. Panjang path didefinisikan sebagai jumlah edge pada jalur tersebut.

🔢 Depth (Kedalaman)

Depth dari node nᵢ adalah panjang path dari root ke nᵢ. Depth root selalu 0.

📊 Height (Tinggi)

Height dari node nᵢ adalah panjang path terpanjang dari nᵢ ke leaf. Height root sama dengan height tree secara keseluruhan.

📌 Contoh Ilustrasi

Misalkan kita memiliki tree dengan struktur:

  • Root: A
  • Children dari A: B, C, D, E, F, G
  • Children dari E: I, J
  • Children dari J: P, Q
  • Leaves: B, C, H, I, K, L, M, N, P, Q

Dalam contoh ini:

  • Ancestors dari J adalah: E dan A
  • Descendants dari E adalah: I, J, P, dan Q
  • Sibling dari F adalah: B, C, D, E, dan G

3. Implementasi Tree dengan Linked List

Tree dapat diimplementasikan menggunakan linked list dengan struktur khusus. Karena jumlah children pada setiap node dapat bervariasi dan tidak diketahui sebelumnya, kita menggunakan pendekatan First Child - Next Sibling.

Struktur Data Tree Node

struct tree_node {
    datatype data;
    tree_node *FC;  // First Child - pointer ke child pertama
    tree_node *NS;  // Next Sibling - pointer ke sibling berikutnya
};

💡 Konsep First Child - Next Sibling

Teknik ini mengatasi masalah variasi jumlah children dengan cara:

  • FC (First Child): Menunjuk ke anak pertama dari node
  • NS (Next Sibling): Menunjuk ke saudara berikutnya yang memiliki parent sama

Dengan cara ini, setiap node hanya membutuhkan dua pointer, namun dapat merepresentasikan tree dengan jumlah children tidak terbatas.

Contoh Implementasi untuk File System

struct node {
    string name;   // nama file atau directory
    long size;     // ukuran file
    node *FC;      // First Child
    node *NS;      // Next Sibling
};

Struktur ini sangat cocok untuk merepresentasikan sistem file komputer, dimana setiap directory dapat memiliki banyak file dan subdirectory.

4. Traversal Tree

Traversal adalah proses mengunjungi setiap node dalam tree secara sistematis. Ada tiga jenis traversal utama yang analog dengan notasi ekspresi matematika:

1️⃣ PreOrder

Mengunjungi node sebelum mengunjungi subtree-nya (analog dengan notasi Prefix)

Urutan: Root → Left → Right

2️⃣ InOrder

Mengunjungi node di antara subtree kiri dan kanan (analog dengan notasi Infix)

Urutan: Left → Root → Right

3️⃣ PostOrder

Mengunjungi node setelah semua subtree-nya dikunjungi (analog dengan notasi Postfix)

Urutan: Left → Right → Root

Implementasi Traversal

PreOrder Traversal - List Directory

void ListDir(node *n, int depth) {
    if (n) {
        print(n, depth);           // Cetak node saat ini
        ListDir(n->FC, depth+1);   // Kunjungi children
        ListDir(n->NS, depth);     // Kunjungi sibling
    }
}

PostOrder Traversal - Calculate Size

long Trace(node *n, int depth) {
    long t_size = 0;
    if (n) {
        t_size = n->size;              // Ambil size node
        t_size += Trace(n->FC, depth+1);  // Hitung size children
        print(n, depth, t_size);       // Cetak setelah children
        t_size += Trace(n->NS, depth);    // Tambah size sibling
    }
    return t_size;
}

🎯 Aplikasi Traversal

  • PreOrder: Membuat salinan tree, menampilkan struktur directory
  • InOrder: Mendapatkan data terurut dari BST
  • PostOrder: Menghapus tree, menghitung ukuran directory

5. Binary Tree (Pohon Biner)

Definisi Binary Tree

Binary Tree adalah tree dimana setiap node maksimal memiliki dua children (anak). Kedua anak ini biasanya disebut sebagai left child (anak kiri) dan right child (anak kanan).

Binary Tree adalah salah satu struktur data tree yang paling sering digunakan karena kesederhanaannya dan efisiensi operasinya. Struktur ini menjadi dasar untuk berbagai struktur data lanjutan seperti BST, AVL Tree, Red-Black Tree, dan Heap.

Jenis-Jenis Binary Tree

1. Complete Binary Tree (Pohon Biner Lengkap)

Complete Binary Tree adalah binary tree dimana:

  • Semua level terisi penuh kecuali mungkin level terakhir
  • Level terakhir diisi dari kiri ke kanan
  • Setiap node memiliki 0 atau 2 children (tidak ada node dengan 1 child)
  • Setiap subtree dapat memiliki panjang path yang berbeda

Karakteristik: Optimal untuk implementasi Heap

2. Full Binary Tree (Pohon Biner Penuh)

Full Binary Tree memiliki properti yang lebih ketat:

  • Sama seperti Complete Binary Tree
  • Semua subtree harus memiliki panjang path yang sama
  • Semua leaf berada pada level yang sama
  • Setiap internal node memiliki tepat 2 children

Karakteristik: Bentuk tree yang paling seimbang sempurna

3. Skewed Binary Tree (Pohon Biner Miring)

Skewed Binary Tree adalah bentuk tree yang tidak seimbang:

  • Sebagian besar node hanya memiliki satu child
  • Bentuknya menyerupai linked list
  • Sangat tidak efisien untuk operasi pencarian
  • Kompleksitas operasi menjadi O(n) seperti linked list

⚠️ Performa Buruk: Harus dihindari dengan balancing

Struktur Data Binary Tree

struct BinaryNode {
    datatype data;
    BinaryNode *left;   // Pointer ke left child
    BinaryNode *right;  // Pointer ke right child
};

Implementasi Array untuk Binary Tree

💡 Formula Indexing Binary Tree dalam Array

Binary Tree dapat direpresentasikan dalam array dengan formula:

  • Root: Index 0
  • Left child dari index p: 2p + 1
  • Right child dari index p: 2p + 2
  • Parent dari index p: (p - 1) / 2

Metode ini sangat efisien untuk Complete Binary Tree karena tidak ada waste space.

6. Expression Tree

Expression Tree adalah aplikasi khusus dari Binary Tree yang merepresentasikan ekspresi matematika. Struktur ini sangat berguna untuk:

  • Parsing dan evaluasi ekspresi matematika
  • Compiler dan interpreter untuk bahasa pemrograman
  • Kalkulator scientific
  • Symbolic mathematics

Karakteristik Expression Tree

🔢 Operand (Leaf Node)

Angka atau variabel berada di leaf nodes

➕ Operator (Internal Node)

Operator matematika (+, -, *, /) berada di internal nodes

Cara Membuat Expression Tree

Langkah-langkah:

  1. Konversi ekspresi infix ke postfix (Reverse Polish Notation)
  2. Buat stack untuk menyimpan pointer ke node tree
  3. Scan ekspresi postfix dari kiri ke kanan:
    • Jika operand: buat node baru dan push ke stack
    • Jika operator: pop 2 node dari stack, buat node operator dengan kedua node sebagai children, push kembali ke stack
  4. Node terakhir di stack adalah root dari expression tree

📌 Contoh: (a + b * c) + ((d * e + f) * g)

Langkah 1: Konversi ke postfix

a b c * + d e * f + g * +

Langkah 2: Konstruksi tree dari postfix

Root tree akan berisi operator '+' terakhir, dengan subtree kiri 'a + b * c' dan subtree kanan '(d * e + f) * g'

Traversal pada Expression Tree

Jenis Traversal Hasil Notasi
PreOrder + + a * b c * + * d e f g Prefix (Polish Notation)
InOrder a + b * c + d * e + f * g Infix (perlu tambahan tanda kurung)
PostOrder a b c * + d e * f + g * + Postfix (Reverse Polish Notation)

7. Binary Search Tree (BST)

Definisi Binary Search Tree

Binary Search Tree (BST) adalah Binary Tree dengan properti khusus untuk setiap node X:

  • Semua nilai node di left subtree harus lebih kecil dari nilai X
  • Semua nilai node di right subtree harus lebih besar dari nilai X

Properti ini berlaku secara rekursif untuk semua node dalam tree.

Keunggulan BST

🚀 Pencarian Cepat

Kompleksitas O(log n) untuk tree seimbang, jauh lebih cepat dibanding array O(n)

📥 Insertion Efisien

Tidak perlu shifting elemen seperti pada array terurut

🗑️ Deletion Fleksibel

Dapat menghapus node dengan berbagai kasus tanpa reorganisasi besar

📊 Data Terurut

InOrder traversal menghasilkan data dalam urutan terurut

Struktur Data BST

struct SNode {
    int data;
    SNode *left;
    SNode *right;
};

SNode *Root;  // Pointer ke root tree

Operasi Insert pada BST

Algoritma Insert

  1. Jika tree kosong, buat node baru sebagai root
  2. Jika data lebih kecil dari node saat ini, insert ke left subtree
  3. Jika data lebih besar dari node saat ini, insert ke right subtree
  4. Jika data sama (opsional: tambahkan counter atau tolak)
SNode* Insert(int dat, SNode* T) {
    if (!T) {
        // Tree kosong, buat node baru
        SNode* temp = new SNode;
        temp->data = dat;
        temp->left = nullptr;
        temp->right = nullptr;
        return temp;
    } else {
        if (dat < T->data)
            T->left = Insert(dat, T->left);   // Insert ke kiri
        else if (dat > T->data)
            T->right = Insert(dat, T->right); // Insert ke kanan
        return T;
    }
}

💡 Handling Duplikasi

Untuk mengizinkan data duplikat, kita dapat menambahkan field counter:

struct SNode {
    int data;
    int occur;     // Jumlah kemunculan data
    SNode *left;
    SNode *right;
};

Operasi Delete pada BST

Operasi delete lebih kompleks karena ada tiga kasus yang harus ditangani:

Kasus 1: Leaf Node

Node tidak memiliki children. Cukup hapus node tersebut.

Kasus 2: Satu Child

Node memiliki satu child. Ganti node dengan child-nya.

Kasus 3: Dua Children

Node memiliki dua children. Ganti dengan inorder successor (minimum dari right subtree) atau inorder predecessor (maximum dari left subtree).

SNode* Delete(int dat, SNode* n) {
    SNode* cur;
    
    if (n) {
        if (dat < n->data)
            n->left = Delete(dat, n->left);
        else if (dat > n->data)
            n->right = Delete(dat, n->right);
        else {
            // Node ditemukan
            if (n->left && n->right) {
                // Kasus 3: dua children
                // Cari minimum dari right subtree
                FindMin(n);
            } else if (n->left) {
                // Kasus 2: hanya left child
                cur = n;
                n = n->left;
                delete cur;
            } else {
                // Kasus 2: hanya right child atau leaf
                cur = n;
                n = n->right;
                delete cur;
            }
        }
        return n;
    } else
        return nullptr;
}

Kompleksitas BST

Operasi Best Case Average Case Worst Case
Search O(log n) O(log n) O(n)
Insert O(log n) O(log n) O(n)
Delete O(log n) O(log n) O(n)

⚠️ Kelemahan BST

Worst case O(n) terjadi ketika BST menjadi skewed (tidak seimbang). Contoh: insert data terurut (1, 2, 3, 4, 5) akan menghasilkan tree yang menyerupai linked list.

Solusi: Gunakan Self-Balancing BST seperti AVL Tree atau Red-Black Tree!

8. AVL Tree - Height Balanced Tree

Definisi AVL Tree

AVL Tree adalah Binary Search Tree yang menjaga properti height balanced, yaitu perbedaan tinggi antara left subtree dan right subtree untuk setiap node maksimal 1.

Nama AVL berasal dari penemunya: Adelson-Velsky dan Landis (1962).

AVL Tree adalah solusi untuk mengatasi kelemahan BST yang dapat menjadi tidak seimbang. Dengan menjaga keseimbangan tinggi tree, AVL Tree memastikan bahwa semua operasi tetap memiliki kompleksitas O(log n).

Konsep Balance Factor (BF)

Balance Factor

Balance Factor dari sebuah node adalah selisih tinggi left subtree dan right subtree:

BF(node) = height(left subtree) - height(right subtree)

Dalam AVL Tree yang valid:

  • BF setiap node harus bernilai -1, 0, atau +1
  • BF = -1: Right subtree lebih tinggi 1 level
  • BF = 0: Left dan right subtree seimbang
  • BF = +1: Left subtree lebih tinggi 1 level

Properti AVL Tree

🎯 Height Balanced

|hL - hR| ≤ 1 untuk setiap node, dimana hL dan hR adalah tinggi left dan right subtree

📏 Tinggi Optimal

Height AVL Tree dengan n node adalah O(log n), menjamin operasi cepat

♻️ Self-Balancing

Otomatis melakukan rotasi saat terjadi ketidakseimbangan setelah insert atau delete

🔍 Efisien

Semua operasi (search, insert, delete) dijamin O(log n)

Struktur Data AVL Tree

struct Node {
    int data;
    int height;    // Menyimpan tinggi node untuk efisiensi
    Node *left;
    Node *right;
};

Node *Root;

Fungsi Bantuan

// Mendapatkan tinggi node
int Height(Node* n) {
    return (n) ? n->height : -1;
}

// Mendapatkan maksimum dari dua nilai
int Max(int L, int R) {
    return (L > R) ? L : R;
}

// Menghitung Balance Factor
int BalanceFactor(Node* n) {
    if (!n) return 0;
    return Height(n->left) - Height(n->right);
}

Jenis Rotasi pada AVL Tree

Ketika terjadi ketidakseimbangan (BF = -2 atau +2), AVL Tree melakukan rotasi untuk mengembalikan keseimbangan. Ada 4 jenis rotasi:

1. Single Right Rotation (LL Case)

Digunakan ketika:

  • Node memiliki BF = +2 (left subtree lebih tinggi)
  • Left child memiliki BF = +1 atau 0
void Right_Rotation(Node* k2) {
    Node* k1;
    
    k1 = k2->left;
    k2->left = k1->right;
    k1->right = k2;
    
    // Update heights
    k2->height = Max(Height(k2->left), Height(k2->right)) + 1;
    k1->height = Max(Height(k1->left), k2->height) + 1;
    
    k2 = k1;  // k1 menjadi root baru
}

2. Single Left Rotation (RR Case)

Digunakan ketika:

  • Node memiliki BF = -2 (right subtree lebih tinggi)
  • Right child memiliki BF = -1 atau 0
void Left_Rotation(Node* k1) {
    Node* k2;
    
    k2 = k1->right;
    k1->right = k2->left;
    k2->left = k1;
    
    // Update heights
    k1->height = Max(Height(k1->left), Height(k1->right)) + 1;
    k2->height = Max(Height(k2->right), k1->height) + 1;
    
    k1 = k2;  // k2 menjadi root baru
}

3. Left-Right Rotation (LR Case)

Digunakan ketika:

  • Node memiliki BF = +2
  • Left child memiliki BF = -1

Rotasi ganda: Left rotation pada left child, kemudian Right rotation pada node

void Left_Right(Node* k3) {
    Left_Rotation(k3->left);   // Rotasi kiri pada k1
    Right_Rotation(k3);         // Rotasi kanan pada k3
}

4. Right-Left Rotation (RL Case)

Digunakan ketika:

  • Node memiliki BF = -2
  • Right child memiliki BF = +1

Rotasi ganda: Right rotation pada right child, kemudian Left rotation pada node

void Right_Left(Node* k1) {
    Right_Rotation(k1->right);  // Rotasi kanan pada k3
    Left_Rotation(k1);          // Rotasi kiri pada k1
}

📌 Kapan Menggunakan Rotasi?

Kasus BF Node BF Child Rotasi
LL +2 +1 atau 0 Right Rotation
RR -2 -1 atau 0 Left Rotation
LR +2 -1 Left-Right Rotation
RL -2 +1 Right-Left Rotation

9. Operasi pada AVL Tree

Operasi Insert pada AVL Tree

Algoritma Insert AVL

  1. Lakukan insert seperti BST biasa
  2. Update height dari node yang di-insert ke atas
  3. Cek Balance Factor setiap node dalam path
  4. Jika BF = -2 atau +2, lakukan rotasi yang sesuai
Node* Insertion(int x, Node* p) {
    if (!p) {
        // Buat node baru
        p = new Node;
        p->data = x;
        p->height = 0;
        p->left = p->right = nullptr;
    } else {
        if (x < p->data) {
            p->left = Insertion(x, p->left);
            
            // Cek balance factor
            if (abs(Height(p->left) - Height(p->right)) == 2) {
                if (x < p->left->data)
                    Right_Rotation(p);      // LL case
                else
                    Left_Right(p);          // LR case
            } else {
                p->height = Max(Height(p->left), Height(p->right)) + 1;
            }
        } else if (x > p->data) {
            p->right = Insertion(x, p->right);
            
            // Cek balance factor
            if (abs(Height(p->left) - Height(p->right)) == 2) {
                if (x > p->right->data)
                    Left_Rotation(p);       // RR case
                else
                    Right_Left(p);          // RL case
            } else {
                p->height = Max(Height(p->left), Height(p->right)) + 1;
            }
        }
    }
    return p;
}

📌 Contoh: Konstruksi AVL Tree

Insert urutan: 60, 50, 70, 40, 80, 30, 90, 20, 100

  1. Insert 60: Tree hanya berisi root
  2. Insert 50: 50 menjadi left child dari 60
  3. Insert 70: 70 menjadi right child dari 60, tree seimbang
  4. Insert 40: 40 menjadi left child dari 50, tree seimbang
  5. Insert 80: 80 menjadi right child dari 70, tree seimbang
  6. Insert 30: Menyebabkan ketidakseimbangan di node 60 (BF=+2), lakukan rotasi
  7. Insert 90, 20, 100: Setiap insert dicek dan dilakukan rotasi jika perlu

Hasil akhir adalah AVL Tree yang seimbang dengan height optimal.

Operasi Delete pada AVL Tree

Delete pada AVL Tree lebih kompleks karena harus mempertimbangkan berbagai kasus rebalancing setelah penghapusan.

5 Kasus Utama Deletion

Setiap kasus memiliki 2 variasi (deletion dari left atau right subtree), total 10 kasus:

Case 1: Equal Balance

Node memiliki balance yang sama (BF=0). Setelah deletion, cukup update BF dan stop. Tidak mempengaruhi node di atasnya.

Case 2: Previously Unbalanced

Deletion mengurangi tinggi subtree yang sebelumnya lebih tinggi. Update BF dan lanjutkan traverse ke atas karena dapat mempengaruhi node lain.

Case 3: Balanced Child

Right subtree lebih tinggi dan left subtree dari right child memiliki subtree yang sama tinggi. Lakukan single rotation dan stop (tidak mempengaruhi node di atas).

Case 4: Unbalanced Child

Right subtree lebih tinggi dan salah satu atau kedua subtree dari right child memiliki tinggi (h-1). Lakukan double rotation dan lanjutkan traverse ke atas.

Case 5: Right-Heavy Child

Right subtree lebih tinggi dan right subtree dari right child lebih tinggi dari left-nya. Lakukan single rotation dan lanjutkan traverse ke atas.

💡 Perbedaan dengan Insert

  • Insert: Maksimal 1 rotasi untuk menyeimbangkan tree
  • Delete: Dapat memerlukan rotasi hingga ke root (O(log n) rotasi)
  • Delete harus menelusuri path dari node yang dihapus ke root untuk memeriksa dan memperbaiki keseimbangan

Kompleksitas AVL Tree

Operasi Time Complexity Keterangan
Search O(log n) Dijamin karena tree seimbang
Insert O(log n) Maksimal 1 rotasi
Delete O(log n) Maksimal O(log n) rotasi
Space O(n) Overhead: height field per node

Perbandingan BST vs AVL Tree

Aspek BST AVL Tree
Kompleksitas Worst Case O(n) O(log n)
Balancing Tidak ada Otomatis (self-balancing)
Memory Overhead Rendah Sedang (height field)
Insert/Delete Speed Lebih cepat Sedikit lebih lambat (rotasi)
Search Speed Bervariasi Konsisten cepat
Use Case Data random, jarang insert/delete Aplikasi real-time, database index

10. Kesimpulan

Tree adalah struktur data fundamental yang sangat penting dalam ilmu komputer. Dari tree dasar hingga AVL Tree, setiap evolusi struktur data ini dirancang untuk meningkatkan efisiensi operasi.

🌳 Tree Dasar

Memberikan dasar untuk struktur hierarkis, cocok untuk representasi struktur data seperti file system, organizational chart, dan XML/JSON parsing.

🌲 Binary Tree

Menyederhanakan implementasi dengan maksimal 2 children per node. Dasar untuk berbagai struktur data lanjutan.

🔍 BST

Menambahkan properti ordering untuk pencarian efisien. Ideal untuk aplikasi yang membutuhkan data terurut dan akses cepat.

⚖️ AVL Tree

Menjamin keseimbangan dan kompleksitas O(log n). Perfect untuk aplikasi real-time dan database yang memerlukan performa konsisten.

Kapan Menggunakan Apa?

Gunakan Tree Dasar untuk:

  • Representasi hierarki organisasi
  • File system navigation
  • Parse tree dalam compiler
  • Decision tree dalam AI

Gunakan Binary Tree untuk:

  • Expression evaluation
  • Huffman coding untuk kompresi data
  • Binary heap untuk priority queue
  • Syntax tree dalam compiler

Gunakan BST untuk:

  • Implementasi set dan map
  • Auto-complete features
  • Data terurut dengan insert/delete cukup jarang
  • Range query applications

Gunakan AVL Tree untuk:

  • Database indexing
  • Aplikasi real-time yang memerlukan performa konsisten
  • Sistem dengan banyak read operations
  • Implementasi associative arrays
  • In-memory database dan caching systems

🎯 Key Takeaways

  • Tree memberikan O(log n) time complexity untuk operasi dasar ketika seimbang
  • BST mudah diimplementasikan namun dapat menjadi tidak seimbang
  • AVL Tree mengatasi masalah keseimbangan dengan rotasi otomatis
  • Trade-off: AVL Tree lebih kompleks namun menjamin performa konsisten
  • Pemilihan struktur data harus disesuaikan dengan kebutuhan aplikasi

Komentar