Penyisipan dan Pencarian BST
Implementasikan penyisipan dan pencarian secara rekursif serta iteratif, telusuri jalur dalam pohon untuk berbagai kunci, dan analisis kompleksitas kasus terburuk pada pohon yang tidak seimbang.
Penyisipan dan Pencarian BST adalah pelajaran DSA Interview Prep gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar DSA Interview Prep, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus DSA Interview Prep mencakup 4 pelajaran total.
Definisi Properti BST
Sebuah Pohon Pencarian Biner memenuhi satu invarian: untuk setiap simpul, semua nilai di subpohon kiri lebih kecil secara ketat daripada nilai simpul tersebut, sedangkan semua nilai di subpohon kanan lebih besar secara ketat. Properti pengurutan ini dipertahankan di seluruh subpohon, bukan hanya pada anak langsung, sehingga memungkinkan pencarian, penyisipan, dan penghapusan dalam O(log n) pada pohon seimbang serta membedakan BST dari pohon biner umum.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
# Valid BST:
# 4
# / \
# 2 6
# / \ / \
# 1 3 5 7
# For node 4: left subtree {1,2,3} < 4 < right subtree {5,6,7}
# This holds recursively for EVERY node in the tree.
print('BST property: left < node < right at every level')Pencarian BST Rekursif
Pencarian BST bekerja seperti pencarian biner: bandingkan target dengan nilai simpul saat ini, lalu lakukan rekursi ke subpohon yang sesuai. Jika target sama dengan nilai saat ini, kembalikan simpul tersebut. Jika target lebih kecil, bergeraklah ke kiri; jika lebih besar, bergeraklah ke kanan. Kembalikan nilai kosong jika mencapai simpul kosong. Kompleksitas waktunya adalah O(h) — O(log n) untuk pohon seimbang dan O(n) untuk pohon miring.
def search_bst(root, val):
if not root:
return None # not found
if root.val == val:
return root # found
if val < root.val:
return search_bst(root.left, val)
else:
return search_bst(root.right, val)
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
result = search_bst(root, 2)
print(result.val if result else 'Not found') # 2
result = search_bst(root, 5)
print(result.val if result else 'Not found') # Not foundPencarian BST Iteratif
Pencarian iteratif menghindari overhead tumpukan pemanggilan dan lebih disukai dalam kode produksi. Gunakan penunjuk curr yang bergerak menuruni pohon ke kiri atau kanan berdasarkan perbandingan. Ini adalah perulangan sederhana dengan tiga kasus: kosong (tidak ditemukan), cocok (ditemukan), atau menyesuaikan arah. Pencarian iteratif juga memiliki kompleksitas O(h), tetapi menggunakan ruang O(1), dibandingkan O(h) pada versi rekursif.
def search_bst_iterative(root, val):
curr = root
while curr:
if val == curr.val:
return curr
elif val < curr.val:
curr = curr.left
else:
curr = curr.right
return None # not found
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
node = search_bst_iterative(root, 3)
print(node.val if node else 'Not found') # 3
print(search_bst_iterative(root, 9)) # NonePenyisipan BST Rekursif
Penyisipan BST menemukan posisi yang tepat dengan mengikuti keputusan kiri/kanan yang sama seperti pada pencarian, lalu menambahkan simpul baru pada posisi null pertama yang dicapai. Pendekatan rekursif mengembalikan akar setiap subpohon (yang mungkin merupakan akar baru): jika simpul saat ini kosong, kembalikan TreeNode baru; jika tidak, perbarui root.left atau root.right dengan hasil pemanggilan rekursif. Pola ini rapi dan umum digunakan dalam solusi wawancara teknis.
def insert_bst(root, val):
if not root:
return TreeNode(val) # create new node here
if val < root.val:
root.left = insert_bst(root.left, val)
elif val > root.val:
root.right = insert_bst(root.right, val)
# val == root.val: duplicate, do nothing (or handle as needed)
return root
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root = insert_bst(root, 1)
root = insert_bst(root, 5)
# Tree is now: 4, left=2(left=1), right=7(left=5)
print(root.right.left.val) # 5Penyisipan BST Iteratif
Penyisipan iteratif menggunakan penunjuk parent untuk melacak simpul terakhir yang tidak kosong sebelum mencapai titik penyisipan. Telusuri pohon seperti pada pencarian, sambil melacak induk dan arah terakhir yang diambil. Saat mencapai nilai kosong, tambahkan simpul baru ke sisi yang sesuai dari induk. Selalu tangani kasus khusus pohon kosong (akar kosong) secara terpisah.
def insert_bst_iterative(root, val):
new_node = TreeNode(val)
if not root:
return new_node
curr = root
while True:
if val < curr.val:
if curr.left is None:
curr.left = new_node
break
curr = curr.left
else: # val > curr.val
if curr.right is None:
curr.right = new_node
break
curr = curr.right
return root
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root = insert_bst_iterative(root, 3)
print(root.left.right.val) # 3BST Kasus Terburuk: Pohon Miring
Jika Anda menyisipkan urutan terurut ke dalam BST, hasilnya adalah pohon miring yang merosot menjadi daftar tertaut. Pencarian, penyisipan, dan penghapusan semuanya menjadi O(n). Inilah alasan pohon BST seimbang seperti pohon AVL dan pohon merah-hitam dibuat. Dalam wawancara, selalu sebutkan kasus terburuk ini ketika ditanya tentang kompleksitas BST — mengatakan 'O(log n) rata-rata, O(n) kasus terburuk untuk pohon yang tidak seimbang' menunjukkan pemahaman yang mendalam.
# Inserting 1, 2, 3, 4, 5 into a BST:
# 1
# \
# 2
# \
# 3
# \
# 4
# \
# 5
# This is a right-skewed tree: search is O(n) not O(log n)
root = None
for val in [1, 2, 3, 4, 5]:
root = insert_bst(root, val)
# Verify the skew
node = root
depth = 0
while node:
depth += 1
node = node.right
print(f'Height: {depth}') # 5 = O(n), not O(log n)Menemukan Nilai Minimum dan Maksimum
Dalam BST, nilai minimum selalu berada pada simpul paling kiri (terus bergerak ke kiri hingga mencapai simpul kosong), sedangkan nilai maksimum berada pada simpul paling kanan. Operasi O(h) ini sering digunakan sebagai subrutin dalam penghapusan BST (untuk menemukan penerus dalam-urutan) dan kueri rentang. Menguasai fungsi pembantu ini akan menghemat waktu dalam wawancara.
def find_min(root):
while root.left:
root = root.left
return root
def find_max(root):
while root.right:
root = root.right
return root
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(7)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
root.right.right = TreeNode(9)
print(find_min(root).val) # 1
print(find_max(root).val) # 9Penerus dan Pendahulu Dalam Urutan
Penerus dalam-urutan suatu simpul adalah simpul dengan nilai terkecil yang lebih besar daripada nilai simpul tersebut. Jika simpul memiliki subpohon kanan, penerusnya adalah find_min(node.right). Jika tidak memiliki subpohon kanan, penerusnya adalah leluhur terendah yang subpohon kirinya memuat simpul tersebut. Memahami hal ini sangat penting untuk penghapusan BST dan masalah pengiterasi BST.
def inorder_successor(root, p):
successor = None
while root:
if p.val < root.val:
successor = root # possible successor
root = root.left
else:
root = root.right
return successor
def inorder_predecessor(root, p):
predecessor = None
while root:
if p.val > root.val:
predecessor = root # possible predecessor
root = root.right
else:
root = root.left
return predecessor
root = TreeNode(4)
root.left = TreeNode(2)
root.right = TreeNode(6)
root.left.left = TreeNode(1)
root.left.right = TreeNode(3)
p = root.left # node with val=2
print(inorder_successor(root, p).val) # 3
print(inorder_predecessor(root, p).val) # 1Analisis Kompleksitas Pencarian BST
Kinerja BST sepenuhnya bergantung pada tinggi pohon. Untuk BST seimbang dengan n simpul, tingginya adalah O(log n), sehingga pencarian, penyisipan, dan penghapusan memiliki kompleksitas O(log n). Untuk BST miring, tingginya adalah O(n), sehingga semua operasi memiliki kompleksitas O(n). Python tidak memiliki BST seimbang bawaan (berbeda dari TreeMap milik Java), jadi Anda harus menerapkan AVL atau pohon merah-hitam sendiri, menggunakan sortedcontainers.SortedList, atau mengandalkan tumpukan untuk kasus penggunaan antrean prioritas.
# Python's BST alternatives:
# 1. heapq - min/max heap, O(log n) push/pop
# 2. sortedcontainers.SortedList (third-party, often allowed)
# 3. Manual AVL or Red-Black (rarely required in interviews)
# When interviews say 'use a BST':
# - LeetCode: implement TreeNode-based solution
# - Real interview: mention sortedcontainers or Java TreeMap equivalent
# - O(log n) operations matter when you need ordered access
# For pure insert/lookup without ordering: use dict (O(1) average)
print('Use heap for priority, dict for lookup, BST for ordered range')Penyisipan ke BST: Kasus Khusus
Selalu pastikan penyisipan Anda menangani: pohon kosong (kembalikan simpul baru sebagai akar), nilai duplikat (tentukan apakah akan mengabaikannya, menyisipkannya ke kiri, atau menyisipkannya ke kanan — dan tetap konsisten), serta nilai yang sangat besar atau sangat kecil. Dalam wawancara, nyatakan asumsi Anda tentang duplikat sebelum menulis kode. Konvensi yang paling umum dalam masalah LeetCode adalah semua nilai berbeda, kecuali dinyatakan sebaliknya.
def insert_bst_no_duplicates(root, val):
if not root:
return TreeNode(val)
if val < root.val:
root.left = insert_bst_no_duplicates(root.left, val)
elif val > root.val:
root.right = insert_bst_no_duplicates(root.right, val)
# else: val == root.val -> duplicate, skip
return root
# Test all edge cases:
root = None
root = insert_bst_no_duplicates(root, 5) # empty tree
root = insert_bst_no_duplicates(root, 5) # duplicate
root = insert_bst_no_duplicates(root, 3)
root = insert_bst_no_duplicates(root, 7)
print(root.val, root.left.val, root.right.val) # 5 3 7BST dari Larik Terurut
Membangun BST seimbang berdasarkan tinggi dari larik terurut (LeetCode #108) menggunakan metode bagi-dan-taklukkan: elemen tengah menjadi akar, separuh kiri menjadi subpohon kiri, dan separuh kanan menjadi subpohon kanan. Cara ini menjamin pohon seimbang dengan tinggi O(log n). Kompleksitas waktunya adalah O(n) karena setiap elemen diproses satu kali.
def sorted_array_to_bst(nums):
if not nums:
return None
mid = len(nums) // 2
root = TreeNode(nums[mid])
root.left = sorted_array_to_bst(nums[:mid])
root.right = sorted_array_to_bst(nums[mid+1:])
return root
nums = [-10, -3, 0, 5, 9]
root = sorted_array_to_bst(nums)
print(root.val) # 0 (middle element)
print(root.left.val) # -3
print(root.right.val) # 9Pemeriksaan Singkat
Uji pemahaman Anda tentang konsep Struktur Data & Algoritma — Persiapan Wawancara Pemrograman dari pelajaran ini.
Ringkasan Pelajaran
Dalam pelajaran ini, Anda mempelajari: properti BST (subpohon kiri lebih kecil secara ketat, subpohon kanan lebih besar secara ketat), pencarian dan penyisipan secara rekursif maupun iteratif dalam waktu O(h), serta pohon miring kasus terburuk yang tingginya sama dengan n. Selanjutnya kita membahas penghapusan BST dan tiga kasusnya.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Penyisipan dan Pencarian BST” gratis?
Ya — teks lengkap “Penyisipan dan Pencarian BST” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus DSA Interview Prep, upgrade ke CoddyKit PRO. Kursus DSA Interview Prep mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Penyisipan dan Pencarian BST”?
Implementasikan penyisipan dan pencarian secara rekursif serta iteratif, telusuri jalur dalam pohon untuk berbagai kunci, dan analisis kompleksitas kasus terburuk pada pohon yang tidak seimbang. Kamu berlatih DSA Interview Prep dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai DSA Interview Prep?
Tidak diperlukan pengalaman sebelumnya. DSA Interview Prep di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.
Berapa lama pelajaran “Penyisipan dan Pencarian BST” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran DSA Interview Prep ini?
Ya. Setiap pelajaran DSA Interview Prep menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Penyisipan dan Pencarian BST
- Penghapusan BST: Tiga Kasus
- Memvalidasi BST dan Sifat In-Order
- Elemen ke-K Terkecil, Jumlah Rentang, dan BST menjadi Array Terurut