Anda di halaman 1dari 24

Laporan Analisis dan Desain Algoritma

Search Algorithm

Oleh:
Ach Althaaf Cahya Ramadhan (220535609181)
Anissa Alifia Putri (220535600012)
Ahmad ‘Ammar Musyaffa’ (220535601431)
David Satria Alamsyah (220535610311)
Dhia Rafifah Thifal (220535601315)
Silvia Wulandari Situngkir (230535618282)

Offering A
Kelompok 6

PROGRAM STUDI S1 TEKNIK INFORMATIKA


DEPARTEMEN TEKNIK ELEKTRO DAN INFORMATIKA
FAKULTAS TEKNIK
UNIVERSITAS NEGERI MALANG
2023/2024
PENDAHULUAN

Algoritma pencarian atau yang biasa disebut dengan Search Algorithm adalah
suatu metode atau prosedur yang digunakan untuk menemukan keberadaan atau lokasi
suatu informasi atau elemen tertentu dalam suatu kumpulan data yang diberikan.
Tujuannya adalah untuk menemukan elemen target dalam kumpulan data tersebut.

Algoritma pencarian dapat diterapkan pada berbagai jenis struktur data, seperti
array, daftar (list), graf, pohon, dan berbagai struktur data lainnya. Misalnya, dalam
konteks array, algoritma pencarian akan mencari elemen dalam array tersebut. Dalam
konteks graf, algoritma pencarian dapat digunakan untuk mencari jalur atau node
tertentu dalam graf tersebut.

Setiap algoritma pencarian memiliki kelebihan dan kelemahan tertentu, serta


cocok untuk berbagai jenis situasi. Beberapa faktor yang mempengaruhi pemilihan
algoritma pencarian adalah ukuran data, jenis data, dan kriteria kinerja yang
diinginkan, seperti waktu eksekusi atau penggunaan memori.
Pembahasan Studi Kasus

1. Linear Search
Linear search adalah algoritma pencarian yang digunakan untuk menemukan nilai
tertentu dalam sebuah kumpulan data atau daftar (biasanya dalam bentuk array atau
daftar terurut). Algoritma ini bekerja dengan cara menelusuri setiap elemen satu per
satu dalam urutan sekuensial, mulai dari elemen pertama hingga elemen terakhir,
untuk mencari nilai yang dicari. Dalam linear search, tidak ada asumsi tentang
kumpulan data yang diurutkan atau tidak diurutkan sebelumnya. Ini berarti bahwa
algoritma ini dapat digunakan pada kumpulan data yang tidak terurut sekalipun.
Berikut adalah gambaran sederhana dari cara kerja linear search.

Gambar 1. Proses Linear Search

Linear search bekerja dengan cara menelusuri setiap elemen dalam kumpulan data,
dimulai dari elemen pertama hingga elemen terakhir, secara berurutan. Pada setiap
langkah, algoritma memeriksa apakah nilai yang dicari cocok dengan nilai elemen
saat ini. Jika cocok, pencarian selesai dan indeks elemen tersebut dikembalikan. Jika
tidak cocok, algoritma melanjutkan ke elemen berikutnya. Proses ini terus berlanjut
sampai nilai yang dicari ditemukan atau seluruh kumpulan data telah diperiksa, dan
jika nilai tersebut tidak ditemukan, pencarian menghasilkan hasil 'tidak ditemukan'.
Berikut dibawah ini adalah contoh implementasi kode dengan pendekatan iteratif
dengan bahasa pemrograman python.

def LinearSearch(arr, target):


n = len(arr)
for i in range(n):
if arr[i] == target:
return i
return -1
1) Kompleksitas Waktu

Kode Program Best Case Average Worst Case


Case
def LinearSearch(arr, target):

n = len(arr) 1 1 1
for i in range(n): 1 1 1
if arr[i] == target: 1 n/2 n
return i 1 1 1
return -1 0 0 1

Total 4 3 + n/2 4+n


a) Best Case
Best case algoritma linear search terjadi ketika elemen yang dicari
berada di posisi pertama dalam kumpulan data. Algoritma hanya perlu
membandingkan nilai yang dicari dengan elemen pertama dan
pencarian nilai selesai. Terlihat hasil analisis hanya menghasilkan
konstanta 5, yang berarti analisis asimtotik pada kasus terbaik adalah
Ω(1), karena algoritma hanya memerlukan satu langkah untuk
menemukan elemen yang dicari.
b) Average Case
Average case (rata-rata) linear search terjadi ketika elemen yang dicari
tersebar secara merata di seluruh kumpulan data. Algoritma harus
menelusuri setiap elemen hingga menemukan nilai yang dicari.
Dengan demikian, pada kasus rata-rata algoritma perlu memeriksa
sekitar setengah dari seluruh elemen dalam kumpulan data. Konstanta
3 pada total hasil perhitungan dalam analisis asimtotik dapat
diabaikan/dihilangkan, karena ketika ukuran input menjadi sangat
besar, perbedaan dalam kinerja antara algoritma dengan konstanta yang
berbeda menjadi tidak signifikan. Analisis asimtotik pada kasus
rata-rata adalah O(n/2), yang dalam notasi Big O disederhanakan
menjadi O(n).
c) Worst Case
Worst case algoritma linear search terjadi ketika elemen yang dicari
berada di posisi terakhir dalam kumpulan data atau bahkan tidak ada
dalam kumpulan data sama sekali. Algoritma harus menelusuri seluruh
kumpulan data untuk mencari elemen yang dicari. Analisis asimtotik
pada kasus terburuk adalah O(n), dimana n adalah jumlah total elemen
dalam kumpulan data. Pada kasus terburuk, algoritma perlu memeriksa
setiap elemen dalam kumpulan data untuk menyelesaikan pencarian.
2) Kompleksitas Ruang

Kode Program Analisis Kompleksitas Memori

def LinearSearch(arr, target):

n = len(arr) n =1

for i in range(n): i =1

if arr[i] == target: target = 1

return i

return -1

Total 3

Pada kompleksitas ruang, linear search biasanya tidak memperhitungkan


ruang yang digunakan oleh kumpulan data/array itu sendiri, karena biasanya
diasumsikan bahwa kumpulan data/array tersebut diberikan sebagai input dan
tidak diproduksi oleh algoritma itu sendiri. Sehingga total ruang memori yang
dibutuhkan hanyalah 3 setiap kali fungsi tersebut dijalankan. Ini menandakan
bahwasanya tidak ada pertumbuhan relatif terhadap memori yang digunakan
ketika ukuran masukkan mendekati tak hingga . Oleh karena itu, analisis
asimtotik terhadap penggunaan sumber daya/ruang memori pada algoritma ini
adalah konstan. Dapat ditulis dengan notasi Θ(1), dikarenakan kompleksitas
memori tersebut berada di antara batas bawah (Ω(1)) dan batas atas (O(1)).

3) Kelebihan
a) Sederhana dan mudah dipahami
Algoritma ini mudah dipelajari dan diimplementasikan, bahkan bagi
programmer pemula.
b) Fleksibilitas
Linear search dapat digunakan pada berbagai jenis data, baik yang
terstruktur maupun tidak terstruktur.
c) Efisien untuk data kecil
Linear search cukup efisien untuk dataset kecil dengan jumlah elemen
yang sedikit.
d) Berlaku untuk Kumpulan Data Tidak Terurut
Linear search dapat digunakan pada kumpulan data yang tidak terurut.
Tidak perlu mengurutkan kumpulan data sebelum melakukan pencarian
sehingga dapat menghemat waktu dan usaha.
4) Kekurangan
a) Kompleksitas Waktu Linear
Pada kasus terburuk, kompleksitas waktu linear search adalah O(n),
dimana n adalah jumlah elemen dalam kumpulan data. Ini membuatnya
kurang efisien untuk kumpulan data besar karena algoritma harus
menelusuri semua elemen satu per satu.
b) Tidak Efisien untuk Kumpulan Data Besar
Karena kompleksitas waktu linear search adalah linier, algoritma ini
mungkin tidak efisien untuk kumpulan data besar.
c) Tidak Cocok untuk Kumpulan Data Terurut
Linear search tidak memanfaatkan kumpulan data yang terurut. Dalam
kasus seperti itu, algoritma pencarian biner akan lebih cepat karena
memanfaatkan sifat terurutnya kumpulan data.
2. Binary Search
Binary Search adalah salah satu metode pencarian data dalam sebuah array
yang sudah diurutkan. Proses pencarian dimulai dengan menentukan nilai tengah
(middle) dari array. Jika nilai tengah sama dengan elemen yang dicari, maka
pencarian selesai dan elemen tersebut ditemukan. Jika elemen yang dicari lebih besar
dari nilai tengah, maka pencarian dilanjutkan pada separuh kanan array. Sebaliknya,
jika elemen yang dicari lebih kecil dari nilai tengah, pencarian dilanjutkan pada
separuh kiri array. Proses ini diulangi pada setiap iterasi hingga elemen yang dicari
ditemukan atau seluruh array telah diperiksa.
Langkah perhitungan Binary Search pada data dengan urutan ascending:
1. Buat perulangan dengan menentukan posisi low, dimana posisi ini
menandakan index paling rendah untuk kemudian dapat menentukan posisi
high. Dengan begitu dapat ditemukan posisi mid = (high+low)/2.
2. Melakukan perbandingan pada data yang dicari dengan nilai pada posisi mid.
3. Jika data yang dicari sama dengan nilai mid, data ditemukan, pencarian
berhenti.
4. Jika data yang dicari lebih kecil dari nilai mid maka pencarian dilanjutkan ke
bagian kiri mid untuk membandingkan nilainya sehingga kondisi high berubah
menjadi mid-1 dan posisi low tetap.
5. Jika data yang dicari lebih besar dari nilai mid maka pencarian dilanjutkan ke
bagian kanan mid untuk membandingkan nilainya sehingga kondisi low
berubah menjadi mid+1 dan posisi high tetap.
6. Berikut merupakan contoh ilustrasi Binary Search:

Gambar 2. Ilustrasi Binary Search Tahap Pertama

Gambar diatas menunjukkan pencarian 7 dalam array yang sudah di susun


secara ascending, dengan menerapkan Binary Search maka array akan dicari
nilai low, high, dan mid. Kemudian data 7 yang disimpan dalam variabel X
akan dibandingkan dengan mid. Karena mid=10 dan 7<10 maka pencarian
dilanjutkan ke bagian kiri mid. Seperti pada gambar berikut:
Gambar 3. Ilustrasi Binary Search Tahap Kedua

Gambar diatas menggeser posisi high (mid-1) sehingga didapatkan


mid=(0+1)/2=0, yang artinya mid terletak pada index[0]. Setelah mid
dibandingakan, di mana 7=7 maka data yang dicari sudah ketemu, pencarian
selesai.
Berikut ini adalah contoh implementasi kode dengan pendekatan iteratif dari
algoritma Binary Search menggunakan bahasa pemrograman python.
def binarySearch2(self, L, n, nmin, nmax):
while (nmin <= nmax):
mid = (nmin + nmax) / 2
if n > L[mid]:
nmin = mid + 1
elif n < L[mid]:
nmax = mid - 1
else:
return True
return False

Pada kode program di atas, ‘L’, ‘n’, ‘nmin’, dan ‘nmax’ adalah inisialisasi variabel ‘L’
merupakan array yang sudah diurutkan, ‘n’ adalah elemen yang dicari dalam array
‘L’, ‘nmin’ menjadi indeks paling rendah dalam array yang di proses, dan ‘nmax’
menjadi indeks paling tinggi dalam array yang diproses
Selanjutnya, dilakukan perulangan untuk mulai mencari memanfaatkan
perulangan ‘while’ yang akan terus berlangsung selama ‘nmin’ kurang dari sama
dengan ‘nmax’. Bagian ini akan memastikan bahwa selama rentang waktu yang dapat
diperiksa, pencarian akan terus dilakukan.
Pada baris berikutnya, dilakuakan pencarian posisi mid dengan menghitung
rata-rata dari ‘nmin’ dan ‘nmax’, yaitu ‘mid = (nmin + nmax) / 2’. Jika elemen yang
dicari ‘n’ lebih besar dari nilai yang ada pada posisi mid, maka rentang pencarian akan
berpindah ke bagian kanan mid dengan mengubah ‘nmin’ menjadi ‘mid + 1’.
Sebaliknya, jika elemen yang dicari lebih kecil dari nilai di posisi mid, maka rentang
pencarian akan berpindah ke kiri mid dengan mengubah ‘nmax’ menjadi ‘mid - 1’.
Terakhir, jika yang dicari sama dengan nilai diposisi mid, maka pencarian selesai dan
fungsi akan mengembalikan ‘True’. Secara keseluruhan, jika seluruh rentang telah
diperiksa dan elemen yang dicari tidak ditemukan dimanapun, maka pencarian akan
mengembalikan fungsi ‘False’.
1) Komplekasitas Waktu
Algoritma Best Average Worst
Case Case Case
def binarySearch2(self, L, n, nmin, 0 0 0
nmax):

while (nmin <= nmax): 1 n+1 n+1

mid = (nmin + nmax) / 2 1 n/2 n/2

if n > L[mid]: 1 n n

nmin = mid + 1 1 0 0

elif n < L[mid]: 0 0 n

nmax = mid - 1 0 0 0

else: 0 1 0
return True

return False 0 0 1

TOTAL 4 5(n/2)+2 7(n/2)+2

a) Best Case
Kasus terbaik terjadi ketika pencarian berhenti karena data yang dicari,
ditemukan pada iterasi pertama. Pada program di atas hanya dibutuhkan
pemenuhan pada baris ke dua(‘while (nmin <= nmax):’) sampai baris ke
empat(‘nmin = mid + 1’) untuk memenuhi syarat iterasi pertama Binary Search.
Dimana total statement untuk pemenuhan algoritmanya adalah konstanta
bernilai empat, yang jika dikonfersikan ke notasi asimtotiknya akan menjadi
Ω(1) atau konstan.

b) Averange Case
Pada kasus averange, pencarian akan selalu dibagi dua. Pencarian ini akan
terus dilakukan hingga ditemukan data yang dicari. Pada program di atas,
ditemukan total statement kasus averange sebanyak 5(n/2)+2, bentuk ini juga
dapat ditulis menjadi T(n/2)+k dimana k adalah konstanta, maka pola
identifikasinya dapat dituliskan sebagai berikut:
T(n) = T(n/2)+O(1)
= T(n/2)/2+O(1)+O(1)
2
= T(n/2 )+2 O(1)
3
= T(n/2 )+3 O(1)
4
= T(n/2 )+4 O(1)
.
.
𝑘
=[T(n/2 )+ k * O(1)]
Sehingga didapatkan nilai T(n) sebesar:
𝑘
T(n)=[T(n/2 + k * O(1))]
𝑘
Diasumsikan: n/2 = 1
𝑘
Jika n = 2 , maka k = log n
𝑘
T(N) = [T(n / 2 ) + k * O(1)]
= T (16 / 16) + log n * O(1)
= O (log n)

c) Worst Case
Pada kasus terburuk, data yang dicari tidak dapat ditemukan, bahkan setelah
menjalankan iterasi berulang sampai keseluruhan list diakses, sehingga program akan
mengembalikan nilai statement 1 pada baris terakhir(‘return False’). Total statement
dari kasus terburuk adalah 7(n/2)+2, bentuk ini juga dapat ditulis menjadi
T(n/2)+k dimana k adalah konstanta. Pola identifikasinya untuk diubah
menjadi notasi asimtotik akan sama dengan kasus averange yang
menghasilkan O (log n).

2) Kompleksitas Ruang
Algoritma Kompleksitas Ruang
def binarySearch2(self, L, n,
nmin, nmax): n = 1,
while (nmin <= nmax): nmin = 1,
mid = (nmin + nmax) / 2 nmax = 1,
if n > L[mid]: mid = 1,
nmin = mid + 1
elif n < L[mid]:
nmax = mid - 1
else:
return True
return False

TOTAL 4

Kompleksitas ruang untuk algoritma Binary Search dalam pola iteratif adalah
pertimbangan jumlah memori yang digunakan variabel-variabel selama eksekusi
algoritma. Pada algoritma di atas, variabel-variabel yang digunakan antara lain
‘n’, ‘nmin’, ‘nmax’, dan ‘mid’, yang totalnya bernilai empat konstanta. Semuanya
menggunakan ruang konstan yang tidak bertambah seiring dengan ukuran input
sehingga dapat dinotasikan menjadi O(1).

3) Kelebihan
Kelebihan dari Binary Search adalah pembandingan data yang tidak perlu di
mulai dari awal dan tidak harus dibandingkan seluruhannya, cukup melalui titik
tengah untuk kemudian berjalan sesuai potensi keberadaan data yang dicari.

4) Kekurangan
Implementasi yang mengharuskan data array yang terurut membuat Binary
Search harus mengurutkan dulu data yang acak, sehingga butuh melakukan
sorting terlebih dulu sebelum dilakukan pencarian
3. Depth-First Search
a. Pengertian
Algoritma Depth First Search (DFS) adalah suatu metode pencarian pada
sebuah tree/pohon dengan menelusuri satu cabang sebuah tree sampai menemukan
solusi. Pencarian dilakukan pada satu node dalam setiap level dari yang paling kiri
dan dilanjutkan pada node sebelah kanan. Jika solusi ditemukan maka tidak
diperlukan proses backtracking yaitu penelusuran balik untuk mendapatkan jalur yang
diinginkan.
Cara kerja algoritma Depth First Search yaitu masukan masukan node akar
kedalam sebuah tumpukan. Kemudian ambil simpul pertama pada level paling atas,
jika simpul merupakan solusi pencarian selesai dan hasil dikembalikan. Jika simpul
bukan merupakan solusi, masukan seluruh simpul yang bertetangga dengan simpul
tersebut ke dalam tumpukan. Apabila semua simpul sudah dicek dan antrean kosong,
pencarian selesai dengan mengembalikan hasil solusi tidak ditemukan. Pencarian
diulang dari simpul awal antrean.

b. Kelebihan dan Kekurangan

Kelebihan

● Depth First Search jauh lebih efisien untuk ruang pencarian dengan banyak cabang
karena tidak perlu mengeksekusi semua simpul pada suatu level tertentu pada daftar
open.
● Depth First Search memerlukan memori yang relatif kecil karena node pada lintasan
yang aktif saja yang disimpan.

Kekurangan

● Memungkinkan tidak ditemukannya tujuan yang diharapkan dan hanya akan


mendapatkan satu solusi pada setiap pencarian.
● Terdapat peluang tidak menemukan solusi optimal
● Kemungkinan terjebak pada jalur pencarian yang tidak berguna.

c. Contoh penerapan

1 0
3 1 0

4 3 1 0

3 1 0

5 3 1 0

3 1 0

2 3 1 0

3 1 0

1 0

d. Contoh Kode Program

class Graph:
def __init__(self):
self.graph = {}

def add_edge(self, u, v):


if u not in self.graph:
self.graph[u] = []
self.graph[u].append(v)

def dfs_util(self, v, visited):


visited.add(v)
print(v, end=' ')

for neighbor in self.graph.get(v, []):


if neighbor not in visited:
self.dfs_util(neighbor, visited)

def dfs(self, start):


visited = set()
self.dfs_util(start, visited)
# Contoh penggunaan:
if __name__ == "__main__":
graph = Graph()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 0)
graph.add_edge(2, 3)
graph.add_edge(3, 3)

print("Hasil DFS traversal dari simpul 2:")


graph.dfs(2)

4. Breadth-First Search

Breadth-First Search (BFS) atau Pencarian Breadth-First adalah algoritma


pencarian yang digunakan untuk mencari struktur data pohon guna menemukan node
yang memenuhi kriteria atau properti tertentu. Algoritma ini dimulai dari akar pohon
dan secara bertahap mengeksplorasi semua node yang berada pada tingkat kedalaman
saat ini sebelum melanjutkan ke node pada tingkat kedalaman berikutnya. Dengan
kata lain, algoritma ini secara sistematis menjelajahi semua node pada tingkat yang
sama sebelum melanjutkan ke node pada tingkat selanjutnya.. Hal ini memastikan
bahwa semua node pada tingkat tertentu diperiksa terlebih dahulu sebelum
menjelajahi node pada tingkat kedalaman yang lebih dalam dalam pohon. Berikut
merupakan gambaran dari Algoritma Breadth-First Search.

Gambar Breadth First Search

Cara Kerja dari Breadth-First Algorithm :


- Mulai dari simpul awal (akar pohon) : BFS dimulai dengan memilih simpul
awal atau akar pohon sebagai simpul awal yang akan dieksplorasi terlebih dahulu.

- Mengeksplorasi simpul pada tingkat yang sama : Algoritma ini mengeksplorasi semua
simpul yang terhubung langsung dengan simpul awal terlebih dahulu. Ini dilakukan
dengan mengeksplorasi semua simpul tetangga dari simpul awal.
- Menyimpan daftar simpul yang telah dieksplorasi : Ketika suatu simpul dieksplorasi,
ia ditandai sebagai telah "dikunjungi" atau "dieksplorasi" agar tidak dieksplorasi lagi
dalam langkah-langkah berikutnya.

- Melanjutkan ke tingkat kedalaman berikutnya : Setelah semua simpul pada tingkat


saat ini telah dieksplorasi, BFS akan melanjutkan ke simpul-simpul yang terhubung
dengan simpul pada tingkat tersebut, yang belum dieksplorasi. Ini berarti menjelajahi
simpul-simpul pada tingkat yang lebih dalam dalam pohon.

- Mengulangi proses hingga target ditemukan atau semua simpul telah dieksplorasi :
Langkah-langkah di atas diulangi secara berulang hingga simpul target ditemukan
atau tidak ada lagi simpul yang tersisa untuk dieksplorasi. Hal ini memastikan bahwa
BFS mengeksplorasi semua simpul pada tingkat yang sama sebelum melanjutkan ke
tingkat yang lebih dalam dalam pohon atau graf.

- Menghasilkan jalur terpendek : Setelah target ditemukan, BFS menghasilkan jalur


terpendek dari simpul awal ke target dengan mengikuti jalur dari simpul target ke
simpul awal, menggunakan informasi yang disimpan selama proses pencarian.

Contoh kode program dalam bahasa python :

tree = {"5": ["3", "7"], "3": ["2", "4"], "7": ["8"], "2": [], "4":
["8"], "8": []} #tree is m x n, where m is the number of nodes and n is
the number of edges

def bfs(tree, node, value): # function for BFS


visited = [] # List for visited nodes.
queue = [] # Initialize a queue
visited.append(node)
queue.append(node)

while queue: # Creating loop to visit each node


m = queue.pop(0)
print(m, end=" ")
if m == value:
print("Found " + m)
return

for neighbour in tree[m]:


# print(neighbour)
if neighbour not in visited:
visited.append(neighbour)
queue.append(neighbour)

# Driver Code
print("Following is the Breadth-First Search")
bfs(tree, "5", '7') # function calling
Analisis Kompleksitas Waktu

Statement Best Case Average Worst Case

def bfs(tree, node, value): 0 0 0

visited = [] 1 1 1

queue = [] 1 1 1

visited.append(node) 1 1 1

queue.append(node) 1 1 1

while queue: 1 1 1

m = queue.pop(0) 1 ½v v

print(m, end=" ") 1 ½v v

if m == value: 1 ½v v

print("Found " + m) 1 ½v v

return 1 1 1

for neighbour in tree[m]: 0 ½e 1

if neighbour not in visited: 0 ½e e

visited.append(neighbour) 0 ½e e

queue.append(neighbour) 0 ½e e

Total Kompleksitas Waktu 10 6 + 2v + 7 + 4v + 3e


2e

a. Best Case

Dalam kasus terbaik, kompleksitas waktu untuk setiap operasi adalah


konstan (1), yang berarti setiap operasi membutuhkan waktu yang sama untuk
dieksekusi, tanpa memperhatikan ukuran masukan (jumlah vertex dan edge
dalam tree). Dalam konteks BFS (Breadth-First Search), kasus terbaik terjadi
ketika nilai yang dicari ditemukan pada node awalnya sendiri. Dengan
demikian, algoritma dapat menemukan elemen yang dicari dengan cepat tanpa
perlu melakukan iterasi tambahan atau menjelajahi lebih banyak vertex atau
edge. Oleh karena itu, analisis asimtotik pada kasus terbaik adalah Ω(1),
karena algoritma hanya memerlukan satu langkah untuk menemukan elemen
yang dicari.

b. Average

Dalam analisis kompleksitas waktu untuk kasus rata-rata pada


algoritma BFS, diasumsikan bahwa elemen yang dicari tersebar secara merata
di seluruh kumpulan data, sehingga algoritma harus menelusuri setiap elemen
hingga menemukan nilai yang dicari. Dalam konteks ini, pada kasus rata-rata,
algoritma perlu memeriksa sekitar setengah dari seluruh elemen dalam
kumpulan data tersebut untuk menemukan nilai yang dicari. Oleh karena itu,
kompleksitas waktu pada kasus rata-rata dipengaruhi oleh jumlah node yang
dikunjungi (v) dan jumlah edge (e) dalam tree yang harus diperiksa. Meskipun
dalam analisis tersebut muncul konstanta 6 pada total hasil perhitungan,
namun konstanta tersebut dapat diabaikan atau dihilangkan karena pada kasus
di mana ukuran input menjadi sangat besar, perbedaan dalam kinerja antara
algoritma dengan konstanta yang berbeda menjadi tidak signifikan. Dengan
demikian, dalam analisis asimtotik, kompleksitas waktu pada kasus rata-rata
dapat direpresentasikan sebagai O(2v + 2e), yang kemudian dalam notasi Big
O dapat disederhanakan menjadi O(v + e).

c. Worst Case

Kasus terburuk terjadi ketika nilai yang dicari terletak pada level
terakhir dalam tree, memaksa algoritma untuk menjelajahi semua node dan
edge. Dalam konteks ini, kompleksitas waktu dalam kasus terburuk
memberikan batas atas kinerja algoritma saat menghadapi situasi yang paling
tidak menguntungkan atau ekstrem. Meskipun tidak semua kasus pada
praktiknya akan mencapai tingkat ekstrem ini, namun analisis terhadap kasus
terburuk memberikan gambaran tentang batas kinerja algoritma dalam kondisi
yang paling sulit. Jadi, kompleksitas waktu dalam kasus terburuk,
diekspresikan sebagai O(v + e), menunjukkan bahwa kompleksitas waktu
algoritma bergantung pada jumlah node (v) dan jumlah edge (e) dalam graf
yang harus diperiksa dalam situasi paling buruk. Notasi Big O O(v + e)
memberikan gambaran tentang pertumbuhan waktu eksekusi algoritma dengan
ukuran tree.
Analisis Kompleksitas Ruang

Statement Ruang

visited = [] 1

queue = [] 1

visited.append(node) 1

queue.append(node) 1

while queue: 1

m = queue.pop(0) 1

for neighbour in tree[m]: 1

visited.append(neighbour) v

queue.append(neighbour) v

Total Kompleksitas Ruang 7 + 2v

Analisis kompleksitas ruang pada algoritma BFS yang diberikan


mengidentifikasi penggunaan ruang oleh struktur data tambahan yang
diperlukan selama eksekusi algoritma. Pertama-tama, variabel visited
digunakan untuk menyimpan daftar vertex yang telah dikunjungi, sedangkan
variabel queue digunakan sebagai antrian untuk melacak vertex yang akan
diproses selanjutnya dalam BFS. Setiap kali sebuah vertex ditambahkan ke
dalam visited atau queue, itu membutuhkan ruang konstan O(1). Selanjutnya,
dalam loop yang memeriksa tetangga-tetangga dari setiap vertex yang
diproses, jika sebuah tetangga belum pernah dikunjungi sebelumnya, itu akan
ditambahkan ke dalam visited dan queue.

Dalam analisis ruang, kita mengasumsikan bahwa kita perlu


menyimpan informasi tentang semua vertex yang dikunjungi, sehingga ruang
yang diperlukan untuk menyimpan informasi tentang setiap vertex yang
ditambahkan ke dalam visited dan queue adalah sebanding dengan jumlah
tetangga dari setiap vertex yang diproses. Dengan demikian, total ruang yang
digunakan oleh algoritma BFS adalah 7 + 2v, di mana 7 adalah ruang yang
digunakan untuk variabel visited dan queue, dan 2v adalah ruang yang
digunakan untuk menyimpan informasi tentang v vertex yang dikunjungi.
Dalam analisis kompleksitas ruang, fokusnya adalah pada seberapa banyak
ruang yang diperlukan oleh algoritma untuk menyimpan data tambahan
selama proses eksekusi, dan dalam kasus algoritma BFS ini, kompleksitas
ruangnya bergantung pada jumlah vertex yang dikunjungi (v) dan dapat
dinyatakan sebagai O(v) dalam notasi Big O.
Kelebihan dan Kekurangan
Meskipun kompleksitas waktu BFS yang berbasis tree dapat dikendalikan
dengan baik dalam tree yang memiliki kedalaman terbatas, namun memori yang
diperlukan masih bergantung pada tingkat tree. Meskipun BFS pada tree
membutuhkan memori yang relatif sedikit, tree dengan tingkat yang besar dapat
membutuhkan banyak memori karena jumlah simpul yang harus disimpan dalam
antrian juga tergantung pada tingkat tree.

5. Interval Search

Interval sendiri merupakan konsep matematika yang merepresentasikan


rentang antara dua titik dalam sebuah hal tertentu, dalam matematika interval sering
digunakan untuk menyatakan kumpulan nilai yang terletak diantara dua nilai tertentu.

Dalam hal ini Interval searh algoritma adalah sebuah search algoritm, tetapi
fokusnya lebih dikhususkan pada search interval (pencarian interval) dalam kumpulan
interval yang mana pencarian interval tersebut memenuhi kriteria. Hal ini merupakan
perbedaan dari pencarian algoritm secara umum yang mana mencari elemen tunggal
dalam kumpulan data.

Interval search berguna Ketika kita memiliki beberapa kumpulan interval dan
perlu untuk menemukan interval yang beririsan dengan interval yang kita miliki , atau
juga mencari interval yang mencakup nilai tertentu. Contoh penggunaanya terdapat
pada pemrosesan rentang waktu, pencarian jadwal, dan pemrosesan data spasial, pada
hal ini saya akan memberikan contoh implementasi search algorithm menggunakan
pendekatan biner, serta menganalisis kompleksitas waktu dan efisiensi dari code
program tersebut

def interval_search(intervals, x):


intervals.sort()

if not intervals:
return -1

min_lower_bound = intervals[0][0]
max_upper_bound = intervals[-1][1]

if x < min_lower_bound or x > max_upper_bound:


return -1

left, right = 0, len(intervals)

while left < right:


mid = (left + right) // 2
if intervals[mid][0] <= x <= intervals[mid][1]:
return mid
elif intervals[mid][1] < x:
left = mid + 1
else:
right = mid

return left
Pada code diatas adalah code program search algoritm menggunakan pendekatan
biner, yang mana cara pengeksekusian program tersebut berawal dari pengurutan nilai
interval yang kita miliki. Setelah selesai mengurutkan, program akan melanjutkan dengan
pencarian biner dimana dalam langkah ini mencari nilai ‘x’ diantara interval, dimana nilai ‘x’
ini adalah nilai yang ingin kita cari, pencarian biner ini menggunakan metode pembagian dan
pengecekan di tengah tengah list interval. Setelah itu, setiap iterasi membagi interavl menjadi
dua bagian dan memeriksan apakah nilai ‘x’ berada dalam interval tersebut. Jika nilai ‘x’
berada dalam nilai interval yang berada ditengah, maka proses akan selesai, jika nilai’x’ tidak
terdapat pada interval tersebut pencarian akan dilanjutkan keinterval kiri atau kanan,
tergantung pada nilai ‘x’ lebih besar atau lebih kecil(dibandingkan) dengan interval tengah,
jika lebih besar maka pencarian akan dilanjutkan pada interval kanan, jka lebih kecil maka
akan dilanjutkan pada interval kiri, hingga nilai ‘x’ ditemukan pada indeks ke berapa.

Kompleksitas waktu ;

def interval_search(intervals, x): Kompleksitas waktu

intervals.sort() O(n log n)

if not intervals: O(n)


return -1
min_lower_bound = intervals[0][0] O(1)

max_upper_bound = intervals[-1][1] O(1)

if x < min_lower_bound or x > O(1)


max_upper_bound:
return -1
left, right = 0, len(intervals) O(1)

while left < right: O(1)

mid = (left + right) // 2 O(1)

if intervals[mid][0] <= x <= O(1)


intervals[mid][1]:
return mid
elif intervals[mid][1] < x: O(1)
left = mid + 1
else: O(1)
right = mid
return left O(n)

= O(n log n) + O(n) + O(1) + O(1) + O(1) + O(1) + O(1) + O(1) . O(1) . O(1) . O(1) + O(n)
= Max O(n log n) + O(n) + O(1) + O(1) + O(1) + O(1) + O(1) + O(1) + O(n)

= O(n log n)

maka code program diatas mempunyai kompleksitas waktu dalam asimtotik yaitu algoritma
n log n

kompleksitas ruang :

algoritm Kompleksitas Ruang

def interval_search(intervals, x): n

intervals.sort()

if not intervals:
return -1
min_lower_bound = intervals[0][0] 1

max_upper_bound = intervals[-1][1] 1

if x < min_lower_bound or x >


max_upper_bound:
return -1
left, right = 0, len(intervals) 1

while left < right:

mid = (left + right) // 2 1

if intervals[mid][0] <= x <=


intervals[mid][1]:
return mid
elif intervals[mid][1] < x:
left = mid + 1
else:
right = mid
return left

Total 4+n

6. Bidirectional Search
Penjelasan

Bidirectional Search adalah sebuah algoritma pencarian yang melakukan pencarian


dari dua arah sekaligus. Algoritma ini biasanya digunakan untuk mencari jalur terpendek
antara dua titik dalam struktur data grafik. Algoritma Bidirectional Search bekerja dengan
cara menjalankan dua pencarian secara bersamaan: satu dari titik awal dan satu dari titik
akhir. Proses pencarian ini dilakukan secara bergantian, satu langkah di setiap arah pada
setiap iterasi. Keuntungan utama dari menggunakan Bidirectional Search adalah bahwa hal
ini dapat mengurangi waktu pencarian secara signifikan dibandingkan dengan pencarian dari
satu arah saja, terutama dalam kasus ketika grafik sangat besar atau ketika kita hanya tertarik
pada jalur terpendek antara dua titik.

Contoh kode program :

def bidirectional_search(list, target):


loop = 1
start = 0
end = len(lst) - 1

while start <= end:


print("Nilai Depan:", start, "|", "Loop ke:", loop)
print("Nilai Delakang:", end, "|", "Loop ke:", loop)
if lst[start] == target:
return start
elif lst[end] == target:
return end
start += 1
end -= 1
loop += 1
return -1

Kompleksitas Ruang

VARIABLE JUMLAH
start 1

end 1

list n

target 1

return 1

TOTAL 4+n

Dalam algoritma yang dibuat terdapat empat variabel yang digunakan dalam bidirectional
search dalam suatu list, yaitu list dengan jumlah sebanyak n (sepanjang jumlah list), target
untuk objek yang dicari, start dan end untuk perulangan dalam algoritma ini. Sehingga total
kompleksitas ruang yang dibutuhkan adalah sebanyak n + 4.

Kompleksitas Waktu

ALGORITMA Best Average Worst


Case Case Case
def bidirectional_search(list, 0 0 0
target):

start = 0 1 1 1
end = len(lst) - 1 1 1 1
while start <= end: 1 1 1
if lst[start] == target: 1 n/4 n/2
return start 1 1 0
elif lst[end] == target: 1 n/4 n/2
return end 1 1 0
start += 1 0 1 1
end -= 1 0 1 1
return -1 0 1 1
7 8+(n/4)^2 6+(n/2)^2

Dalam analisis kompleksitas waktu algoritma Bidirectional Search yang telah dilakukan,
diketahui bahwa algoritma tersebut memiliki 3 kondisi yaitu best-case, average-case, dan
worst-case. Kondisi pertama best-case memiliki total kompleksitas waktu 7 yang terjadi jika
operasi pencarian elemen pada suatu data terurut dilakukan, dan elemen yang dicari tepat
berada pada posisi pertama atau indeks ke-0 dari data tersebut. Dalam skenario ini, algoritma
pencarian dapat menemukan elemen target tanpa harus mengecek elemen-elemen tambahan,
sehingga mencapai kompleksitas waktu O(1), yang merupakan kasus terbaik dalam hal
efisiensi pencarian. Kemudian pada kondisi kedua average-case memiliki total 8 + (n/4)2
yang merupakan kasus rata-rata terjadi antara best case dan worst-case. Terakhir kondisi
worst-case memiliki total kompleksitas waktu 6 + (n/2)2, dalam kondisi ini terjadi ketika
operasi pencarian elemen pada suatu data terurut dilakukan, dan elemen yang dicari berada
pada posisi terakhir atau indeks ke-(n-1) dari data tersebut.

Kompleksitas Asimtotik

STATEMENT NOTASI
ASIMTOTIK
def bidirectional_search(list, target):

start = 0 O(1)

end = len(lst) - 1 O(1)

while start <= end: O(N/2)

if lst[start] == target:

return start
O(1)
elif lst[end] == target:

return end

start += 1
O(1)
end -= 1

return -1 O(1)
Algoritma Bidirectional Search memiliki kompleksitas waktu asimptotik O(n) pada kasus
terburuk. Namun, pada kasus rata-rata, algoritma ini lebih efisien dengan kompleksitas waktu
asimptotik O(n/2).

Anda mungkin juga menyukai