Apa masalah dunia nyata di mana pendekatan rekursif adalah solusi alami selain pencarian mendalam-pertama (DFS)?
(Saya tidak menganggap Menara Hanoi , bilangan Fibonacci , atau masalah dunia nyata faktorial. Mereka sedikit dibuat-buat dalam pikiran saya.)
Jawaban:
Ada banyak contoh matematika di sini, tetapi Anda menginginkan contoh dunia nyata , jadi dengan sedikit pemikiran, ini mungkin yang terbaik yang bisa saya tawarkan:
Anda menemukan seseorang yang telah tertular infeksi menular tertentu, yang tidak fatal, dan sembuh sendiri dengan cepat (Tipe A), Kecuali satu dari 5 orang (Kami akan menyebutnya tipe B) yang terinfeksi secara permanen dan tidak menunjukkan gejala dan hanya bertindak sebagai penyebar.
Ini menciptakan gelombang malapetaka yang cukup menjengkelkan ketika tipe B menginfeksi banyak tipe A.
Tugas Anda adalah melacak semua tipe B dan mengimunisasi mereka untuk menghentikan tulang punggung penyakit. Sayangnya, Anda tidak dapat memberikan pengobatan nasional untuk semua, karena orang-orang yang bertipe A juga alergi mematikan terhadap obat yang bekerja untuk tipe B.
Cara Anda melakukan ini, akan menjadi penemuan sosial, mengingat orang yang terinfeksi (Tipe A), memilih semua kontak mereka dalam seminggu terakhir, menandai setiap kontak di tumpukan. Saat Anda menguji seseorang terinfeksi, tambahkan mereka ke antrian "tindak lanjut". Ketika seseorang adalah tipe B, tambahkan mereka ke "tindak lanjut" di kepala (karena Anda ingin menghentikan ini dengan cepat).
Setelah memproses orang tertentu, pilih orang tersebut dari depan antrian dan terapkan imunisasi jika diperlukan. Dapatkan semua kontak mereka yang sebelumnya tidak dikunjungi, lalu uji untuk melihat apakah mereka terinfeksi.
Ulangi hingga antrian orang yang terinfeksi menjadi 0, lalu tunggu wabah lainnya ..
(Oke, ini agak berulang, tetapi ini adalah cara berulang untuk memecahkan masalah rekursif, dalam hal ini, lintasan pertama yang luas dari basis populasi mencoba menemukan kemungkinan jalan menuju masalah, dan selain itu, solusi berulang seringkali lebih cepat dan lebih efektif , dan saya secara kompulsif menghapus rekursi di mana-mana sehingga menjadi naluriah .... Sialan!)
sumber
Contoh rekursi dunia nyata
sumber
Bagaimana dengan apa pun yang melibatkan struktur direktori dalam sistem file. Menemukan file secara berulang, menghapus file, membuat direktori, dll.
Berikut adalah implementasi Java yang secara rekursif mencetak konten direktori dan subdirektorinya.
import java.io.File; public class DirectoryContentAnalyserOne implements DirectoryContentAnalyser { private static StringBuilder indentation = new StringBuilder(); public static void main (String args [] ){ // Here you pass the path to the directory to be scanned getDirectoryContent("C:\\DirOne\\DirTwo\\AndSoOn"); } private static void getDirectoryContent(String filePath) { File currentDirOrFile = new File(filePath); if ( !currentDirOrFile.exists() ){ return; } else if ( currentDirOrFile.isFile() ){ System.out.println(indentation + currentDirOrFile.getName()); return; } else{ System.out.println("\n" + indentation + "|_" +currentDirOrFile.getName()); indentation.append(" "); for ( String currentFileOrDirName : currentDirOrFile.list()){ getPrivateDirectoryContent(currentDirOrFile + "\\" + currentFileOrDirName); } if (indentation.length() - 3 > 3 ){ indentation.delete(indentation.length() - 3, indentation.length()); } } } }
sumber
Quicksort , merge sort , dan kebanyakan N-log N sort lainnya.
sumber
Teladan Matt Dillard bagus. Secara lebih umum, setiap berjalan di pohon umumnya dapat ditangani dengan sangat mudah dengan rekursi. Misalnya, mengompilasi pohon parse, berjalan di atas XML atau HTML, dll.
sumber
Rekursi sering digunakan dalam implementasi algoritma Backtracking . Untuk aplikasi "dunia nyata" ini, bagaimana dengan pemecah Sudoku ?
sumber
Rekursi dapat dilakukan jika suatu masalah dapat diselesaikan dengan membaginya menjadi sub-masalah, yang dapat menggunakan algoritme yang sama untuk menyelesaikannya. Algoritme pada pohon dan daftar yang diurutkan sangat cocok. Banyak masalah dalam geometri komputasi (dan permainan 3D) dapat diselesaikan secara rekursif dengan menggunakan pohon partisi ruang biner (BSP), subdivisi lemak , atau cara lain untuk membagi dunia menjadi sub-bagian.
Rekursi juga sesuai saat Anda mencoba menjamin kebenaran algoritme. Dengan adanya fungsi yang mengambil input yang tidak dapat diubah dan mengembalikan hasil yang merupakan kombinasi panggilan rekursif dan non-rekursif pada input, biasanya mudah untuk membuktikan bahwa fungsi tersebut benar (atau tidak) menggunakan induksi matematika. Seringkali sulit untuk melakukan ini dengan fungsi iteratif atau dengan input yang mungkin bermutasi. Ini dapat berguna saat berhadapan dengan kalkulasi keuangan dan aplikasi lain yang sangat mengutamakan kebenaran.
sumber
Tentunya banyak kompiler di luar sana yang banyak menggunakan rekursi. Bahasa komputer secara inheren rekursif sendiri (yaitu, Anda dapat menyematkan pernyataan 'jika' di dalam pernyataan 'jika' lainnya, dll.).
sumber
Menonaktifkan / menyetel hanya-baca untuk semua kontrol anak dalam kontrol penampung. Saya perlu melakukan ini karena beberapa kontrol anak adalah wadah itu sendiri.
sumber
Siklus Evaluasi / Terapkan terkenal dari SICP
(sumber: mit.edu )
Berikut definisi eval:
Berikut definisi dari aplikasinya:
Berikut definisi eval-sequence:
eval
->apply
->eval-sequence
->eval
sumber
Rekursi digunakan dalam hal-hal seperti pohon BSP untuk deteksi tabrakan dalam pengembangan game (dan area serupa lainnya).
sumber
Orang sering kali mengurutkan tumpukan dokumen menggunakan metode rekursif. Misalnya, bayangkan Anda menyortir 100 dokumen dengan nama di dalamnya. Pertama-tama, tempatkan dokumen ke dalam tumpukan berdasarkan huruf pertama, lalu urutkan setiap tumpukan.
Mencari kata-kata dalam kamus sering kali dilakukan dengan teknik seperti pencarian biner, yang bersifat rekursif.
Dalam organisasi, atasan sering memberikan perintah kepada kepala departemen, yang pada gilirannya memberi perintah kepada manajer, dan sebagainya.
sumber
Persyaratan dunia nyata yang saya dapatkan baru-baru ini:
Persyaratan A: Terapkan fitur ini setelah memahami Persyaratan A.
sumber
Parser dan compiler dapat ditulis dengan metode keturunan rekursif. Bukan cara terbaik untuk melakukannya, karena alat seperti lex / yacc menghasilkan parser yang lebih cepat dan efisien, tetapi secara konseptual sederhana dan mudah diimplementasikan, sehingga tetap umum.
sumber
Rekursi diterapkan pada masalah (situasi) di mana Anda dapat memecahnya (menguranginya) menjadi bagian-bagian yang lebih kecil, dan setiap bagian terlihat mirip dengan masalah aslinya.
Contoh bagus tentang hal-hal yang berisi bagian-bagian kecil yang mirip dengan dirinya sendiri adalah:
Rekursi adalah teknik untuk terus memecah masalah menjadi potongan-potongan kecil dan kecil, sampai salah satu potongan itu menjadi cukup kecil untuk menjadi sepotong kue. Tentu saja, setelah Anda memecahnya, Anda kemudian harus "menjahit" hasilnya kembali dalam urutan yang benar untuk membentuk solusi total dari masalah awal Anda.
Beberapa algoritme pengurutan rekursif, algoritme berjalan di pohon, algoritme peta / reduksi, divide-and-conquer adalah contoh dari teknik ini.
Dalam pemrograman komputer, sebagian besar bahasa jenis panggilan-kembali berbasis tumpukan sudah memiliki kemampuan yang dibangun untuk rekursi: yaitu
sumber
Saya memiliki sistem yang menggunakan rekursi ekor murni di beberapa tempat untuk mensimulasikan mesin negara.
sumber
Beberapa contoh rekursi yang bagus ditemukan dalam bahasa pemrograman fungsional . Dalam bahasa pemrograman fungsional ( Erlang , Haskell , ML / OCaml / F # , dll.), Sangat umum untuk memiliki pemrosesan daftar menggunakan rekursi.
Ketika berhadapan dengan daftar dalam bahasa gaya-OOP imperatif yang khas, sangat umum untuk melihat daftar diimplementasikan sebagai daftar tertaut ([item1 -> item2 -> item3 -> item4]). Namun, dalam beberapa bahasa pemrograman fungsional, Anda menemukan bahwa daftar itu sendiri diimplementasikan secara rekursif, di mana "kepala" daftar menunjuk ke item pertama dalam daftar, dan "ekor" menunjuk ke daftar yang berisi item lainnya ( [item1 -> [item2 -> [item3 -> [item4 -> []]]]]). Cukup kreatif menurut saya.
Penanganan daftar ini, bila dikombinasikan dengan pencocokan pola, SANGAT ampuh. Katakanlah saya ingin menjumlahkan daftar angka:
Ini pada dasarnya mengatakan "jika kita dipanggil dengan daftar kosong, kembalikan 0" (memungkinkan kita untuk menghentikan rekursi), jika tidak mengembalikan nilai head + nilai Sum yang dipanggil dengan item yang tersisa (karenanya, rekursi kita).
Misalnya, saya mungkin memiliki daftar URL , menurut saya memisahkan semua URL yang ditautkan ke setiap URL, lalu saya mengurangi jumlah total tautan ke / dari semua URL untuk menghasilkan "nilai" untuk halaman (pendekatan yang digunakan Google mengambil dengan PageRank dan yang dapat Anda temukan didefinisikan dalam kertas MapReduce asli ). Anda juga dapat melakukan ini untuk menghasilkan jumlah kata dalam dokumen. Dan banyak, banyak, banyak hal lainnya juga.
Anda dapat memperluas pola fungsional ini ke semua jenis kode MapReduce di mana Anda dapat mengambil daftar sesuatu, mengubahnya, dan mengembalikan sesuatu yang lain (apakah daftar lain, atau beberapa perintah zip pada daftar).
sumber
XML, atau melintasi apapun yang berupa pohon. Meskipun, sejujurnya, saya hampir tidak pernah menggunakan rekursi dalam pekerjaan saya.
sumber
Umpan balik berputar dalam organisasi hierarki.
Atasan teratas memberi tahu eksekutif puncak untuk mengumpulkan umpan balik dari semua orang di perusahaan.
Setiap eksekutif mengumpulkan bawahan langsungnya dan memberi tahu mereka untuk mengumpulkan umpan balik dari bawahan langsung mereka.
Dan di telepon.
Orang yang tidak memiliki bawahan langsung - simpul daun di pohon - memberikan umpan balik mereka.
Umpan balik berjalan kembali ke atas pohon dengan setiap manajer menambahkan umpan baliknya sendiri.
Akhirnya semua umpan balik membuatnya kembali ke atasan.
Ini adalah solusi alami karena metode rekursif memungkinkan pemfilteran di setiap level - menyusun duplikat dan menghilangkan umpan balik ofensif. Atasan teratas dapat mengirim email global dan meminta setiap karyawan melaporkan umpan balik langsung kembali kepadanya, tetapi ada masalah "Anda tidak bisa menangani kebenaran" dan "Anda dipecat", jadi rekursi bekerja paling baik di sini.
sumber
Misalkan Anda sedang membangun CMS untuk situs web, di mana halaman Anda berada dalam struktur pohon, dengan misalnya root menjadi halaman beranda.
Misalkan juga permintaan {user | client | customer | boss} Anda agar Anda menempatkan jejak runut tautan di setiap halaman untuk menunjukkan posisi Anda di pohon.
Untuk halaman n tertentu, Anda mungkin ingin berjalan ke induk dari n, dan induknya, dan seterusnya, secara rekursif untuk membuat daftar node kembali ke akar pohon halaman.
Tentu saja, Anda menekan db beberapa kali per halaman dalam contoh itu, jadi Anda mungkin ingin menggunakan beberapa SQL aliasing di mana Anda mencari page-table sebagai a, dan page-table lagi sebagai b, dan bergabung dengan a.id dengan b.parent sehingga Anda membuat database melakukan rekursif bergabung. Sudah lama, jadi sintaks saya mungkin tidak membantu.
Kemudian lagi, Anda mungkin hanya ingin menghitung ini sekali dan menyimpannya dengan rekaman halaman, hanya memperbaruinya jika Anda memindahkan halaman. Itu mungkin akan lebih efisien.
Bagaimanapun, itu $ 0,02 saya
sumber
Anda memiliki pohon organisasi dengan kedalaman N level. Beberapa node dicentang, dan Anda ingin memperluas ke hanya node yang telah diperiksa.
Ini adalah sesuatu yang sebenarnya saya kodekan. Bagus dan mudah dengan rekursi.
sumber
Dalam pekerjaan saya, kami memiliki sistem dengan struktur data umum yang dapat digambarkan sebagai pohon. Itu berarti rekursi adalah teknik yang sangat efektif untuk bekerja dengan data.
Memecahkannya tanpa rekursi akan membutuhkan banyak kode yang tidak perlu. Masalah dengan rekursi adalah tidak mudah untuk mengikuti apa yang terjadi. Anda benar-benar harus berkonsentrasi saat mengikuti alur eksekusi. Tetapi jika berhasil, kodenya elegan dan efektif.
sumber
Perhitungan untuk keuangan / fisika, seperti rata-rata majemuk.
sumber
sumber
Parsing pohon kontrol di Windows Forms atau WebForms (.NET Windows Forms / ASP.NET ).
sumber
Contoh terbaik yang saya tahu adalah quicksort , ini jauh lebih sederhana dengan rekursi. Melihat:
shop.oreilly.com/product/9780596510046.do
www.amazon.com/Beautiful-Code-Leading-Programmers-Practice/dp/0596510047
(Klik subtitle pertama di bawah bab 3: "Kode terindah yang pernah saya tulis").
sumber
Perusahaan telepon dan kabel mempertahankan model topologi kabel mereka, yang merupakan jaringan atau grafik besar. Rekursi adalah salah satu cara untuk melintasi model ini ketika Anda ingin menemukan semua elemen induk atau semua anak.
Karena rekursi mahal dari perspektif pemrosesan dan memori, langkah ini biasanya hanya dilakukan ketika topologi diubah dan hasilnya disimpan dalam format daftar pra-order yang dimodifikasi.
sumber
Penalaran induktif, proses pembentukan konsep, bersifat rekursif. Otak Anda melakukannya sepanjang waktu, di dunia nyata.
sumber
Ditto komentar tentang kompiler. Simpul pohon sintaksis abstrak secara alami cocok untuk rekursi. Semua struktur data rekursif (daftar tertaut, pohon, grafik, dll.) Juga lebih mudah ditangani dengan rekursi. Saya pikir sebagian besar dari kita tidak dapat menggunakan rekursi terlalu sering setelah keluar dari sekolah karena jenis masalah di dunia nyata, tetapi ada baiknya untuk menyadarinya sebagai pilihan.
sumber
Perkalian bilangan asli adalah contoh rekursi dunia nyata:
sumber