Anda di halaman 1dari 42

BAB 1: ANALISIS ALGORITMA

1. Apakah Itu Algoritma

Ditinjau dari asal-usul katanya, kata Algoritma sendiri mempunyai sejarah yang aneh. Orang hanya
menemukan kata algorism yang berarti proses menghitung dengan angka arab. Anda dikatakan algorist
jika Anda menghitung menggunakan angka arab. Para ahli bahasa berusaha menemukan asal kata ini
namun hasilnya kurang memuaskan. Akhirnya para ahli sejarah matematika menemukan asal kata
tersebut yang berasal dari nama penulis buku arab yang terkenal yaitu Abu Ja’far Muhammad Ibnu
Musa Al-Khuwarizmi. Al-Khuwarizmi dibaca orang barat menjadi Algorism. Al-Khuwarizmi menulis buku
yang berjudul Kitab Al Jabar Wal-Muqabala yang artinya “Buku pemugaran dan pengurangan” (The book
of restoration and reduction). Dari judul buku itu kita juga memperoleh akar kata “Aljabar” (Algebra).
Perubahan kata dari algorism menjadi algorithm muncul karena kata algorism sering dikelirukan dengan
arithmetic, sehingga akhiran –sm berubah menjadi –thm. Karena perhitungan dengan angka Arab sudah
menjadi hal yang biasa, maka lambat laun kata algorithm berangsur-angsur dipakai sebagai metode
perhitungan (komputasi) secara umum, sehingga kehilangan makna kata aslinya. Dalam bahasa
Indonesia, kata algorithm diserap menjadi algoritma.

2. Definisi Algoritma

“Algoritma adalah urutan langkah-langkah logis penyelesaian masalah yang disusun secara sistematis
dan logis”. Kata logis merupakan kata kunci dalam algoritma. Langkah-langkah dalam algoritma harus
logis dan harus dapat ditentukan bernilai salah atau benar. Dalam beberapa konteks, algoritma adalah
spesifikasi urutan langkah untuk melakukan pekerjaan tertentu. Pertimbangan dalam pemilihan
algoritma adalah, pertama, algoritma haruslah benar. Artinya algoritma akan memberikan keluaran yang
dikehendaki dari sejumlah masukan yang diberikan. Tidak peduli sebagus apapun algoritma, kalau
memberikan keluaran yang salah, pastilah algoritma tersebut bukanlah algoritma yang baik.

Pertimbangan kedua yang harus diperhatikan adalah kita harus mengetahui seberapa baik hasil yang
dicapai oleh algoritma tersebut. Hal ini penting terutama pada algoritma untuk menyelesaikan masalah
yang memerlukan aproksimasi hasil (hasil yang hanya berupa pendekatan). Algoritma yang baik harus
mampu memberikan hasil yang sedekat mungkin dengan nilai yang sebenarnya.

Ketiga adalah efisiensi algoritma. Efisiensi algoritma dapat ditinjau dari 2 hal yaitu efisiensi waktu dan
memori. Meskipun algoritma memberikan keluaran yang benar (paling mendekati), tetapi jika kita harus
menunggu berjam-jam untuk mendapatkan keluarannya, algoritma tersebut biasanya tidak akan
dipakai, setiap orang menginginkan keluaran yang cepat. Begitu juga dengan memori, semakin besar
memori yang terpakai maka semakin buruklah algoritma tersebut. Dalam kenyataannya, setiap orang
bisa membuat algoritma yang berbeda untuk menyelesaikan suatu permasalahan, walaupun terjadi
perbedaan dalam menyusun algoritma, tentunya kita mengharapkan keluaran yang sama. Jika terjadi
demikian, carilah algoritma yang paling efisien dan cepat.

3. Beda Algoritma dan Program

Program adalah kumpulan pernyataan komputer, sedangkan metode dan tahapan sistematis dalam
program adalah algoritma. Program ditulis dengan menggunakan bahasa pemrograman. Jadi bisa
disebut bahwa program adalah suatu implementasi dari bahasa pemrograman. Beberapa pakar
memberi formula bahwa :
Program = Algoritma + Bahasa (Struktur Data)

Bagaimanapun juga struktur data dan algoritma berhubungan sangat erat pada sebuah program.
Algoritma yang baik tanpa pemilihan struktur data yang tepat akan membuat program menjadi kurang
baik, demikian juga sebaliknya.

Pembuatan algoritma mempunyai banyak keuntungan di antaranya :

Pembuatan atau penulisan algoritma tidak tergantung pada bahasa pemrograman manapun, artinya
penulisan algoritma independen dari bahasa pemrograman dan komputer yang melaksanakannya.

Notasi algoritma dapat diterjemahkan ke dalam berbagai bahasa pemrograman.

Apapun bahasa pemrogramannya, output yang akan dikeluarkan sama karena algoritmanya sama.

Beberapa hal yang perlu diperhatikan dalam membuat algoritma :

Teks algoritma berisi deskripsi langkah-langkah penyelesaian masalah. Deskripsi tersebut dapat ditulis
dalam notasi apapun asalkan mudah dimengerti dan dipahami.

Tidak ada notasi yang baku dalam penulisan teks algoritma seperti notasi bahasa pemrograman. Notasi
yang digunakan dalam menulis algoritma disebut notasi algoritmik.

Setiap orang dapat membuat aturan penulisan dan notasi algoritmik sendiri. Hal ini dikarenakan teks
algoritma tidak sama dengan teks program. Namun, supaya notasi algoritmik mudah ditranslasikan ke
dalam notasi bahasa pemrograman tertentu, maka sebaiknya notasi algoritmik tersebut
berkorespondensi dengan notasi bahasa pemrograman secara umum.

Notasi algoritmik bukan notasi bahasa pemrograman, karena itu pseudocode dalam notasi algoritmik
tidak dapat dijalankan oleh komputer. Agar dapat dijalankan oleh komputer, pseudocode dalam notasi
algoritmik harus ditranslasikan atau diterjemahkan ke dalam notasi bahasa pemrograman yang dipilih.
Perlu diingat bahwa orang yang menulis program sangat terikat dalam aturan tata bahasanya dan
spesifikasi mesin yang menjalannya.

Algoritma sebenarnya digunakan untuk membantu kita dalam mengkonversikan suatu permasalahan ke
dalam bahasa pemrograman.

Algoritma merupakan hasil pemikiran konseptual, supaya dapat dilaksanakan oleh komputer, algoritma
harus ditranslasikan ke dalam notasi bahasa pemrograman. Ada beberapa hal yang harus diperhatikan
pada translasi tersebut, yaitu :

a. Pendeklarasian variabel

Untuk mengetahui dibutuhkannya pendeklarasian variabel dalam penggunaan bahasa pemrograman


apabila tidak semua bahasa pemrograman membutuhkannya.

b. Pemilihan tipe data

Apabila bahasa pemrograman yang akan digunakan membutuhkan pendeklarasian variabel maka perlu
hal ini dipertimbangkan pada saat pemilihan tipe data.

c. Pemakaian instruksi-instruksi
Beberapa instruksi mempunyai kegunaan yang sama tetapi masing-masing memiliki kelebihan dan
kekurangan yang berbeda.

d. Aturan sintaksis

Pada saat menuliskan program kita terikat dengan aturan sintaksis dalam bahasa pemrograman yang
akan digunakan.

e. Tampilan hasil

Pada saat membuat algoritma kita tidak memikirkan tampilan hasil yang akan disajikan. Hal-hal teknis ini
diperhatikan ketika mengkonversikannya menjadi program.

f. Cara pengoperasian compiler atau interpreter.

Bahasa pemrograman yang digunakan termasuk dalam kelompok compiler atau interpreter.

4. Algoritma Merupakan Jantung Ilmu Informatika

Algoritma adalah jantung ilmu komputer atau informatika. Banyak cabang ilmu komputer yang
mengarah ke dalam terminologi algoritma. Namun, jangan beranggapan algoritma selalu identik dengan
ilmu komputer saja. Dalam kehidupan sehari-hari pun banyak terdapat proses yang dinyatakan dalam
suatu algoritma. Cara-cara membuat kue atau masakan yang dinyatakan dalam suatu resep juga dapat
disebut sebagai algoritma. Pada setiap resep selalu ada urutan langkah-langkah membuat masakan. Bila
langkah-langkahnya tidak logis, tidak dapat dihasilkan masakan yang diinginkan. Ibu-ibu yang mencoba
suatu resep masakan akan membaca satu per satu langkah-langkah pembuatannya lalu ia mengerjakan
proses sesuai yang ia baca. Secara umum, pihak (benda) yang mengerjakan proses disebut pemroses
(processor). Pemroses tersebut dapat berupa manusia, komputer, robot atau alat-alat elektronik
lainnya. Pemroses melakukan suatu proses dengan melaksanakan atau “mengeksekusi” algoritma yang
menjabarkan proses tersebut.

Algoritma adalah deskripsi dari suatu pola tingkah laku yang dinyatakan secara primitif yaitu aksi-aksi
yang didefenisikan sebelumnya dan diberi nama, dan diasumsikan sebelumnya bahwa aksi-aksi tersebut
dapat kerjakan sehingga dapat menyebabkan kejadian.

Melaksanakan algoritma berarti mengerjakan langkah-langkah di dalam algoritma tersebut. Pemroses


mengerjakan proses sesuai dengan algoritma yang diberikan kepadanya. Juru masak membuat kue
berdasarkan resep yang diberikan kepadanya, pianis memainkan lagu berdasarkan papan not balok.
Karena itu suatu algoritma harus dinyatakan dalam bentuk yang dapat dimengerti oleh pemroses. Jadi
suatu pemroses harus:

Mengerti setiap langkah dalam algoritma.

Mengerjakan operasi yang bersesuaian dengan langkah tersebut.

5. Mekanisme Pelaksanaan Algoritma oleh Pemroses

Komputer hanyalah salah satu pemroses. Agar dapat dilaksanakan oleh komputer, algoritma harus
ditulis dalam notasi bahasa pemrograman sehingga dinamakan program. Jadi program adalah
perwujudan atau implementasi teknis algoritma yang ditulis dalam bahasa pemrograman tertentu
sehingga dapat dilaksanakan oleh komputer.

Kata “algoritma” dan “program” seringkali dipertukarkan dalam penggunaannya. Misalnya ada orang
yang berkata seperti ini: “program pengurutan data menggunakan algoritma selection sort”. Atau
pertanyaan seperti ini: “bagaimana algoritma dan program menggambarkan grafik tersebut?”. Jika Anda
sudah memahami pengertian algoritma yang sudah disebutkan sebelum ini, Anda dapat membedakan
arti kata algoritma dan program. Algoritma adalah langkah-langkah penyelesaikan masalah, sedangkan
program adalah realisasi algoritma dalam bahasa pemrograman. Program ditulis dalam salah satu
bahasa pemrograman dan kegiatan membuat program disebut pemrograman (programming). Orang
yang menulis program disebut pemrogram (programmer). Tiap-tiap langkah di dalam program disebut
pernyataan atau instruksi. Jadi, program tersusun atas sederetan instruksi. Bila suatu instruksi
dilaksanakan, maka operasi-operasi yang bersesuaian dengan instruksi tersebut dikerjakan komputer.

Secara garis besar komputer tersusun atas empat komponen utama yaitu, piranti masukan, piranti
keluaran, unit pemroses utama, dan memori. Unit pemroses utama (Central Processing Unit – CPU)
adalah “otak” komputer, yang berfungsi mengerjakan operasi-operasi dasar seperti operasi
perbandingan, operasi perhitungan, operasi membaca, dan operasi menulis. Memori adalah komponen
yang berfungsi menyimpan atau mengingatingat.

Yang disimpan di dalam memori adalah program (berisi operasi-operasi yang akan dikerjakan oleh CPU)
dan data atau informasi (sesuatu yang diolah oleh operasi-operasi). Piranti masukan dan keluaran (I/O
devices) adalah alat yang memasukkan data atau program ke dalam memori, dan alat yang digunakan
komputer untuk mengkomunikasikan hasil-hasil aktivitasnya. Contoh piranti masukan antara lain, papan
kunci (keyboard), pemindai (scanner), dan cakram (disk). Contoh piranti keluaran adalah, layar peraga
(monitor), pencetak (printer), dan cakram.

Mekanisme kerja keempat komponen di atas dapat dijelaskan sebagai berikut. Mula-mula program
dimasukkan ke dalam memori komputer. Ketika program dilaksanakan (execute), setiap instruksi yang
telah tersimpan di dalam memori dikirim ke CPU. CPU mengerjakan operasioperasi yang bersesuaian
dengan instruksi tersebut. Bila suatu operasi memerlukan data, data dibaca dari piranti masukan,
disimpan di dalam memori lalu dikirim ke CPU untuk operasi yang memerlukannya tadi. Bila proses
menghasilkan keluaran atau informasi, keluaran disimpan ke dalam memori, lalu memori menuliskan
keluaran tadi ke piranti keluaran (misalnya dengan menampilkannya di layar monitor).

6. Belajar Memprogram dan Belajar Bahasa Pemrograman

Belajar memprogram tidak sama dengan belajar bahasa pemrograman. Belajar memprogram adalah
belajar tentang metodologi pemecahan masalah, kemudian menuangkannya dalam suatu notasi
tertentu yang mudah dibaca dan dipahami. Sedangkan belajar bahasa pemrograman berarti belajar
memakai suatu bahasa aturan-aturan tata bahasanya, pernyataan-pernyataannya, tata cara
pengoperasian compiler-nya, dan memanfaatkan pernyataan-pernyataan tersebut untuk membuat
program yang ditulis hanya dalam bahasa itu saja. Sampai saat ini terdapat puluhan bahasa pemrogram,
antara lain bahasa rakitan (assembly), Fortran, Cobol, Ada, PL/I, Algol, Pascal, C, C++, Basic, Prolog, LISP,
PRG, bahasabahasa simulasi seperti CSMP, Simscript, GPSS, Dinamo. Berdasarkan terapannya, bahasa
pemrograman dapat digolongkan atas dua kelompok besar :

Bahasa pemrograman bertujuan khusus. Yang termasuk kelompok ini adalah Cobol (untuk terapan bisnis
dan administrasi). Fortran (terapan komputasi ilmiah), bahasa rakitan (terapan pemrograman mesin),
Prolog (terapan kecerdasan buatan), bahasa-bahasa simulasi, dan sebagainya.

Bahasa perograman bertujuan umum, yang dapat digunakan untuk berbagai aplikasi. Yang termasuk
kelompok ini adalah bahasa Pascal, Basic dan C. Tentu saja pembagian ini tidak kaku.
Bahasabahasabertujuan khusus tidak berarti tidak bisa digunakan untuk aplikasi lain. Cobol misalnya,
dapat juga digunakan untuk terapan ilmiah, hanya saja kemampuannya terbatas. Yang jelas,
bahasabahasa pemrograman yang berbeda dikembangkan untuk bermacam-macam terapan yang
berbeda pula.

Berdasarkan pada apakah notasi bahasa pemrograman lebih “dekat” ke mesin atau ke bahasa manusia,
maka bahasa pemrograman dikelompokkan atas dua macam :

Bahasa tingkat rendah. Bahasa jenis ini dirancang agar setiap instruksinya langsung dikerjakan oleh
komputer, tanpa harus melalui penerjemah (translator). Contohnya adalah bahasa mesin. CPU
mengambil instruksi dari memori, langsung mengerti dan langsung mengerjakan operasinya. Bahasa
tingkat rendah bersifat primitif, sangat sederhana, orientasinya lebih dekat ke mesin, dan sulit dipahami
manusia. Sedangkan bahasa rakitan dimasukkan ke dalam kelompok ini karena alasan notasi yang
dipakai dalam bahasa ini lebih dekat ke mesin, meskipun untuk melaksanakan instruksinya masih perlu
penerjemahan ke dalam bahasa mesin.

Bahasa tingkat tinggi, yang membuat pemrograman lebih mudah dipahami, lebih “manusiawi”, dan
berorientasi ke bahasa manusia (bahasa Inggris). Hanya saja, program dalam bahasa tingkat tinggi tidak
dapat langsung dilaksanakan oleh komputer. Ia perlu diterjemahkan terlebih dahulu oleh sebuah
translator bahasa (yang disebut kompilator atau compiler) ke dalam bahasa mesin sebelum akhirnya
dieksekusi oleh CPU. Contoh bahasa tingkat tinggi adalah Pascal, PL/I, Ada, Cobol, Basic, Fortran, C, C++,
dan sebagainya.
Bahasa pemrograman bisa juga dikelompokkan berdasarkan pada tujuan dan fungsinya. Di antaranya
adalah :

7. Menilai Sebuah Algoritma

Ketika manusia berusaha memecahkan masalah, metode atau teknik yang digunakan untuk
memecahkan masalah itu ada kemungkinan bisa banyak (tidak hanya satu). Dan kita memilih mana yang
terbaik di antara teknikteknik itu. Hal ini sama juga dengan algoritma, yang memungkinkan suatu
permasalahan dipecahkan dengan metode dan logika yang berlainan. Yang menjadi pertanyaan adalah
bagaimana mengukur mana algoritma yang terbaik?. Beberapa persyaratan untuk menjadi algoritma
yang baik adalah :

Tingkat kepercayaannya tinggi (realibility). Hasil yang diperoleh dari proses harus berakurasi tinggi dan
benar.

Pemrosesan yang efisien (cost rendah). Proses harus diselesaikan secepat mungkin dan frekuensi
kalkulasi yang sependek mungkin.

Sifatnya general. Bukan sesuatu yang hanya untuk menyelesaikan satu kasus saja, tapi juga untuk kasus
lain yang lebih general.

Bisa dikembangkan (expandable). Haruslah sesuatu yang dapat kita kembangkan lebih jauh berdasarkan
perubahan requirement yang ada.

Mudah dimengerti. Siapapun yang melihat, dia akan bisa memahami algoritma Anda. Susah
dimengertinya suatu program akan membuat susah di-maintenance (kelola).

Portabilitas yang tinggi (portability). Bisa dengan mudah diimplementasikan di berbagai platform
komputer.
Precise (tepat, betul, teliti). Setiap instruksi harus ditulis dengan seksama dan tidak ada keragu-raguan,
dengan demikian setiap instruksi harus dinyatakan secara eksplisit dan tidak ada bagian yang
dihilangkan karena pemroses dianggap sudah mengerti. Setiap langkah harus jelas dan pasti.

Contoh : Tambahkan 1 atau 2 pada x.

Instruksi di atas terdapat keraguan.

Jumlah langkah atau instruksi berhingga dan tertentu. Artinya, untuk kasus yang sama banyaknya,
langkah harus tetap dan tertentu meskipun datanya berbeda.

Efektif. Tidak boleh ada instruksi yang tidak mungkin dikerjakan oleh pemroses yang akan
menjalankannya.

Contoh : Hitung akar 2 dengan presisi sempurna.

Instruksi di atas tidak efektif, agar efektif instruksi tersebut diubah.

Misal : Hitung akar 2 sampai lima digit di belakang koma.

Harus terminate. Jalannya algoritma harus ada kriteria berhenti. Pertanyaannya adalah apakah bila
jumlah instruksinya berhingga maka pasti terminate?

Output yang dihasilkan tepat. Jika langkah-langkah algoritmanya logis dan diikuti dengan seksama maka
dihasilkan output yang diinginkan.

Sedangkan kriteria Algoritma menurut Donald E. Knuth adalah :

Input: algoritma dapat memiliki nol atau lebih inputan dari luar.

Output: algoritma harus memiliki minimal satu buah output keluaran.

Definiteness (pasti): algoritma memiliki instruksi-instruksi yang jelas dan tidak ambigu.

Finiteness (ada batas): algoritma harus memiliki titik berhenti (stopping role).

Effectiveness (tepat dan efisien): algoritma sebisa mungkin harus dapat dilaksanakan dan efektif. Contoh
instruksi yang tidak efektif adalah: A = A + 0 atau A = A * 1

Namun ada beberapa program yang memang dirancang untuk unterminatable : contoh Sistem Operasi.

8. Penyajian Algoritma

Penyajian algoritma secara garis besar bisa dalam 2 bentuk penyajian yaitu tulisan dan gambar.
Algoritma yang disajikan dengan tulisan yaitu dengan struktur bahasa tertentu (misalnya bahasa
Indonesia atau bahasa Inggris) dan pseudocode. Pseudocode adalah kode yang mirip dengan kode
pemrograman yang sebenarnya seperti Pascal, atau C, sehingga lebih tepat digunakan untuk
menggambarkan algoritma yang akan dikomunikasikan kepada pemrogram. Sedangkan algoritma
disajikan dengan gambar, misalnya dengan flowchart. Secara umum, pseudocode mengekspresikan ide-
ide secara informal dalam proses penyusunan algoritma. Salah satu cara untuk menghasilkan kode
pseudo adalah dengan meregangkan aturan-aturan bahasa formal yang dengannya versi akhir dari
algoritma akan diekspresikan. Pendekatan ini umumnya digunakan ketika bahasa pemrograman yang
akan digunakan telah diketahui sejak awal.

Flowchart merupakan gambar atau bagan yang memperlihatkan urutan dan hubungan antar proses
beserta pernyataannya. Gambaran ini dinyatakan dengan simbol. Dengan demikian setiap simbol
menggambarkan proses tertentu. Sedangkan antara proses digambarkan dengan garis penghubung.
Dengan menggunakan flowchart akan memudahkan kita untuk melakukan pengecekan bagian-bagian
yang terlupakan dalam analisis masalah. Di

samping itu flowchart juga berguna sebagai fasilitas untuk berkomunikasi antara pemrogram yang
bekerja dalam tim suatu proyek.

Ada dua macam flowchart yang menggambarkan proses dengan komputer, yaitu :

Flowchart sistem yaitu bagan dengan simbol-simbol tertentu yang menggambarkan urutan prosedur dan
proses suatu file dalam suatu media menjadi file di dalam media lain, dalam suatu sistem pengolahan
data. Beberapa contoh Flowchart sistem:

Flowchart program yaitu bagan dengan simbol-simbol tertentu yang menggambarkan urutan proses dan
hubungan antar proses secara mendetail di dalam suatu program.

Kaidah-Kaidah Umum Pembuatan Flowchart Program

Dalam pembuatan flowchart Program tidak ada rumus atau patokan yang bersifat mutlak. Karena
flowchart merupakan gambaran hasil pemikiran dalam menganalisis suatu masalah dengan komputer.
Sehingga flowchart yang dihasilkan dapat bervariasi antara satu pemrogram dengan yang lainnya.
Namun secara garis besar setiap pengolahan selalu terdiri atas 3 bagian utama, yaitu :

Input,

Proses pengolahan dan

Output
Untuk pengolahan data dengan komputer, urutan dasar pemecahan suatu masalah:

START, berisi pernyataan untuk persiapan peralatan yang diperlukan sebelum menangani pemecahan
persoalan.

READ, berisi pernyataan kegiatan untuk membaca data dari suatu peralatan input.

PROSES, berisi kegiatan yang berkaitan dengan pemecahan persoalan sesuai dengan data yang dibaca.

WRITE, berisi pernyataan untuk merekam hasil kegiatan ke peralatan output.

END, mengakhiri kegiatan pengolahan.

Walaupun tidak ada kaidah-kaidah yang baku dalam penyusunan flowchart, namun ada beberapa
anjuran :

Hindari pengulangan proses yang tidak perlu dan logika yang berbelit sehingga jalannya proses menjadi
singkat.

Jalannya proses digambarkan dari atas ke bawah dan diberikan tanda panah untuk memperjelas.

Sebuah flowchart diawali dari satu titik START dan diakhiri dengan END.

Berikut merupakan beberapa contoh simbol flowchart yang disepakati oleh dunia pemrograman :
Untuk memahami lebih dalam mengenai flowchart ini, akan diambil sebuah kasus sederhana.

Kasus : Buatlah sebuah rancangan program dengan menggunakan flowchart, mencari luas persegi
panjang.

Solusi : Perumusan untuk mencari luas persegi panjang adalah :

L=p.l

di mana, L adalah Luas persegi panjang, p adalah panjang persegi, dan l adalah lebar persegi.

Keterangan :

Simbol pertama menunjukkan dimulainya sebuah program.

Simbol kedua menunjukkan bahwa input data dari p dan l.

Data dari p dan l akan diproses pada simbol ketiga dengan menggunakan perumusan L = p. l.

Simbol keempat menunjukkan hasil output dari proses dari simbol ketiga.

Simbol kelima atau terakhir menunjukkan berakhirnya program dengan tanda End.

9. Struktur Dasar Algoritma

Algoritma berisi langkah-langkah penyelesaian suatu masalah. Langkah-langkah tersebut dapat berupa
runtunan aksi (sequence), pemilihan aksi (selection), pengulangan aksi (iteration) atau kombinasi dari
ketiganya. Jadi struktur dasar pembangunan algoritma ada tiga, yaitu:

Struktur Runtunan

Digunakan untuk program yang pernyataannya sequential atau urutan.

Struktur Pemilihan

Digunakan untuk program yang menggunakan pemilihan atau penyeleksian kondisi.


Struktur Perulangan

Digunakan untuk program yang pernyataannya akan dieksekusi berulang-ulang.

Dalam Algoritma, tidak dipakai simbol-simbol / sintaks dari suatu bahasa pemrograman tertentu,
melainkan bersifat umum dan tidak tergantung pada suatu bahasa pemrograman apapun juga. Notasi-
notasi algoritma dapat digunakan untuk seluruh bahasa pemrograman manapun.

Definisi Pseudo-code

Kode atau tanda yang menyerupai (pseudo) atau merupakan penjelasan cara menyelesaikan suatu
masalah. Pseudo-code sering digunakan oleh manusia untuk menuliskan algoritma.

Contoh kasus : mencari bilangan terbesar dari dua bilangan yang diinputkan

Solusi Pseudo-code :

Masukkan bilangan pertama

Masukkan bilangan kedua

Jika bilangan pertama > bilangan kedua maka kerjakan langkah 4, jika tidak, kerjakan langkah 5.

Tampilkan bilangan pertama

Tampilkan bilangan kedua

Solusi Algoritma :

Masukkan bilangan pertama (a)

Masukkan bilangan kedua (b)

if a > b then kerjakan langkah 4

print a

print b

Contoh Lain Algortima dan Pseudo-code :


BAB 2 : Analysis Framework
Analysis Framework menyediakan alat umum untuk memproses data ALICE dengan cara yang
efisien. Ini dirancang untuk mengambil keuntungan dari teknologi yang ada untuk komputasi paralel dan
menyediakan akses ke CPU dan data ke beberapa modul analisis bersamaan dalam waktu yang sama
(proses yang sama).

Analisis Modul tidak memiliki dependensi langsung tetapi dapat mengomunikasikan data yang
diproses melalui objek kontainer, membuat model data berorientasi. Sesi analisis dikoordinasikan oleh
kelas manajer yang berisi daftar modul klien (tugas) seperti pada gambar di bawah ini. Semua tugas
dalam sesi yang sama berbagi loop kejadian yang sama (fungsionalitas yang disediakan oleh TSelector)
dan berasal dari kelas dasar yang sama. Tugas perlu mengimplementasikan satu set metode virtual yang
disebut dalam berbagai tahap pemrosesan.

Akses ke data simulasi / rekonstruksi atau analisis khusus ALICE disediakan melalui penangan
acara ESD, AOD, dan MC.

A. Measuring an Input Size

Size of the input


a)Biasanya cukup mudah untuk menentukan ukuran input

- Jika kita menyortir sebuah array, itu ukuran dari array


- Jika kita menghitung n!, angka n adalah "ukuran" masalah

b)Terkadang lebih dari satu nomor diperlukan

Jika kita mencoba mengemas objek ke dalam kotak, hasilnya mungkin bergantung pada jumlah objek

dan jumlah kotak

c)Terkadang sangat sulit untuk menentukan "ukuran input"

Mempertimbangkan:

f(n) = if n is 1, then 1;
else if n is even, then f(n/2);
else f(3*n + 1)

Ukuran ukuran yang jelas, n, sebenarnya bukan ukuran yang sangat baik

Untuk melihat ini, hitunglah f (7) dan f (8)

B. UNIT FOR MEASURING RUNNING TIME


1. CPU TIME

Secara tradisional, kami akan mengukur runtime algoritma sebagai waktu CPU. Kita dapat menyimpan
waktu sistem saat ini dari komputer dalam variabel v, menjalankan algoritma A kami, dan setelah
algoritma berakhir, simpan waktu sistem saat ini di variabel lain w. C (A) = w-v adalah waktu yang
dikonsumsi oleh satu run A.

Sebagian besar bahasa pemrograman menawarkan fungsi untuk mengakses waktu sistem saat ini yang
dapat digunakan untuk melakukan pengukuran tersebut.

Di bawah Java, Anda dapat menggunakan System.currentTimeMillis (), yang mengembalikan nilai waktu
dalam milidetik, System.nanoTime () (sejak Java 5) yang mengembalikan nilai waktu dalam nanodetik,
atau kelas baru Instan yang diperkenalkan di [Java 8].

Waktu CPU seperti itu merupakan informasi yang sangat berguna. Jika Anda membaca literatur tentang
TSP, banyak dari mereka akan melaporkan waktu runtime sebagai waktu CPU. "Bagaimana lagi?" Anda
mungkin bertanya, tetapi tunggu sampai nanti di posting ini. Bagaimanapun, waktu CPU cukup mudah
dimengerti. Ini adalah hal yang ada dalam fisika nyata dan yang secara intuitif masuk akal bagi kita.
Namun, ada beberapa masalah dengan itu juga.

1.1. Pengukuran Bias


Pertama, kita tidak langsung menjalankan algoritma pada komputer "abstrak". Kami telah menerapkan
algoritme kami dalam bahasa pemrograman, kami telah mengumpulkannya, lalu mengeksekusinya di
bawah sistem operasi dan konfigurasi yang diberikan. Selain proses menjalankan program kami, ada
proses lain. Jika Anda menggunakan komputer kerja biasa untuk menjalankan eksperimen, mungkin
Anda memiliki internet messenger terbuka, browser, atau program perkantoran, atau ingin menonton
video pada saat yang bersamaan. Jika algoritma Anda diimplementasikan di Java dan, karenanya,
berjalan di Java Virtual Machine (JVM), itu tidak akan pernah sendirian di mesin virtual itu: Setidaknya
ada thread pengumpul sampah (GC) yang, dari waktu ke waktu, akan melakukan beberapa tindakan dan
mengkonsumsi waktu proses. Jika Anda menggunakan C untuk mengimplementasikan algoritma Anda,
Anda tidak memiliki thread GC yang membutuhkan waktu, tetapi Anda tidak pernah dapat melepaskan
biaya overhead yang diperlukan untuk manajemen memori. Semua itu akan mengacaukan pengukuran
waktu Anda, karena semua proses dan utas dapat berbagi CPU yang sama. Anda dapat menutup proses
sebanyak mungkin, tetapi tidak semua. Akan selalu ada beberapa proses lain, dan ini mungkin
melakukan I / O atau hal-hal lain yang berpotensi memperlambat proses Anda.

1.2. Mengurangi Bias


Kita bisa menjalankan proses yang sama berkali-kali dan mengambil waktu proses minimum. Runtime
minimum akan menjadi pendekatan terbaik, karena batas bawah runtime dari implementasi algoritma
pada mesin tertentu adalah runtime tepat dan hanya implementasi algoritma. Melihat ini dari sisi lain:
Satu-satunya hal yang dapat memperlambat suatu algoritma adalah efek sistem seperti proses dan
barang lainnya, dan dalam waktu yang paling kecil yang diukur, dampaknya adalah yang terkecil di
antara pengukuran.

Tentu saja, ide ini hanya berfungsi untuk algoritme deterministik - dan metaheuristik biasanya diacak,
yaitu, berpotensi mengambil jalur eksekusi yang berbeda setiap kali dimulai. Oleh karena itu, mereka
juga dapat mengkonsumsi jumlah waktu proses yang berbeda setiap kali dijalankan dan memilih
runtime minimum, maka dapat memperkenalkan bias lain dalam eksperimen Anda.
Cara lain untuk mengukur runtime suatu proses adalah dengan menggunakan waktu CPU yang
sebenarnya dikonsumsi. Kali ini biasanya ditawarkan oleh alat sistem operasi dan, dikombinasikan
dengan metode di atas, dapat memberikan perkiraan yang masuk akal. Di bawah Java, Anda dapat
menggunakan manajemen API dan ThreadMXBean untuk mendapatkan runtime aktual dari thread yang
diberikan. Membuat kode untuk mendapatkan perkiraan runtime mungkin merupakan pendekatan yang
layak lainnya, karena orang dapat mengharapkan bahwa alat profil yang baik harus mengambil sebagian
besar masalah yang dibahas di sini menjadi pertimbangan.

1.3. Bias yang Tak Terduga


Kadang-kadang ada juga jenis bias yang tak terduga yang mengacaukan pengukuran waktu kita. Salah
satu sumber masalah yang mungkin adalah pengukuran itu sendiri: Waktu sistem diperoleh dari sistem
operasi, dengan memanggil fungsi sistem operasi. Ini membutuhkan waktu juga.

Sumber masalah lain di Jawa adalah JVM. JVM dapat melakukan pengoptimalan kode dan kompilasi ke
kode mesin setelah mengeksekusi kode beberapa kali. Jadi, program kami mungkin pertama kali
dijalankan dengan satu cara, dan kemudian di yang lain. Dan di antara dua cara ini, sesuatu yang lain
harus terjadi, kompilasi just-in-time (JIT). Jadi, idealnya, sebelum mengukur kinerja sepotong kode, kita
harus melaksanakannya beberapa ribu kali, untuk memastikan bahwa setiap tindakan JIT potensial telah
terjadi dan tidak akan mengganggu pengukuran.

Jika Anda melakukan eksperimen dengan metode pengoptimalan, Anda mungkin ingin membuat file log
yang mencantumkan perkembangan metode dari waktu ke waktu, yaitu, menyimpan beberapa titik data
selama satu kali proses. File I / O cukup lambat dibandingkan dengan akses memori RAM. Penebangan
data kinerja ke file dapat mengacaukan seluruh proses pengukuran Anda. Idealnya, Anda harus
menyimpan semua pengukuran dalam memori (wilayah pra-alokasi) dan hanya menuliskannya ke file
setelah proses selesai.

1.4. Presisi Jam dan Resolusi


Dalam hal apapun, kita juga harus ingat bahwa baik resolusi dan ketepatan pengukuran waktu CPU
terbatas. Di masa lalu, ketika saya pertama kali melakukan sesuatu dengan pengukuran waktu, Anda
bisa mendapatkan waktu saat ini pada PC dalam satuan 1 milidetik, tetapi jam presisi sekitar 10
milidetik. Dokumentasi metode System.currentTimeMillis (), di Java saat ini masih menyatakan:

Perhatikan bahwa sementara unit waktu dari nilai kembalian adalah milidetik, granularitas nilai
bergantung pada sistem operasi yang mendasarinya dan mungkin lebih besar. Sebagai contoh, banyak
sistem operasi mengukur waktu dalam satuan puluhan milidetik.

Dokumentasi dari metode System.nanoTime () yang disebutkan sebelumnya menyatakan: Metode ini
memberikan presisi nanodetik, tetapi belum tentu akurasi nanodetik dan hal yang sama berlaku untuk
nilai waktu yang bisa kita dapatkan melalui ThreadMXBean.

Umumnya, selalu ada batasan tentang seberapa tepat Anda dapat mengukur waktu dan biasanya lebih
tinggi daripada resolusi jam. Saat mengevaluasi pengukuran waktu Anda untuk algoritme yang sangat
cepat, Anda mungkin mendapatkan waktu konsumsi 0. Jika algoritme berjalan terlalu cepat, maka kami
perlu mengekstrapolasi waktu prosesnya dengan menjalankannya. Perangkap umum di sini adalah
untuk menjalankannya, katakanlah, 10.000 kali dan membagi waktu yang diukur dengan 10000. Jika
algoritma terlalu cepat, kita masih bisa mendapatkan runtime nol. Hal ini terutama berlaku ketika
menjalankan program yang dibangun 20 tahun atau lebih pada perangkat keras saat ini. Sebagai
gantinya, seseorang dapat menentukan waktu minimum, katakanlah 10 menit. Algoritme dijalankan
dalam lingkaran berulang hingga gaya (yang mengeksekusi tubuh setidaknya sekali) hingga 10 menit
berlalu. Melakukan pembagian titik apung dari waktu sebenarnya yang diambil loop (kemungkinan akan
sedikit lebih dari 10 menit jika kita selalu menganggap berjalan lengkap) dengan jumlah waktu algoritma
telah dieksekusi harus menghasilkan perkiraan yang wajar di semua tetapi yang paling aneh kasus.

1.5. Jendela Utilitas


Mengukur waktu CPU memiliki batasan lain yang sangat berat. Ini sangat tergantung pada fitur-fitur
berikut:

Konfigurasi Perangkat Keras: kecepatan prosesor dan jenis dan nomor, ukuran dan kecepatan RAM,
mainboard, dan perangkat keras lain yang digunakan.

Konfigurasi Perangkat Lunak: sistem operasi, program utilitas yang digunakan, dan pustaka pihak ketiga.

Implementasi: Bahasa pemrograman (Assembler? C? Java? Python?), Kompilator (optimasi?),


Lingkungan runtime (Java JVM version?).

Jika beberapa elemen dalam konfigurasi ini berubah, maka pengukuran waktu proses juga dapat
berubah secara signifikan. Sebenarnya, ini adalah alasan untuk banyak perkembangan di atas tiga
bidang, untuk membuat segalanya lebih cepat. Ini, bagaimanapun, juga berarti bahwa runtime yang
diukur memiliki jendela utilitas yang sangat terbatas. Jika Anda membaca kertas dari lima belas tahun
yang lalu, melaporkan runtime dari suatu algoritma pada prosesor Pentium II dengan 400 MHz, maka
informasi ini tidak benar-benar berguna bagi Anda, karena Anda hampir tidak dapat memperkirakan
runtime yang sesuai pada mesin saat ini.

1,6. Apa yang Harus Disertakan?


Akhirnya, ketika mengukur waktu CPU, kita harus yakin apa yang sebenarnya ingin kita masukkan ke
dalam pengukuran kita. Katakanlah Anda ingin mem-benchmark suatu algoritma untuk menyelesaikan
instance TSP. Implementasi Anda akan memuat instance dari file, mencari solusi perkiraan, dan
menyimpannya ke file lain. Haruskah kita memasukkan file I / O ke dalam pengukuran waktu kita atau
tidak? Itu tergantung pada apa yang Anda inginkan. Jika Anda ingin mengetahui keseluruhan, lengkap
runtime dari program, atau hanya runtime dari algoritma yang memecahkan contoh yang diberikan.
Dalam kasus terakhir, termasuk file I / O dalam pengukuran mungkin tidak masuk akal. Tetapi
bagaimana jika program Anda sudah melakukan preprocessing saat memuat instance masalah?

Sebagai hasilnya, kita dapat menyimpulkan bahwa pengukuran waktu CPU hanya berguna jika kita
sangat persis mendokumentasikan bagaimana mereka telah diperoleh dan apa sebenarnya yang telah
kita ukur - dan bahkan kemudian, mereka hanya berguna selama kita dapat menciptakan kembali
eksperimen , yaitu, platform perangkat keras dan lunak yang digunakan tersedia.

Banyak peneliti dengan demikian mempertimbangkan waktu CPU sehingga hanya sebagai pendekatan
yang sangat kasar. Jika satu algoritma membutuhkan waktu setengah dari yang lain, mereka mungkin
menganggapnya kurang lebih sama di kelas kinerja yang sama. Pengukuran runtime untuk contoh
masalah tunggal kemudian tidak menarik, menarik adalah perbandingan atas beberapa contoh masalah
dari skala yang berbeda n: Bagaimana runtime menumbuhkan skala masalah (ingat O (2n)?) ...

2. NORMALIZED CPU TIME


OK, tetapi bagaimana jika kita ingin membandingkan runtimes pada satu instance?

Kami tidak dapat memperbaiki semua masalah yang terjadi saat mengukur waktu proses, tetapi kami
mungkin mencoba mengurangi setidaknya ketergantungan alat berat. Idenya adalah sebagai berikut:
Sebelum kita mengukur runtime dari algoritma A kami, kami patokan mesin M di mana kami akan
menjalankannya dan memperoleh faktor kinerja yang bergantung pada mesin Z (M). Kami kemudian
menggunakan Z (M) untuk menormalkan runtime C (A) yang kami ukur.

2.1. Benchmark the Machine, kemudian Benchmark the Algorithm


Ada dua cara untuk melakukannya: Di satu sisi, Anda dapat menjalankan patokan standar untuk
perangkat keras, katakanlah LinPACK atau sesuatu, yang memberi tahu Anda seberapa cepat mesin
Anda pada umumnya. Namun, pengukuran semacam itu mungkin tidak benar-benar sesuai dengan
eksperimen Anda, karena tolok ukur perangkat keras tersebut dapat mengukur fitur yang tidak relevan
dengan algoritme Anda.

Di sisi lain, Anda bisa melanjutkan sebagai berikut. Katakanlah Anda ingin mengukur runtime dari
pemecah TSP pada set I = i1, i2, i ... dari contoh terkenal ik dari TSP. Yang Anda inginkan adalah bahwa
faktor kinerja yang bergantung pada mesin Z (M) mencerminkan kinerja mesin M dalam hal semua fitur
yang relevan untuk algoritma Anda A. Karena kita dapat mengharapkan bahwa pemecah TSP yang paling
masuk akal memiliki persyaratan yang sama, itu akan masuk akal untuk memilih pemecah TSP
sederhana dan mudah dilaksanakan B dan membiarkan Z (M) menjadi runtime pada mesin M.

B harus bersifat deterministik dan memiliki runtime yang wajar, tidak terlalu pendek (sehingga
pengukuran menjadi tidak tepat) dan tidak terlalu lama (karena akan meningkatkan waktu yang kita
perlukan untuk bereksperimen terlalu banyak). Saat mengukur runtime B, poin yang dibahas mengenai
pengurangan bias pengukuran pada bagian sebelumnya harus dipertimbangkan

2.2. Terapkan Algoritma Standar untuk Setiap Soal Masalah


Untuk mendapatkan perkiraan kinerja yang sempurna, saya sarankan untuk tidak hanya menerapkan B
pada beberapa instance TSP untuk mendapatkan satu nilai Z (M). Sebagai gantinya, saya akan
menerapkan B pada setiap contoh ik di I dan mendapatkan satu faktor kinerja Z (M, ik) untuk masing-
masingnya. Alasannya adalah bahwa contoh masalah yang berbeda mungkin memiliki runtime dan
persyaratan mesin yang berbeda. Contoh TSP dengan, katakanlah, 10 kota mungkin memiliki matriks
jarak yang sepenuhnya cocok dengan cache mesin. Ini mungkin tidak benar untuk sebuah instance
dengan 100 kota, dan untuk sebuah instance dengan 100000 kota, bahkan permutasi yang tidak
mewakili satu solusi ke TSP dapat masuk ke dalam cache. Jika kita memiliki satu faktor kinerja Z (M, ik)
untuk setiap contoh, yang diciptakan oleh jalur B, kita dapat mengurangi pengaruh ini juga.

Jika Z (M, ik) adalah runtime dari benchmark standar algoritma B, kita sekarang dapat membagi semua
runtime yang diukur untuk algoritma A pada contoh ik (yang sebenarnya kita tertarik) oleh Z (M, ik).
Hasilnya adalah runtime yang dinormalisasi yang seharusnya dapat dibandingkan secara wajar dengan
sejumlah mesin yang berbeda.

2.3. Pro dan kontra


Dengan pendekatan ini, kami agak mengurangi ketergantungan mesin terhadap waktu CPU. Namun,
kami sekarang memiliki hasil yang tidak dapat dibandingkan dengan hasil yang dilaporkan dalam
literatur, karena ini umumnya tidak dinormalisasi. Juga, waktu yang dinormalisasi tidak memiliki unit
dan dengan demikian kurang mudah ditafsirkan. Itu juga mungkin masih bias oleh proses lain yang
berjalan pada mesin yang sama mengacaukan pengukuran kami.

3. Mengukur "Algoritma Langkah" 1: FEs


Di bidang optimasi metaheuristik, ada pendekatan lain untuk mengukur runtime: untuk menghitung apa
yang disebut "Evaluasi Fungsi" obyektif, atau FE untuk jangka pendek.

Ide dasar di sini berasal dari optimasi kotak hitam. Algoritma optimisasi kami dilengkapi dengan struktur
data kandidat solusi dan fungsi obyektif f. Fungsi obyektif adalah kriteria pengoptimalan. Dibutuhkan
solusi kandidat sebagai parameter dan mengembalikan nilai obyektif, angka angka utilitasnya (biasanya,
semakin kecil angka ini semakin baik adalah solusi kandidat).

Dalam kasus TSP, kandidat solusi struktur data bisa "permutasi dari> kota-kota" dan f bisa
mengembalikan panjang tur didefinisikan oleh permutasi tersebut. Metaheuristik kotak hitam hanya
membutuhkan dua hal ini, kandidat solusi struktur data dan fungsi obyektif, untuk menemukan solusi
perkiraan untuk masalah.

Seringkali, menghitung nilai f akan memakan waktu lama. Itu bisa, misalnya, mengharuskan kita untuk
melakukan simulasi yang rumit. Dengan demikian, seseorang dapat mengukur runtime suatu algoritma
dengan menghitung berapa kali ia mengevaluasi fungsi obyektif (hingga mencapai nilai obyektif tujuan
tertentu). Pengukuran ini sepenuhnya bebas mesin.

Penghitungan FE dapat digunakan saat membandingkan algoritme dengan cara yang tidak bergantung
pada masalah: Kita dapat mengukur suatu algoritme dengan menggunakan fungsi obyektif yang
sederhana dan cepat dihitung. Jika fungsi ini memiliki fitur serupa yang kompleks masalah nyata,
daripada kita dapat melakukan beberapa eksperimen cukup cepat. Algoritma yang membutuhkan
evaluasi fungsi obyektif paling sedikit untuk mencapai kualitas solusi tujuan, maka akan menjadi yang
tercepat ketika diterapkan pada masalah yang sebenarnya. Sistem pembandingan COCO / BBOB yang
populer melakukan hal itu.

Kami dapat meringkas gagasan pengukuran runtime ini sebagai berikut:

Identifikasi jenis langkah algoritme yang tampaknya paling rumit secara komputasi dan tampaknya
memiliki kontribusi tertinggi terhadap runtime dalam algoritme yang akan dibandingkan.

Hitung langkah-langkah ini dan ukur runtime sesuai dengan itu.

Idealnya, Anda dapat menggantinya dengan operasi "bodoh" yang jauh lebih cepat daripada yang asli.
Kemudian Anda dapat melakukan lebih banyak eksperimen dalam bingkai waktu nyata yang sama.
Dalam pengoptimalan, oleh karena itu kami menggunakan fungsi sasaran tolok ukur yang
disederhanakan alih-alih yang nyata, yang dapat, misalnya, memerlukan simulasi yang rumit.

3.1. Pro dan kontra

Ide ini memiliki beberapa kelebihan. Mengukur runtime algoritma dalam hal langkah-langkah algoritma
membuat Anda sepenuhnya independen pada perangkat keras, perangkat lunak, atau lingkungan
pemrograman. Banyak makalah dalam domain optimasi melaporkan hasil mereka runtime dalam hal FE,
jadi biasanya ada stok data besar yang tersedia dengan mana Anda dapat membandingkan hasil Anda -
dan data ini akan tetap berarti dalam 100 tahun dari sekarang.

Tetapi ada juga beberapa kekurangan. Menghitung FE tidak memberi kita bukti nyata berapa banyak
runtime yang sebenarnya dibutuhkan algoritma. Ini jelas, karena FE tidak memiliki unit fisik, yaitu, tidak
ada nilai waktu untuk memulai.

Selanjutnya, pengukuran waktu berbasis FE, menurut definisi, tidak termasuk hal-hal seperti waktu
start-up, waktu pembukaan, preprocessing, pengumpulan sampah atau alokasi memori, inisialisasi
variabel, penyalinan array, pencarian dalam peta hash, penyortiran daftar, pembaruan struktur data
internal, seleksi atau reproduksi dalam algoritma evolusioner (EA), dan seterusnya. Semua aspek ini
sebenarnya merupakan bagian dari algoritma optimasi, bagian dari runtime yang diperlukannya.
Katakanlah Anda menerapkan EA yang melakukan pemilihan pemotongan dan karena itu harus
mengurutkan penduduknya. Anda akan mengukur runtime yang sama di FE, terlepas dari apakah Anda
menggunakan Quicksort atau Bubble Sort untuk tujuan ini. Apakah ini baik atau buruk?

Semua rincian ini diabaikan dengan asumsi bahwa perhitungan fungsi tujuan adalah bagian yang paling
memakan waktu dari algoritme Anda, dan yang lainnya dapat diabaikan. Ini tidak selalu benar. Di TSP,
misalnya, tidak.

3.2. Kompleksitas 1 FE

Dalam TSP, menghitung panjang dari tur yang benar-benar baru (solusi kandidat), mengunjungi semua n
kota dari contoh masalah, membutuhkan perhitungan jarak n dengan tepat. Itu bisa dilakukan di O (n).
Karena kita dapat memperkirakan bahwa menghitung jarak antara dua kota cukup cepat, mengevaluasi
solusi baru (mungkin dihasilkan oleh metaheuristik kotak hitam) seharusnya cukup cepat juga.

Jika ini benar, kita tidak bisa a priori mengharapkannya menjadi faktor yang menentukan runtime suatu
algoritma. Sebaliknya, kita harus berpikir tentang algoritma itu sendiri. Dalam kasus TSP, kita mungkin
bertanya, "Berapa banyak upaya komputasi yang diperlukan untuk menghasilkan dan mengevaluasi
solusi baru atas semua?" Mari kita tetap dengan representasi permutasi (jalur) untuk tur. Jika kita
memiliki algoritme evolusioner dengan beberapa operator mutasi dan crossover standar, maka
menghasilkan tur baru mungkin juga akan mengambil sesuatu dalam kisaran O (n) langkah (mungkin
hingga O (n2) untuk operator crossover yang rumit, tetapi mari kita tetap dengan ke O (n)). Dengan kata
lain, membuat dan mengevaluasi solusi baru dapat terjadi bersama-sama dalam O (n) langkah jika kita
beruntung. Tetapi apakah ini juga berlaku untuk pemecah TSP lainnya?
Bukan itu. Mari kita lihat Ant Colony Optimization (ACO), metaheuristik lain yang telah berhasil
diterapkan pada TSP. Di ACO, kami mensimulasikan cara semut berjalan dari sumber ke titik tujuan. Jika
kita menerapkan ini untuk TSP, kita bisa mulai dengan menempatkan semut simulasi di beberapa node
asal acak. Semut perlu sekarang memilih simpul mana yang akan dikunjungi sebagai langkah kedua
dalam turnya. Untuk tujuan ini, ia akan memeriksa setiap insiden tepi ke lokasinya saat ini dan
memutuskan secara heuristik (berdasarkan panjang tepi dan jumlah feromon yang disimulasikan pada
mereka) ke mana harus pergi. Ini akan mengulangi prosedur ini sampai telah mengunjungi semua node.
Ini berarti akan membuat (n-1) + (n-2) + (n-3) + ... + 2 perbandingan, yang dalam O (n2) Dengan kata lain,
satu FE yang dilakukan oleh ACO memiliki kompleksitas yang jauh lebih tinggi daripada satu FE di EA.

Tetapi ada juga kasus sebaliknya: Mari kita asumsikan kita telah membuat solusi t1 = (12345678910) dan
kita hanya ingin menukar dua kota yang dipilih secara acak dalam tur, katakanlah kota 3 dan 8. Kita
mendapatkan tur t2 = (12845673910) . Jika kita tahu panjang t1 tur pertama, maka kita dapat
menghitung panjang tur baru dengan mengurangkan dan menambahkan empat jarak: Kita kurangi jarak
dari simpul 3 dan 8 ke kota pendahulunya dan penerus di t2 dan tambahkan jaraknya ke pendahulu dan
penerus baru mereka di t2. Ini berarti kita dapat menghasilkan dan mengevaluasi solusi baru di bawah
seperti "swap" bergerak dalam O (1) perhitungan jarak. Ini terjadi karena kita sebenarnya tidak
melakukan optimasi black-box tetapi menggunakan pengetahuan tentang struktur fungsi obyektif.

4. Mengukur "Langkah Algoritma"


Mari kita bergerak dari optimasi kotak hitam, di mana tidak ada pengetahuan tentang masalah dan
struktur fungsi obyektif yang diintegrasikan ke dalam algoritme kami, ke pengoptimalan khusus masalah,
di mana pengetahuan tersebut digunakan. Kami mungkin menemukan bahwa proses membangun solusi
kandidat menjadi faktor penentu untuk keseluruhan waktu proses. Hanya menghitung FE mungkin tidak
adil, meskipun itu juga memiliki beberapa kelebihan. Tampaknya logis untuk mencari langkah-langkah
algoritma yang lebih mendasar yang dapat dihitung, untuk mengurangi kerugian menghitung FE sambil
mempertahankan kelebihannya.

Dalam TSP, misalnya, satu kandidat untuk langkah-langkah semacam itu dapat berupa "evaluasi jarak".
Dalam contoh kami sebelumnya, kami mengasumsikan bahwa EA dapat melakukan operasi mutasi
crossover atau off-the-rak dalam O (n) langkah. Menghitung panjang dari tur yang benar-benar baru
mengharuskan kita untuk melakukan perhitungan jarak n dengan tepat juga. Jika ACO, keputusan semut
yang disimulasikan bergantung pada feromon pada tepi dan panjang tepi, yaitu jarak. Semut membuat,
secara total, O (n2) keputusan semacam itu. Dan untuk menghitung panjang tur dari tur baru, yang
dihasilkan dalam O (1) langkah oleh operator swap, mengambil paling banyak 8 perhitungan jarak.

Dengan kata lain, dalam tiga contoh ini, jumlah jarak kota-ke-kota yang perlu kita hitung selama
pembuatan solusi baru adalah di kelas big-O yang sama dengan langkah-langkah algoritma halus yang
diperlukan untuk proses ini. Menghitung evaluasi jarak (DE) dalam TSP dengan demikian tampaknya
menjadi ukuran waktu yang lebih adil daripada menghitung FE. Ini mungkin masih tidak sepenuhnya
adil, karena mungkin ada implementasi operator yang dapat menghitung jarak solusi baru dengan
sejumlah DE yang berada dalam kelas kompleksitas yang berbeda dari jumlah langkah yang diperlukan
untuk menghasilkan solusi: Membalikkan sub-tur panjang 1 <m <n dapat diimplementasikan dalam O
(m) langkah-langkah sementara panjang tur baru dihitung dalam O (1) ...
Menggunakan DE memiliki beberapa kekurangan. Pertama-tama, itu masih tidak terkait dengan waktu
jam nyata, meskipun kita dapat mengharapkan hubungan yang lebih dekat. Kedua, seperti FE, itu tidak
dapat menangkap langkah-langkah algoritma yang tidak terkait dengan perhitungan jarak. Jika algoritme
pengoptimalan kami melakukan analisis kompleks dari langkah pencarian sebelumnya dengan
menggunakan pendekatan Machine Learning, atau jika sebagian besar modifikasi yang diterapkan pada
solusi kandidat tidak memerlukan penghitungan jarak kota, ini (masih) akan luput dari perhatian. Ketiga,
tidak ada pekerjaan terkait yang menggunakan ukuran waktu tersebut, sehingga Anda tidak akan
menemukan kertas untuk membandingkan hasil Anda dengan. Akhirnya, keempat, DEs adalah ukuran
waktu khusus TSP. Untuk masalah pengoptimalan apa pun, seseorang harus menentukan langkah
langkah algoritma yang sesuai. (Dalam masalah MaxSAT, orang bisa menghitung bit flips, misalnya.)

Jika kita hanya ingin mengukur kemampuan optimasi kotak hitam dari suatu algoritma optimasi, kita
akan tetap berpegang pada FE, karena kita akan berasumsi bahwa FE memakan waktu begitu lama
sehingga tidak ada hal lain yang penting. Jika kita membandingkan pemecah TSP, bagaimanapun, DE
dapat menawarkan cara yang lebih adil, mesin-independen untuk mengukur waktu.

C. ORDER OF GROWTH

10 Order of growth

Anggaplah komputer Anda dapat melakukan 10.000 operasi (mis., Manipulasi struktur data, sisipan basis
data, dll.) Per detik. Diberi algoritma yang membutuhkan lg n, n½, n, n2, n3, n4, n6, 2n, dan n! operasi
untuk melakukan tugas yang diberikan pada item n, inilah berapa lama waktu yang dibutuhkan untuk
memproses 10, 50, 100 dan 1.000 item.

n
10 50 100 1,000
lg n 0.0003 sec 0.0006 sec 0.0007 sec 0.0010 sec
n ½
0.0003 sec 0.0007 sec 0.0010 sec 0.0032 sec
n 0.0010 sec 0.0050 sec 0.0100 sec 0.1000 sec
n lg n 0.0033 sec 0.0282 sec 0.0664 sec 0.9966 sec
n 2 0.0100 sec 0.2500 sec 1.0000 sec 100.00 sec
n3 0.1000 sec 12.500 sec 100.00 sec 1.1574 day
n4 1.0000 sec 10.427 min 2.7778 hrs 3.1710 yrs
n6 1.6667 min 18.102 day 3.1710 yrs 3171.0 cen
2n 0.1024 sec 35.702 cen 4×1016 cen 1×10166 cen
n! 362.88 sec 1×1051 cen 3×10144 cen 1×102554 cen
Table 1: Waktu yang dibutuhkan untuk memproses n item pada kecepatan 10.000 operasi /
detik menggunakan delapan algoritma yang berbeda.
Catatan: Satuan di atas adalah detik (sec), menit (min), jam (hrs), hari (day), tahun (yrs), dan abad (cen)!
The Explosive Growth dari 2n

n
15 20 25 30 35 40 45
3.28 sec 1.75 min 55.9 min 1.24 days 39.8 days 3.48 yrs 1.12 cen
Table 2: Waktu yang dibutuhkan untuk memproses n item pada kecepatan 10.000 operasi /
detik menggunakan algoritma 2n.

The Explosive Growth dari n!

n
11 12 13 14 15 16 17
1.11 hrs 13.3 hrs 7.20 days 101 days 4.15 yrs 66.3 yrs 11.3 cen
Table 3: Waktu yang dibutuhkan untuk memproses n item dengan kecepatan 10.000 operasi /
detik menggunakan n! algoritma.

BAB 3: Brute Force & Exhaustive Search


A.Definisi
Dalam ilmu komputer, pencarian kekuatan atau pencarian lengkap, juga dikenal sebagai hasil dan tes,
adalah teknik pemecahan masalah yang sangat umum dan paradigma algoritmik yang terdiri dari
penghitungan secara sistematis semua kandidat yang mungkin untuk solusi dan memeriksa apakah
masing-masing kandidat memenuhi pernyataan masalah .

Algoritma brute-force untuk menemukan pembagi bilangan alami n akan menghitung semua bilangan
bulat dari 1 hingga n, dan memeriksa apakah masing-masing memisah n tanpa sisa. Sebuah pendekatan
brute force untuk teka-teki delapan ratu akan memeriksa semua pengaturan yang mungkin dari 8 buah
pada papan catur 64-persegi, dan, untuk setiap pengaturan, periksa apakah masing-masing (ratu)
potongan dapat menyerang yang lain.

Sementara pencarian brute-force sederhana untuk diterapkan, dan akan selalu menemukan solusi jika
ada, biayanya sebanding dengan jumlah solusi kandidat - yang dalam banyak masalah praktis cenderung
tumbuh sangat cepat karena ukuran masalah meningkat ( ledakan kombinatorial) [1]. Oleh karena itu,
pencarian brute-force biasanya digunakan ketika ukuran masalah terbatas, atau ketika ada heuristik
spesifik masalah yang dapat digunakan untuk mengurangi kumpulan solusi kandidat ke ukuran yang
dapat dikelola. Metode ini juga digunakan ketika kesederhanaan implementasi lebih penting daripada
kecepatan.

Ini adalah kasus, misalnya, dalam aplikasi kritis di mana kesalahan dalam algoritma akan memiliki
konsekuensi yang sangat serius; atau saat menggunakan komputer untuk membuktikan teorema
matematika. Penelusuran gaya-brute juga berguna sebagai metode dasar ketika membandingkan
algoritme lain atau metaheuristik. Memang, pencarian brute-force dapat dipandang sebagai
metaheuristik yang paling sederhana. Pencarian kekuatan brute tidak boleh disamakan dengan
backtracking, di mana set solusi yang besar dapat dibuang tanpa disebutkan secara eksplisit (seperti
dalam solusi komputer buku teks untuk delapan ratu masalah di atas). Metode brute-force untuk
menemukan item dalam tabel - yaitu, periksa semua entri yang terakhir, secara berurutan - disebut
pencarian linear.

Algoritma dasar

Untuk menerapkan pencarian brute-force ke kelas masalah tertentu, seseorang harus menerapkan
empat prosedur, pertama, berikutnya, valid, dan output. Prosedur ini harus mengambil sebagai
parameter data P untuk contoh khusus dari masalah yang harus dipecahkan, dan harus melakukan hal
berikut:

first (P): menghasilkan solusi kandidat pertama untuk P.

next (P, c): buat kandidat selanjutnya untuk P setelah yang sekarang c.

valid (P, c): periksa apakah kandidat c adalah solusi untuk P.

output (P, c): gunakan solusi c P yang sesuai dengan aplikasi.

Prosedur selanjutnya juga harus memberi tahu ketika tidak ada lagi kandidat untuk instance P, setelah
yang sekarang c. Cara mudah untuk melakukannya adalah mengembalikan "kandidat tidak sah",
beberapa nilai data konvensional Λ yang berbeda dari kandidat nyata. Demikian juga prosedur pertama
harus mengembalikan Λ jika tidak ada kandidat sama sekali untuk contoh P. Metode brute-force
kemudian diekspresikan oleh algoritma

c ← first(P)

while c ≠ Λ do

if valid(P,c) then output(P, c)

c ← next(P,c)

end while

Misalnya, ketika mencari pembagi dari bilangan bulat n, contoh data P adalah bilangan n. Panggilan
pertama (n) harus mengembalikan bilangan bulat 1 jika n ≥ 1, atau Λ sebaliknya; panggilan berikutnya
(n, c) harus mengembalikan c + 1 jika c <n, dan Λ sebaliknya; dan valid (n, c) harus mengembalikan true
jika dan hanya jika c adalah pembagi dari n. (Bahkan, jika kita memilih Λ menjadi n + 1, tes n ≥ 1 dan c <n
tidak diperlukan.) Algoritma pencarian brute-force di atas akan memanggil output untuk setiap kandidat
yang merupakan solusi untuk instance yang diberikan P. Algoritma ini mudah dimodifikasi untuk
berhenti setelah menemukan solusi pertama, atau sejumlah solusi yang ditentukan; atau setelah
menguji jumlah kandidat yang ditentukan, atau setelah menghabiskan sejumlah waktu CPU.
B.Selection Sort and Bubble Sort

Sorting bisa didefinisikan sebagai suatu pengurutan data yang sebelumnya disusun secara acak, sehingga
menjadi tersusun secara teratur menurut aturan tertentu. sorting yang kita terapkan menggunakan tipe
data array agar pemahaman serta pengimplementasiannya lebih mudah

Pada umumnya metode yang digunakan untuk sorting adalah :

1. Buble\Exchange sort

2. Selection sort

3. Shell Sort

4. Quick sort

Selection Sort
Cara kerja metode ini didasarkan pada pencarian elemen dengan nilai terkecil. kemudian dilakukan
penukaran dengan elemen ke-I. Secara singkat metode ini bisa dijelaskan sebagai berikut. Pada langkah
pertama, dicari data yang terkecil dari data pertama sampai terakhir. Kemudian data tersebut kita tukar
dari data pertama. Dengan demikian, data pertama sekarang mempunyai nilai paling kecil dibanding
dengan data lain. Pada langkah kedua, data terkecil kita cari mulai dari data kedua sampai data terakhir.
Data terkecil yang kita peroleh kita tukar dengan data kedua. Demikian seterusnya sampai seluruh data
terurut.

Contoh dari proses sorting dengan menggunakan metode Selection sort :


Dalam Procedure Pascal :

Procedure Selection(Var Temp : Data; JmlData : Integer);

Var I,J, Lok : Integer;


Begin
For I:=1 To JmlData-1 Do
Begin
Lok:=I;
For J:=I+1 To JmlData Do
If Temp[Lok] > Temp[J] Then Lok:=J;
SWAP(Temp[I], Temp[Lok]);
End;
End;

Bubble sort
Diberi nama "Bubble" karena proses pengurutan secara berangsur-angsur bergera/berpindah ke posisi
yang tepat , seperti gelembung yang keluar dari sebuah gelas bersoda. Bubble sort mengurutkan data
dengan cara membandingkan elemen sekarang dengan elemen berikutnya. jika elemen sekarang lebih
besar dari elemen berikutnya maka elemen tersebut ditukar (untuk pengurutan ascending) jika elemen
sekarang lebih kecil daripada elemen berikutnya, maka kedua elemen tersebut ditukar (untuk
pengurutan descending). algoritma ini seolanh olah menggeser satu per satu elemen dari kenan ke kiri
atau kiri ke kanan. tergantung jenis pengurutannya. Ketika suatu proses telah selesai, maka bubble sort
akan mengalami proses, demikian seterusnya. Bubble sort berhenti jika seluruh array telah diperiksa dan
tidak ada pertukaran lagi yang bisa dilakukan,serta tercapai pengurutan yang telah diinginkan
Contoh pengurutan data yang dilakukan dengan metode bubble sort sebagai berikut :
Proses 1 :
22 10 15 3 8 2
22 10 15 3 2 8
22 10 15 2 3 8
22 10 2 15 3 8
22 10 2 15 3 8
22 2 10 15 3 8
2 22 10 15 3 8
Pengecekan dimulai dari data yang paling akhir, kemudian dibandingkan dengan data di depannya,jika
data didepannya lebih besar maka akan di tukar.
Proses 2:
2 22 10 15 3 8
2 22 10 15 3 8
2 22 10 3 15 8
2 22 3 10 15 8
2 3 22 10 15 8
pengecekan dilakukan sampai dengan data ke-2 karena data pertama pasti sudah paling kecil.
Proses 3 :
2 3 22 10 15 8
2 3 22 10 8 15
2 3 22 8 10 15
2 3 8 22 10 15
Proses 4 :
2 3 8 22 10 15
2 3 8 22 15 10
2 3 8 15 22 10
Proses 5 :
2 3 8 15 22 10
2 3 8 15 10 22
Pengurutan berhenti.
Dalam Procedure Pascal :
Procedure Bubble(Var Temp : Data; JmlData : Integer);
Var I,J : Integer;
Begin
For I:=2 To JmlData Do
For J:=JmlData DownTo I Do
If Temp[J] < Temp[J-1] Then {Untuk Descending
>}
SWAP(Temp[J], Temp[J-1]);
End;
Dalam Procedure SWAP :
Var Temp : Char;
Begin
Temp := A;
A := B;
B := Temp;
End;

C.Sequential Search and Brute-Force String Maching


Pencarian Berurutan dan Pencocokan String Brute-Force

Kami melihat pada bagian sebelumnya dua aplikasi pendekatan brute force ke porblem pengurutan. Di
sini kita membahas dua aplikasi strategi ini untuk masalah pencarian. Kesepakatan pertama dengan
masalah kanonik mencari item dari nilai yang diberikan dalam daftar yang diberikan. Yang kedua
berbeda karena berhubungan dengan masalah pencocokan string.

Pencarian Berurutan

Kami telah menemukan algoritma brute-force untuk masalah pencarian umum: ini disebut pencarian
berurutan (lihat Bagian 2.1). Untuk mengulang, algoritma hanya membandingkan elemen-elemen yang
berurutan dari daftar yang diberikan dengan kunci pencarian yang diberikan sampai suatu kecocokan
ditemukan (pencarian sukses) atau daftar tersebut habis tanpa menemukan kecocokan (pencarian yang
tidak berhasil). Trik tambahan yang sederhana sering digunakan dalam mengimplementasikan pencarian
berurutan: jika kita menambahkan kunci pencarian ke ujung daftar, pencarian kunci harus berhasil, dan
oleh karena itu kita dapat menghilangkan akhir daftar cek sama sekali. Berikut ini adalah pseudocode
dari versi yang disempurnakan ini.

ALGORITHM SequentialSearch2 (A [0..n], K)

// Menerapkan pencarian berurutan dengan kunci pencarian sebagai sentinel // Input: Array A dari n
elemen dan kunci pencarian K

// Output: Indeks elemen pertama dalam A [0..n - 1] yang nilainya

sama dengan K atau −1 jika tidak ditemukan elemen seperti itu

A [n] ← K i ← 0

sementara A [i] = K do i ← i + 1

jika saya kembali lagi, saya kembali −1


Perbaikan langsung lainnya dapat dimasukkan dalam pencarian berurutan jika daftar yang diberikan
diketahui diurutkan: pencarian dalam daftar seperti itu dapat dihentikan segera setelah elemen yang
lebih besar atau sama dengan kunci pencarian ditemui.

Pencarian sekuensial memberikan ilustrasi yang sangat baik dari pendekatan kekuatan brute-force,
dengan kekuatan karakteristiknya (kesederhanaan) dan kelemahan (inferior effi-ciency). Hasil efisiensi
yang diperoleh dalam Bagian 2.1 untuk versi standar dari perubahan pencarian berurutan untuk versi
yang disempurnakan hanya sangat sedikit, sehingga algoritma tetap linier baik dalam kasus-kasus
terburuk dan rata-rata. Kita bahas nanti di buku beberapa algoritma pencarian dengan efisiensi waktu
yang lebih baik.

Pencarian Berurutan dan Pencocokan String Brute-Force

Pencocokan String Brute-Force

Ingat masalah string-matching yang diperkenalkan pada Bagian 1.3: diberi string n karakter yang disebut
teks dan string karakter m (m ≤ n) yang disebut pola, temukan substring teks yang sesuai dengan pola.
Untuk lebih tepatnya, kami ingin menemukan i — indeks karakter paling kiri dari substring pencocokan
pertama dalam teks

Jika pertandingan selain yang pertama harus ditemukan, algoritma pencocokan string dapat terus
bekerja sampai seluruh teks habis.

Algoritma brute-force untuk masalah pencocokan string cukup jelas: selaraskan pola dengan karakter m
pertama dari teks dan mulailah mencocokkan pasangan karakter yang sesuai dari kiri ke kanan sampai
semua pasangan pasangan karakter cocok (kemudian algoritma dapat berhenti) atau pasangan yang
tidak cocok dijumpai. Dalam kasus terakhir, geser pola satu posisi ke kanan dan lanjutkan perbandingan
karakter, mulai lagi dengan karakter pertama dari pola dan pasangannya dalam teks. Perhatikan bahwa
posisi terakhir dalam teks yang masih bisa menjadi awal dari substring yang cocok adalah n - m (asalkan
posisi teks diindeks dari 0 ke n - 1). Di luar posisi itu, tidak ada cukup karakter untuk mencocokkan
seluruh pola; karenanya, algoritme tidak perlu membuat perbandingan di sana.

ALGORITHM BruteForceStringMatch (T [0..n - 1], P [0..m - 1])

// Menerapkan pencocokan string brute-force

// Input: Array T [0..n - 1] dari n karakter yang mewakili teks dan

sebuah array P [0..m - 1] dari karakter m yang mewakili suatu pola // Output: Indeks karakter pertama
dalam teks yang memulai

pencocokan substring atau −1 jika pencarian tidak berhasil

untuk i ← 0 sampai n - m lakukan j ← 0


sementara j <m dan P [j] = T [i + j] lakukan j ← j + 1

jika j = m kembali saya kembali −1

Operasi dari algoritma diilustrasikan pada Gambar 3.3. Perhatikan bahwa untuk contoh ini, algoritme
menggeser pola hampir selalu setelah perbandingan karakter tunggal. Kasus terburuk jauh lebih buruk:
algoritme mungkin harus membuat semua perbandingan m sebelum menggeser pola, dan ini dapat
terjadi untuk setiap percobaan n-m + 1. (Soal 6 dalam latihan bagian ini meminta Anda untuk
memberikan contoh spesifik dari situasi semacam itu.) Jadi, dalam kasus terburuk, algoritme membuat

m (n - m + 1) perbandingan karakter, yang menempatkannya di kelas O (nm). Untuk pencarian kata yang
khas dalam teks bahasa alami, bagaimanapun, kita harus berharap bahwa sebagian besar pergeseran
akan terjadi setelah sangat sedikit perbandingan (periksa contoh lagi). Oleh karena itu, efisiensi kasus
rata-rata harus jauh lebih baik daripada efisiensi terburuk. Memang itu adalah: untuk mencari dalam
teks acak, telah terbukti linier, yaitu, (n). Ada beberapa algoritma yang lebih canggih dan lebih efisien
untuk pencarian string. Yang paling banyak diketahui oleh mereka — oleh R. Boyer dan J. Moore —
diuraikan dalam Bagian 7.2 bersama dengan penyederhanaan yang disarankan oleh R. Horspool.

Latihan 3.2

Temukan jumlah perbandingan yang dibuat oleh versi sentinel pencarian berurutan dalam kasus
terburuk.

dalam kasus rata-rata jika probabilitas pencarian yang berhasil adalah p (0 ≤ p ≤ 1).

Seperti yang ditunjukkan pada Bagian 2.1, jumlah rata-rata perbandingan kunci yang dibuat oleh
pencarian berurutan (tanpa sentinel, di bawah asumsi standar tentang inputnya) diberikan oleh rumus

dimana p adalah probabilitas pencarian yang sukses. Tentukan, untuk n tetap, nilai-nilai p (0 ≤ p ≤ 1)
yang rumus ini menghasilkan nilai maksimum Cavg (n) dan nilai minimum Cavg (n).
Pengujian gadget Sebuah perusahaan ingin menentukan lantai tertinggi dari markas besar n-story-nya
dari mana sebuah gadget dapat jatuh tanpa putus. Perusahaan memiliki dua gadget yang identik untuk
bereksperimen. Jika salah satunya rusak, tidak dapat diperbaiki, dan eksperimen harus diselesaikan
dengan gadget yang tersisa. Rancang suatu algoritma dalam kelas efisiensi terbaik yang Anda bisa untuk
memecahkan masalah ini.

Tentukan jumlah perbandingan karakter yang dibuat oleh algoritma brute-force dalam mencari
pola GANDHI dalam teks

THERE_IS_MORE_TO_LIFE_THAN_INCREASING_ITS_SPEED

Asumsikan bahwa panjang teks — panjangnya 47 karakter — diketahui sebelum pencarian dimulai.

Berapa banyak perbandingan (baik yang berhasil maupun yang tidak berhasil) yang akan dibuat oleh
algoritma brute-force dalam mencari masing-masing pola berikut dalam teks biner dari seribu nol?

Sebuah. 00001 b. 10000 c. 01010

Berikan contoh teks panjang n dan pola panjang m yang merupakan input kasus terburuk untuk
algoritma pencocokan string brute-force. Persisnya berapa banyak perbandingan karakter yang akan
dibuat untuk input semacam itu?

Dalam menyelesaikan masalah string-matching, apakah akan ada keuntungan dalam membandingkan
pola dan karakter teks dari kanan ke kiri, bukan dari kiri ke kanan?

Pertimbangkan masalah penghitungan, dalam teks yang diberikan, jumlah substring yang dimulai
dengan A dan diakhiri dengan B. Misalnya, ada empat substring seperti itu di CABAAXBYA.

Rancanglah algoritma brute force untuk masalah ini dan tentukan kelas efisiensinya.

Rancang algoritma yang lebih efisien untuk masalah ini. [Gin04]

Tulis program visualisasi untuk algoritma pencocokan string brute-force.

Pencarian Kata Sebuah pengalihan populer di Amerika Serikat, teka-teki "kata temukan" (atau
"pencarian kata") meminta pemain untuk menemukan masing-masing satu set kata yang diberikan
dalam sebuah tabel persegi yang diisi dengan huruf-huruf tunggal. Sebuah kata dapat dibaca secara
horizontal (kiri atau kanan), vertikal (atas atau bawah), atau sepanjang 45 derajat diagonal (di salah satu
dari empat arah) yang dibentuk oleh sel-sel yang berdekatan secara bersebelahan dari tabel; mungkin
membentang di sekitar batas tabel, tetapi harus dibaca ke arah yang sama tanpa zig-zag. Sel yang sama
dari tabel dapat digunakan dengan kata yang berbeda, tetapi, dalam kata tertentu, sel yang sama dapat
digunakan tidak lebih dari satu kali. Tulis program komputer untuk memecahkan teka-teki ini.
Game Battleship Tuliskan sebuah program berdasarkan versi pencocokan pola brute-force untuk
memainkan game Battleship di komputer. Aturan mainnya adalah sebagai berikut. Ada dua lawan dalam
game (dalam hal ini, pemain manusia dan komputer). Permainan ini dimainkan di dua papan yang
identik (10 × 10 tabel kotak) di mana setiap lawan menempatkan kapalnya, tidak terlihat oleh lawan.
Setiap pemain memiliki lima kapal, yang masing-masing menempati sejumlah kotak di papan:
penghancur (dua kotak), kapal selam (tiga kotak), kapal penjelajah (tiga kotak), kapal perang (empat
kotak), dan pesawat terbang pembawa (lima kotak). Setiap kapal ditempatkan baik secara horizontal
maupun vertikal, dengan tidak ada dua kapal saling menyentuh. Permainan ini dimainkan oleh lawan
bergiliran “menembak” di kapal masing-masing. Hasil setiap bidikan ditampilkan baik sebagai hit atau
miss. Jika terjadi pukulan, pemain harus pergi lagi dan terus bermain sampai hilang. Tujuannya adalah
menenggelamkan semua kapal lawan sebelum lawan berhasil melakukannya terlebih dahulu. Untuk
menenggelamkan kapal, semua kotak yang ditempati oleh kapal harus dipukul.

D.Closest-Pair and Convex-Hull Problems


Masalah Pasangan Terdekat
Euclidean distance d (Pi, Pj) = √ [(xi-xj) 2 + (yi-yj) 2]
Temukan jarak minimal antara pasangan dalam satu set poin
Algoritma BruteForceClosestPoints (P)
// P adalah daftar poin
dmin ← ∞
for i ← 1 to n-1 do
for j ← i+1 to n do
d ← sqrt((xi-xj)2 + (yi-yj)2)
if d < dmin then
dmin ← d; index1 ← i; index2 ← j
return index1, index2

Perhatikan algoritma tidak harus menghitung akar kuadrat


Maka operasi dasar adalah mengkuadratkan

C (n) = ∑i = 1n-1 ∑j = i + 1n 2 = 2∑j = i + 1n (n-i) = 2n (n-1) / 2 ε Θ (n2)

Convex-Hull Problem
Seperangkat poin cembung jika untuk dua titik, P dan Q, seluruh segmen garis, PQ, ada di set.
Mengilustrasikan cembung dan perangkat non-cembung
Convex-hull dari satu set poin adalah poligon cembung terkecil yang berisi set.
Mengilustrasikan interpretasi karet-band dari lambung cembung
Cembung-hull dari satu set poin terdiri dari beberapa bagian dari poin dalam set.
Bagaimana cara menemukan subset ini? Pertimbangkan sosok karet-band. Properti apa yang
dibagikan segmen garis?
Sisa poin yang ditetapkan semuanya berada di satu sisi.
Dua poin (x1, y1), (x2, y2) membuat garis ax + by = c
Dimana a = y2-y1, b = x1-x2, dan c = x1y2 - y1x2

Dan membagi pesawat dengan ax + by - c < 0 dan ax + by - c > 0


Jadi kita hanya perlu memeriksa ax + by – c untuk sisa poin

Exhaustive Search
Pencarian yang luas membutuhkan pencarian semua solusi yang mungkin (biasanya objek
kombinatorial) untuk solusi terbaik.

Pencarian yang luas hanyalah pendekatan brute force untuk masalah kombinatorial. (Levitin)

Masalah Salesman Traveling


Jalur minimal melalui semua simpul grafik berbobot, mengunjungi setiap titik hanya satu kali.

Sirkuit Hamiltonian adalah siklus yang melewati semua simpul grafik tepat satu kali.

Jadi mereka sama untuk grafik yang tidak tertimbang. Bagaimana cara mengubah grafik berbobot?

Kami berkonsentrasi di Sirkuit Hamiltonian. Jika ada sirkuit, maka titik mana pun bisa menjadi titik awal
dan akhir. Setelah titik awal dipilih, kita hanya perlu urutan dari simpul n-1 yang tersisa. Kita bisa
menghasilkan semua kemungkinan urutan simpul dan menghitung panjang jalan.

Berapa banyak kombinasi yang mungkin? (n-1)!

Biaya untuk menghitung jalan? Θ (n)

Jadi total biaya untuk menemukan jalur terpendek? Θ (n!)

Perhatikan bahwa setengah jalur dapat dihilangkan dengan arah, jadi Θ (n! / 2)

Knapsack Problem
Diberikan item dengan bobot w1, w2, ..., wn dan nilai v1, v2, ..., vn dan knapsack kapasitas W, temukan
yang paling berharga (max ∑vj) yang cocok dalam ransel (∑wj ≤ W ).

Kita bisa menghasilkan semua himpunan bagian yang mungkin dari item, memeriksa kelayakan dan
kemudian nilai, memilih sub-set dengan nilai maksimal.

Berapa banyak himpunan bagian dari n item? 2n

Kedua masalah adalah NP-hard, yang berarti tidak ada algoritma tahu yang memecahkan masalah dalam
waktu polinomial.
Assignment Problem
Tugasi n pekerja ke n pekerjaan. Setiap pekerja mengenakan tarif berbeda untuk setiap pekerjaan yang
ditentukan oleh matriks biaya C [i, j].

Perhatikan setiap pekerja harus ditugaskan untuk satu dan hanya satu pekerjaan.

Matriks biaya menentukan contoh masalah.

Suatu solusi dapat ditentukan oleh n-tupel yang menentukan penugasan pekerjaan untuk pekerja
pertama, kedua, dll.

Kemudian pencarian lengkap akan menghasilkan semua permutasi dan mencari biaya minimal.

Biaya dari algoritma ini? Θ (n!)

Ada algoritma yang lebih baik yang disebut metode Hungaria yang dikembangkan oleh Kong dan
Egervary.

E.Exhaustive Search
Untuk masalah diskrit di mana tidak ada metode solusi yang efisien yang diketahui, mungkin perlu
menguji setiap kemungkinan secara berurutan untuk menentukan apakah itu adalah solusinya.
Pemeriksaan yang mendalam seperti semua kemungkinan dikenal sebagai pencarian lengkap, pencarian
langsung, atau metode "brute force". Kecuali ternyata NP-masalah setara dengan P-masalah, yang
tampaknya tidak mungkin tetapi belum terbukti, NP-masalah hanya dapat diselesaikan dengan
pencarian lengkap dalam kasus terburuk.

F.Depth-First Search and Breath-First Search


Traversal grafik dan digraf
Untuk melintasi berarti mengunjungi simpul dalam beberapa urutan sistematis. Anda harus terbiasa
dengan berbagai metode lintasan untuk pepohonan:
praorder: kunjungi setiap node sebelum anak-anaknya.
postorder: kunjungi setiap node setelah anak-anaknya.
inorder (hanya untuk pohon biner): kunjungi subtree kiri, node, subtree kanan.
Kami juga melihat jenis lain, pemesanan topologi traversal, ketika saya berbicara tentang jalur
terpendek.

Hari ini, kita akan melihat dua traversal lainnya: breadth first search (BFS) dan depth first search (DFS).
Kedua konstruksi ini mencakup pohon dengan properti tertentu yang berguna dalam algoritma grafik
lainnya. Kita akan mulai dengan mendeskripsikannya dalam grafik yang tidak terarah, tetapi keduanya
sangat berguna untuk graf berarah.

Breadth First Search


Ini bisa diartikan sebagai seperti algoritma Dijkstra untuk jalur terpendek, tetapi dengan setiap tepi
memiliki panjang yang sama. Namun itu jauh lebih sederhana dan tidak memerlukan struktur data. Kami
hanya menyimpan pohon (pohon pencarian pertama yang luas), daftar simpul yang akan ditambahkan
ke pohon, dan tanda (variabel Boolean) pada simpul untuk mengatakan apakah mereka berada di pohon
atau daftar.
luasnya pencarian pertama:
unmark all vertices
choose some starting vertex x
mark x
list L = x
tree T = x
while L nonempty
choose some vertex v from front of list
visit v
for each unmarked neighbor w
mark w
add it to end of list
add edge vw to T

Sangat penting bahwa Anda menghapus simpul dari ujung lain dari daftar daripada yang Anda
tambahkan ke, sehingga daftar bertindak sebagai antrian (penyimpanan fifo) daripada stack (lifo).
Langkah "kunjungi v" akan diisi nanti tergantung pada apa yang Anda gunakan BFS untuk, seperti halnya
pohon traversal biasanya melibatkan melakukan sesuatu di setiap titik yang tidak ditentukan sebagai
bagian dari algoritma dasar. Jika vertex memiliki beberapa tetangga yang tidak bertanda, akan sama-
sama benar untuk mengunjungi mereka dalam urutan apa pun. Mungkin metode yang paling mudah
untuk diterapkan adalah dengan hanya mengunjungi mereka dalam urutan daftar adjacency untuk v
disimpan.
Mari buktikan beberapa fakta dasar tentang algoritma ini. Pertama, setiap titik jelas ditandai paling
banyak sekali, ditambahkan ke daftar paling banyak sekali (karena itu hanya terjadi ketika ditandai), dan
karena itu dihapus dari daftar paling banyak sekali. Karena waktu untuk memproses suatu verteks
sebanding dengan panjang daftar kedekatannya, total waktu untuk seluruh algoritma adalah O (m).

Selanjutnya, mari kita lihat pohon T yang dibangun oleh algoritma. Kenapa ini pohon? Jika Anda
memikirkan setiap sisi vw sebagai menunjuk "ke atas" dari w ke v, maka masing-masing ujung menunjuk
dari titik yang dikunjungi kemudian ke salah satu yang dikunjungi sebelumnya. Mengikuti tepi yang
berurutan ke atas hanya bisa berhenti di x (yang tidak memiliki tepi ke atas darinya) sehingga setiap titik
di T memiliki jalur ke x. Ini berarti bahwa T setidaknya merupakan subgraph terhubung dari G. Sekarang
mari kita buktikan bahwa itu adalah sebuah pohon. Sebuah pohon hanyalah graf yang terhubung dan
asiklik, jadi kita hanya perlu menunjukkan bahwa T tidak memiliki siklus. Dalam siklus apa pun, tidak
peduli bagaimana Anda mengorientasikan ujung-ujungnya sehingga satu arah adalah "ke atas" dan yang
lain "ke bawah", selalu ada titik "bawah" yang memiliki dua sisi ke atas dari itu. Tetapi dalam T, setiap
titik memiliki paling banyak satu tepi ke atas, sehingga T tidak dapat memiliki siklus. Karena itu, T benar-
benar adalah sebuah pohon. Hal ini dikenal sebagai pohon pencarian pertama yang luas.

Kami juga ingin tahu bahwa T adalah pohon rentang, yaitu bahwa jika grafik terhubung (setiap titik
memiliki beberapa jalur ke akar x) maka setiap titik akan terjadi di suatu tempat di T. Kita dapat
membuktikan ini dengan induksi pada panjang jalur terpendek ke x. Jika v memiliki jalur panjang k, mulai
vw -...- x, maka w memiliki jalur panjang k-1, dan dengan induksi akan dimasukkan ke T. Tapi kemudian
ketika kita mengunjungi kita akan melihat tepi vw , dan jika v belum ada di pohon, itu akan
ditambahkan.

Luas traversal pertama dari G berhubungan dengan beberapa jenis traversal pohon di T. Tetapi itu tidak
preorder, postorder, atau bahkan inorder traversal. Sebaliknya, traversal berjalan satu tingkat pada
suatu waktu, kiri ke kanan dalam tingkat (di mana tingkat didefinisikan hanya dalam jarak dari akar
pohon). Misalnya, pohon berikut ini digambar dengan simpul yang diberi nomor dalam urutan yang
mungkin diikuti oleh pencarian pertama yang luas:
1
/ | \
2 3 4
/ \ |
5 6 7
| / | \
8 9 10 11
Bukti bahwa simpul dalam urutan ini dengan luasnya pencarian pertama berjalan dengan induksi pada
nomor tingkat. Dengan hipotesis induksi, BFS daftar semua simpul pada tingkat k-1 sebelum mereka
pada tingkat k. Oleh karena itu ia akan menempatkan ke L semua simpul pada tingkat k sebelum semua
level k + 1, dan oleh karena itu daftar mereka tingkat k sebelum level k + 1. (Ini benar-benar bukti
meskipun terdengar seperti alasan melingkar.)
Pohon pencarian pertama yang luas memiliki properti yang bagus: Setiap sisi G dapat diklasifikasikan
menjadi satu dari tiga kelompok. Beberapa sisi berada di T sendiri. Beberapa menghubungkan dua
simpul pada tingkat yang sama T. Dan yang tersisa menghubungkan dua simpul pada dua tingkat yang
berdekatan. Tidaklah mungkin bagi sebuah edge untuk melewati level.

Oleh karena itu, keluasan pohon pencarian pertama benar-benar merupakan pohon jalur terpendek
mulai dari akarnya. Setiap titik memiliki jalur ke akar, dengan panjang jalur yang sama dengan tingkatnya
(cukup ikuti pohon itu sendiri), dan tidak ada jalan yang dapat melompati satu tingkat sehingga ini
benar-benar jalur terpendek.

Depth first search


Pencarian pertama Depth adalah cara lain untuk melintasi grafik, yang terkait erat dengan preorder
traversal dari pohon. Ingat bahwa preorder traversal hanya mengunjungi setiap node sebelum anak-
anaknya. Sangat mudah untuk memprogram sebagai rutin rekursif:
preorder(node v)
{
visit(v);
for each child w of v
preorder(w);
}
Untuk mengubah ini menjadi algoritma grafik traversal, pada dasarnya kita mengganti "anak" dengan
"tetangga". Tetapi untuk mencegah loop yang tidak terbatas, kami hanya ingin mengunjungi setiap titik
sekali. Sama seperti di BFS kita dapat menggunakan mark untuk melacak simpul yang telah dikunjungi,
dan tidak mengunjungi mereka lagi. Juga, sama seperti di BFS, kita dapat menggunakan pencarian ini
untuk membangun pohon rentang dengan sifat-sifat berguna tertentu.
dfs(vertex v)
{
visit(v);
for each neighbor w of v
if w is unvisited
{
dfs(w);
add edge vw to tree T
}
}
Algoritma pencarian kedalaman mendalam secara keseluruhan kemudian cukup menginisialisasi satu set
penanda sehingga kita dapat mengetahui simpul mana yang dikunjungi, memilih simpul awal x,
menginisialisasi T pohon ke x, dan memanggil dfs (x). Persis seperti dalam pencarian pertama yang luas,
jika sebuah titik memiliki beberapa tetangganya akan sama-sama benar untuk melewatinya dalam
urutan apa pun. Saya tidak hanya mengatakan "untuk setiap tetangga v yang tidak dikunjungi" karena
sangat penting untuk menunda tes apakah verteks dikunjungi sampai panggilan rekursif untuk tetangga
sebelumnya selesai.
Bukti bahwa ini menghasilkan pohon rentang (pohon pencarian pertama kedalaman) pada dasarnya
sama dengan untuk BFS, jadi saya tidak akan mengulanginya. Namun sementara pohon BFS biasanya
"pendek dan lebat", pohon DFS biasanya "panjang dan berserabut".

Sama seperti yang kami lakukan untuk BFS, kami dapat menggunakan DFS untuk mengklasifikasikan tepi
G ke dalam tipe. Entah ujung vw ada di pohon DFS itu sendiri, v adalah leluhur dari w, atau w adalah
leluhur dari v. (Dua kasus terakhir ini harus dianggap sebagai tipe tunggal, karena mereka hanya
berbeda berdasarkan urutan yang kita lihat simpul di.) Apa artinya ini adalah bahwa jika v dan w berada
dalam subtipe yang berbeda dari v, kita tidak dapat memiliki keunggulan dari v ke w. Ini karena jika ada
tepi seperti itu dan (katakanlah) v dikunjungi terlebih dahulu, maka satu-satunya cara kita akan
menghindari menambahkan vw ke pohon DFS adalah jika kita dikunjungi selama salah satu panggilan
rekursif dari v, tetapi kemudian v akan menjadi leluhur dari w.

BAB 4: Decrease and Conquer

A.Definisi
Decrease and conquer adalah metode desain algoritma dengan mereduksi persoalan menjadi beberapa
sub-persoalan yang lebih kecil, tetapi selanjutnya hanya memproses satu sub-persoalan saja. Metode ini
memiliki dua tahapan, antara lain:
Decrease, yaitu mereduksi persoalan menjadi beberapa persoalan yang lebih kecil (biasanya dua sub-
persoalan).
Conquer, yaitu memproses satu sub-persoalan secara rekursif.
Terdapat tiga varian pengurangan pada metode decrease and conquer, antara lain decrease by a
constant, decrease by a constant factor, dan decrease by a variable size.
Decrease by a constant
Pada varian ini, ukuran instans persoalan direduksi sebesar konstanta yang sama setiap iterasi algoritma.
Umumnya, konstanta yang digunakan bernilai sama dengan 1. Salah satu contoh dari varian ini adalah
penyelesaian perpangkatan an. Penyelesaiannya dapat dilihat di bawah ini.

Dengan metode decrease and conquer, maka:

Kompleksitas waktu (berdasarkan jumlah kali) adalah sebagai berikut:

Decrease by a constant factor


Pada varian ini, ukuran instans persoalan direduksi sebesar faktor konstanta yang sama setiap iterasi
algoritma. Salah satu contoh menggunakan varian ini adalah binary search, yang bila diilustrasikan
prosesnya menjadi seperti berikut.
Decrease by a variable size
Pada varian ini, ukuran instans persoalan direduksi bervariasi pada setiap iterasi algoritma. Contoh
algoritma yang menggunakan varian pengurangan decrease by a variable size adalah algoritma Euclid.
Penyelesaian algoritma Euclid adalah sebagai berikut.
gcd(m,n) = gcd(n, m mod n)
Contoh:
gcd(80,12) --> 80:12 = 6 sisa 8
gcd (12, 8) --> 12:8 = 1 sisa 4
gcd (8,4) --> 8:4 = 2 sisa 0
Jadi, gcd (80,12) = gcd (12, 8) = gcd (8, 4) = gcd (4, 0) = 4.

B.Three Major Varian of Decrease-and-Conquer


Pendekatan divide-and-conquer sudah dibahas, yang termasuk langkah-langkah berikut:
Bagilah masalah menjadi sejumlah subproblem yang merupakan contoh yang lebih kecil dari masalah
yang sama.
Menaklukkan sub masalah dengan menyelesaikannya secara rekursif. Jika ukuran subproblem cukup
kecil, bagaimanapun, cukup selesaikan masalah sub secara langsung.
Gabungkan solusi untuk masalah sub ke dalam solusi untuk masalah asli.

Demikian pula, pendekatan karya penurunan-dan-menaklukkan, itu juga termasuk langkah-langkah


berikut:
Turunkan atau kurangi contoh masalah ke contoh yang lebih kecil dari masalah yang sama dan
perpanjang solusi.
Taklukkan masalah dengan memecahkan masalah yang lebih kecil dari masalah.
Perluas solusi dari instance yang lebih kecil untuk mendapatkan solusi untuk masalah asli.
Ide dasar teknik penurunan-dan-menaklukkan didasarkan pada pemanfaatan hubungan antara solusi
untuk contoh tertentu dari masalah dan solusi untuk contoh yang lebih kecil. Pendekatan ini juga dikenal
sebagai pendekatan inkremental atau induktif.

"Divide-and-Conquer" vs "Decrease-and-Conquer":
Seperti Wikipedia, beberapa penulis menganggap bahwa nama "membagi dan menaklukkan" harus
digunakan hanya ketika setiap masalah dapat menghasilkan dua atau lebih subproblem. Nama menurun
dan menaklukkan telah diusulkan bukan untuk kelas single-subproblem. Menurut definisi ini, Merge Sort
dan Quick Sort berada di bawah membagi dan menaklukkan (karena ada 2 sub-masalah) dan Pencarian
Biner datang di bawah penurunan dan menaklukkan (karena ada satu sub-masalah).

Implementasi Penurunan dan Penaklukan:

Pendekatan ini dapat diimplementasikan sebagai top-down atau bottom-up.


Pendekatan top-down: Selalu mengarah pada penerapan masalah secara rekursif.
Pendekatan bottom-up: Biasanya diimplementasikan dengan cara berulang, dimulai dengan solusi untuk
masalah terkecil dari masalah.
Variasi Penurunan dan Menaklukkan:

Ada tiga variasi utama penurunan-dan-menaklukkan:

Turun dengan konstan


Turun dengan faktor konstan
Penurunan ukuran variabel
Penurunan oleh Konstan: Dalam variasi ini, ukuran instance dikurangi oleh konstanta yang sama pada
setiap iterasi dari algoritma. Biasanya, konstanta ini sama dengan satu, meskipun pengurangan ukuran
konstan lainnya terjadi sesekali. Di bawah ini adalah contoh masalah:

Penyisipan semacam
Algoritma pencarian grafik: DFS, BFS
Pemilahan topologi
Algoritma untuk menghasilkan permutasi, himpunan bagian
Turun dengan faktor Konstan: Teknik ini menyarankan pengurangan contoh masalah oleh faktor konstan
yang sama pada setiap iterasi dari algoritma. Dalam sebagian besar aplikasi, faktor konstan ini sama
dengan dua. Pengurangan oleh faktor lain dari dua sangat jarang.

Penurunan oleh algoritma faktor konstan sangat efisien terutama ketika faktor lebih besar dari 2 seperti
pada masalah koin palsu. Di bawah ini adalah contoh masalah:

Pencarian biner
Masalah koin palsu
Perkalian petani Rusia
Variabel-Ukuran-Turun: Dalam variasi ini, pola pengurangan ukuran bervariasi dari satu iterasi algoritma
ke algoritma lainnya.
Seperti, dalam masalah menemukan gcd dari dua angka meskipun nilai argumen kedua selalu lebih kecil
di sisi kanan daripada di sisi kiri, itu berkurang baik oleh konstanta maupun oleh faktor konstan. Di
bawah ini adalah contoh masalah:

Menghitung masalah median dan seleksi.


Pencarian Interpolasi
Algoritma Euclid
Mungkin ada kasus masalah yang dapat diselesaikan dengan penurunan-oleh-konstan serta penurunan-
oleh-faktor variasi, tetapi implementasi dapat berupa rekursif atau iteratif. Implementasi berulang
mungkin memerlukan upaya pengkodean lebih lanjut, namun mereka menghindari kelebihan beban
yang menyertai rekursi.

C.Insertion Sort
Penyisipan semacam adalah algoritma pengurutan sederhana yang bekerja dengan cara kita
mengurutkan kartu remi di tangan kita.
Algoritma
// Sort arr [] dari ukuran n
insertionSort (arr, n)
Loop dari i = 1 ke n-1.
…… a) Pilih elemen arr [i] dan masukkan ke dalam urutan array yang diurutkan [0 ... i-1]

Contoh:

Contoh lain:
12, 11, 13, 5, 6

Mari kita loop untuk i = 1 (elemen kedua dari array) ke 5 (Ukuran array input)

i = 1. Karena 11 lebih kecil dari 12, pindah 12 dan masukkan 11 sebelum 12


11, 12, 13, 5, 6

i = 2. 13 akan tetap pada posisinya karena semua elemen dalam A [0..I-1] lebih kecil dari 13
11, 12, 13, 5, 6

i = 3. 5 akan pindah ke awal dan semua elemen lain dari 11 hingga 13 akan bergerak satu posisi di depan
posisi mereka saat ini.
5, 11, 12, 13, 6

i = 4. 6 akan pindah ke posisi setelah 5, dan elemen dari 11 hingga 13 akan bergerak satu posisi di depan
posisi mereka saat ini.
5, 6, 11, 12, 13
D.Topological Sorting
Pemilahan topologi untuk Directed Acyclic Graph (DAG) adalah pengurutan linear dari simpul-simpul
sedemikian rupa sehingga untuk setiap ujung terarah, vertex u datang sebelum v dalam urutan.
Penyortiran Topologi untuk grafik tidak dimungkinkan jika grafik bukan DAG.
Misalnya, pemilahan topologi dari grafik berikut adalah "5 4 2 3 1 0". Bisa ada lebih dari satu pemilahan
topologi untuk grafik. Misalnya, pemilahan topologi lain dari grafik berikut adalah "4 5 2 3 1 0". Simpul
pertama dalam pemilahan topologi selalu berupa vertex dengan derajat sebagai 0 (titik tanpa ujung
yang masuk).

Topological Sorting vs Depth First Traversal (DFS):


Dalam DFS, kami mencetak titik dan kemudian secara rekursif memanggil DFS untuk simpul yang
berdekatan. Dalam pemilahan topologi, kita perlu mencetak titik sudut sebelum simpul yang
berdekatan. Sebagai contoh, dalam grafik yang diberikan, vertex ‘5’ harus dicetak sebelum vertex ‘0’,
tetapi tidak seperti DFS, vertex ‘4’ juga harus dicetak sebelum vertex ‘0’. Jadi pemilahan Topologi
berbeda dari DFS. Sebagai contoh, DFS dari grafik yang ditampilkan adalah "5 2 3 1 0 4", tetapi ini bukan
pemilahan topologi

BAB 5: Devide and Conquer

A.Definisi
divide and conquer merupakan algoritme yang sangat populer. Prinsip dari algoritme ini adalah
memecah-mecah masalah yang ada menjadi beberapa bagian kecil sehingga lebih mudah untuk
diselesaikan.

Langkah-langkah umum algoritme Divide and Conquer adalah: [1]

Divide: Membagi masalah menjadi beberapa upa-masalah yang memiliki kemiripan dengan masalah
semula namun berukuran lebih kecil (idealnya berukuran hampir sama).
Conquer: Memecahkan (menyelesaikan) masing-masing upa-masalah (secara rekursif).
Combine: Menggabungkan solusi masing-masing masalah sehingga membentuk solusi masalah semula.
B.Mergesort
Seperti QuickSort, Merge Sort adalah algoritma Divide and Conquer. Ini membagi array input dalam dua
bagian, panggilan itu sendiri untuk dua bagian dan kemudian menggabungkan dua bagian yang disortir.
Fungsi gabungan () digunakan untuk menggabungkan dua bagian. Penggabungan (arr, l, m, r) adalah
proses kunci yang mengasumsikan bahwa arr [l..m] dan arr [m + 1..r] diurutkan dan menggabungkan dua
sub-array yang diurutkan menjadi satu. Lihat implementasi C berikut untuk detailnya.
MergeSort(arr[], l, r)
If r > l
1. Find the middle point to divide the array into two halves:
middle m = (l+r)/2
2. Call mergeSort for first half:
Call mergeSort(arr, l, m)
3. Call mergeSort for second half:
Call mergeSort(arr, m+1, r)
4. Merge the two halves sorted in step 2 and 3:
Call merge(arr, l, m, r)

Diagram berikut dari wikipedia menunjukkan proses penggabungan lengkap untuk contoh array {38, 27,
43, 3, 9, 82, 10}. Jika kita melihat lebih dekat pada diagram, kita dapat melihat bahwa array secara
rekursif dibagi dalam dua bagian sampai ukuran menjadi 1. Setelah ukuran menjadi 1, proses
penggabungan datang ke dalam tindakan dan mulai menggabungkan kembali array sampai array
lengkap digabung
C.Quicksort
Quicksort merupakan Algoritme pengurutan yang dikembangkan oleh Tony Hoare. performa rata-rata
pengurutan O(n log n) untuk mengurutkan n item. Algoritme ini juga dikenal sebagai Partition-Exchange
Sort atau disebut sebagai Sorting Pergantian Pembagi. Pada kasus terburuknya, algoritme ini membuat
perbandingan O(n2), malaupun kejadian seperti ini sangat langka. Quicksort sering lebih cepat dalam
praktiknya daripada algoritme urut gabung dan heapshort.[1] Dan juga, urutan dan referensi lokalisasi
memori quicksort bekerja lebih baik dengan menggunakan cache CPU, jadi keseluruhan sorting dapat
dilakukan hanya dengan ruang tambahan O(log n).[2]

Quicksort merupakan sorting pembanding dan pada implementasi efisien tidak merupakan algoritme
sorting yang stabil

Quicksort merupakan Algoritme Pembagi. Pertama quicksort membagi list yang besar menjadi dua buah
sub list yang lebih kecil: element kecil dan element besar. Quicksort kemudian dapat menyortir sub list
itu secara rekursif.

Langkah-Langkah pengerjaannya ialah:

1.Ambil sebuah elemen, yang disebut dengan pivot, pada sebuah daftar.

2.Urutkan kembali sebuah list sehingga elemen dengan nilai yang kecil dari pivot berada sebelum pivot,
sedangkan seluruh element yang memiliki nilai yang lebih besar dari pivot berada setelahnya (nilai yang
sama dapat berada pada pivot setelahnya). Setelah pemisahan, pivot berada pada posisi akhirnya.
Operasi ini disebut Partition.

3.Sub list kemudian disortir secara recursif dari elemen yang lebih kecil dan sub list dari elemen yang
lebih besar.

Kasus dasar dari rekusrif ialah list dari besaran nol atau satu, yang tidak perlu untuk di sorting.

Anda mungkin juga menyukai