Saya telah mempelajari tentang fungsi rekursif, dan tampaknya, mereka adalah fungsi yang menyebut diri mereka sendiri, dan tidak menggunakan iterasi / loop (jika tidak itu tidak akan menjadi fungsi rekursif).
Namun, saat menjelajahi web sebagai contoh (masalah 8-ratu-rekursif), saya menemukan fungsi ini:
private boolean placeQueen(int rows, int queens, int n) {
boolean result = false;
if (row < n) {
while ((queens[row] < n - 1) && !result) {
queens[row]++;
if (verify(row,queens,n)) {
ok = placeQueen(row + 1,queens,n);
}
}
if (!result) {
queens[row] = -1;
}
}else{
result = true;
}
return result;
}
Ada while
loop yang terlibat.
... jadi saya agak bingung sekarang. Bisakah saya menggunakan loop atau tidak?
placeQueen
adalah "place 8 queens" dan versi yang lebih mudahplaceQueen
adalah "place 7 queens" (lalu place 6, dll.)Jawaban:
Anda salah memahami rekursi: meskipun dapat digunakan untuk menggantikan iterasi, sama sekali tidak ada persyaratan untuk fungsi rekursif untuk tidak memiliki iterasi internal pada dirinya sendiri.
Satu-satunya persyaratan agar suatu fungsi dianggap rekursif adalah keberadaan jalur kode yang digunakan untuk memanggil dirinya, secara langsung atau tidak langsung. Semua fungsi rekursif yang benar juga memiliki semacam kondisional, mencegahnya dari "berulang" selamanya.
Fungsi rekursif Anda sangat ideal untuk menggambarkan struktur pencarian rekursif dengan pengulangan. Dimulai dengan memeriksa kondisi keluar
row < n
, dan mulai membuat keputusan pencarian pada tingkat rekursi (yaitu memilih posisi yang memungkinkan untuk nomor raturow
). Setelah setiap iterasi, panggilan rekursif dibuat untuk membangun konfigurasi yang telah ditemukan fungsi sejauh ini; akhirnya, "turun" ketikarow
mencapain
panggilan rekursif yangn
tingkatnya dalam.sumber
Struktur umum dari fungsi rekursif adalah sesuatu seperti ini:
Teks yang saya tandai
/*recursive processing*/
bisa berupa apa saja. Itu bisa termasuk perulangan, jika masalah yang diselesaikan memerlukannya, dan juga bisa mencakup panggilan rekursif kemyRecursiveFunction
.sumber
Anda pasti dapat menggunakan loop dalam fungsi rekursif. Apa yang membuat suatu fungsi rekursif hanyalah fakta bahwa fungsi tersebut memanggil dirinya sendiri pada suatu titik di jalur eksekusi. Namun Anda harus memiliki beberapa kondisi untuk mencegah panggilan rekursi tak terbatas dari mana fungsi Anda tidak dapat kembali.
sumber
Panggilan dan loop rekursif hanyalah dua cara / konstruk untuk mengimplementasikan komputasi berulang.
Sebuah
while
loop berhubungan dengan panggilan berulang -ekor (lihat misalnya di sini ), yaitu iterasi di mana Anda tidak perlu menyimpan hasil antara antara dua iterasi (semua hasil dari satu siklus siap ketika Anda memasuki siklus berikutnya). Jika Anda perlu menyimpan hasil antara yang dapat Anda gunakan lagi nanti Anda bisa menggunakan satuwhile
lingkaran bersama dengan tumpukan (lihat di sini ), atau panggilan rekursif non-ekor-rekursif (yaitu sewenang-wenang).Banyak bahasa memungkinkan Anda untuk menggunakan kedua mekanisme tersebut dan Anda dapat memilih salah satu yang lebih cocok untuk Anda dan bahkan menggabungkan keduanya dalam kode Anda. Dalam bahasa imperatif seperti C, C ++, Java, dll. Anda biasanya menggunakan a
while
ataufor
loop ketika Anda tidak membutuhkan stack, dan Anda menggunakan panggilan rekursif ketika Anda membutuhkan stack (Anda secara implisit menggunakan run-time stack). Haskell (bahasa fungsional) tidak menawarkan struktur kontrol iterasi sehingga Anda hanya dapat menggunakan panggilan rekursif untuk melakukan iterasi.Dalam contoh Anda (lihat komentar saya):
sumber
Anda benar berpikir ada hubungan antara rekursi dan iterasi atau perulangan. Algoritma rekursif sering secara manual atau bahkan secara otomatis dikonversi ke solusi berulang menggunakan optimasi panggilan ekor.
Dalam delapan ratu, bagian rekursif terkait dengan menyimpan data yang diperlukan untuk pelacakan kembali. Ketika Anda memikirkan rekursi, penting untuk memikirkan apa yang didorong pada tumpukan. Tumpukan dapat berisi pass by parameter nilai dan variabel lokal yang memainkan peran kunci dalam algoritma, atau kadang-kadang hal-hal yang tidak begitu relevan seperti alamat pengirim atau dalam kasus ini, nilai yang diteruskan dengan jumlah ratu yang digunakan tetapi tidak diubah oleh algoritma.
Tindakan yang terjadi dalam delapan ratu adalah bahwa pada dasarnya kita diberikan solusi parsial untuk beberapa jumlah ratu dalam beberapa kolom pertama dari mana kita secara iteratif menentukan pilihan yang valid sejauh ini di kolom saat ini yang kami lewati secara rekursif untuk dievaluasi untuk kolom yang tersisa. Secara lokal, delapan ratu melacak baris apa yang dicoba dan jika pelacakan kembali terjadi, ia siap untuk melangkah melalui baris yang tersisa atau untuk melacak kembali dengan hanya mengembalikan jika tidak menemukan baris lain yang dapat bekerja.
sumber
Bagian "buat versi yang lebih kecil dari masalah" dapat memiliki loop. Selama metode menyebut dirinya lewat sebagai parameter versi lebih kecil dari masalah, metode ini bersifat rekursif. Tentu saja kondisi keluar, ketika versi terkecil dari masalah diselesaikan dan metode mengembalikan nilai, harus disediakan untuk menghindari kondisi stack overflow.
Metode dalam pertanyaan Anda bersifat rekursif.
sumber
Rekursi pada dasarnya memanggil fungsi Anda lagi dan keuntungan utama rekursi adalah menghemat memori. Rekursi dapat memiliki loop di dalamnya mereka digunakan untuk melakukan beberapa operasi lain.
sumber