"Hai, Amigo. Hari ini Bilaabo akan bercerita tentang rekursi."

Rekursi - 1

Seperti yang Anda ketahui, di Jawa beberapa metode memanggil metode lain. Selain itu, saat sebuah metode dipanggil, argumen khusus diteruskan ke metode tersebut, tetapi variabel lokal metode tersebut mengambil nilai tertentu saat dijalankan.

"Uh huh."

"Dan seperti yang Anda ketahui, variabel internal metode yang berbeda tidak bergantung satu sama lain."

"Uh huh."

"Jadi bayangkan situasi di mana sebuah metode memanggil dirinya sendiri. Ini disebut rekursi. Misalnya:"

Contoh
public static void main(String[] args)
{
 countDown(10);
}

public static void countDown(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown(x - 1);
 }
}
Keluaran layar:
10
9
8
7
6
5
4
3
2
1
Boom!

"Saya dapat melihat bahwa metode tersebut memanggil dirinya sendiri dalam kode, tetapi sejujurnya saya tidak mengerti apa yang terjadi."

"Yah, hal yang sama terjadi ketika metode yang berbeda dipanggil."

"Tidak, saya bertanya tentang apa yang terjadi dengan variabel? Dengan nilainya? Dan bagaimana kita keluar dari metode? Atau apakah kita keluar dari semuanya sekaligus?"

"Ya ampun. Semuanya jauh lebih sederhana. Bayangkan bahwa metode yang memanggil dirinya sendiri telah dikalikan berkali-kali. Maka kita akan memiliki situasi yang analog:"

Panggilan metode rekursif Apa yang sebenarnya terjadi
public static void main(String[] args)
{
 countDown(10);
}

public static void countDown(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown(x - 1);
 }
}
public static void main(String[] args)
{
 countDown1(10);
}

public static void countDown1(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown2(x - 1);
 }
}
public static void countDown2(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown3(x - 1);
 }
}
public static void countDown3(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown4(x - 1);
 }
}

public static void countDown4(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown5(x - 1);
 }
}
Keluaran layar: Keluaran layar:
3
2
1
Boom!
3
2
1
Boom!

"Dengan kata lain, setiap kali sebuah metode dipanggil (bahkan dengan sendirinya), variabel baru dibuat yang menyimpan data untuk metode ini. Tidak ada variabel bersama."

"Dengan setiap panggilan, salinan lain dari argumen metode, dengan nilai baru, dibuat di memori. Saat kita kembali ke metode lama, variabelnya digunakan di sana. Dengan kata lain, selama rekursi sebenarnya kita memanggil metode lain, tetapi dengan kode yang sama dengan milik kita! "

"Begitu. Dan bagaimana cara keluar dari metode seperti itu? Mungkin sebuah contoh?"

"Oke. Contoh bernilai seribu kata. "Ini contoh Anda:"

Panggilan metode rekursif Panggilan metode rekursif
public static void main(String[] args)
{
 print(3);
}

public static void print(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  print(x - 1);
  System.out.println(x);
 }
}
public static void main(String[] args)
{
 print1(3);
}

public static void print1(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  print2(x - 1);
  System.out.println(x);
 }
}

public static void print2(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  print3(x - 1);
  System.out.println(x);
 }
}
Keluaran layar: Keluaran layar:
3
2
1
Boom!
1
2
3
3
2
1
Boom!
1
2
3

"Oke. Saya pikir saya mengerti. Mengapa kita membutuhkan rekursi?"

"Ada banyak, banyak tugas yang dapat dibagi menjadi subtugas terpisah yang identik dengan tugas aslinya. Misalnya, Anda perlu menelusuri semua elemen pohon XML. Setiap elemen dapat memiliki beberapa elemen anak, dan mereka memiliki elemen anak sendiri."

"Atau Anda perlu menampilkan daftar file yang ada di direktori dan semua subdirektorinya. Jadi Anda menulis metode yang menampilkan file dari direktori saat ini. Kemudian untuk mendapatkan file dari semua subdirektori, Anda memanggil metode Anda menggunakan argumen yang berbeda: subdirektori."

"Misalnya:"

Menampilkan semua file dalam direktori dan subdirektorinya
public static void main(String[] args)
{
 printAllFiles(new File("c:/windows/"));
}

public static void printAllFiles(File dir)
{
 for (File file : dir.listFiles())
 {
  if (file.isDirectory())
   printAllFiles(file);
  else
   System.out.println(file.getAbsolutePath());
 }
}

"Baris 8 – Kami mendapatkan daftar semua file (dan direktori) di direktori dir."

"Baris 10-11 – Jika file sebenarnya adalah sebuah direktori, maka kita memanggil printAllFiles lagi, tapi kali ini dengan argumen lain: subdirektori."

"Baris 13 – Kami menampilkan nama file saat ini."

"Oke. Kurasa aku mengerti. Terima kasih, Bilaabo."