"안녕, 아미고. 오늘은 Bilaabo가 재귀에 대해 알려줄거야."

재귀 - 1

아시다시피 Java에서 일부 메서드는 다른 메서드를 호출합니다. 또한 메서드가 호출되면 특정 인수가 메서드에 전달되지만 메서드가 실행되는 동안 메서드의 로컬 변수는 특정 값을 사용합니다.

"어 허."

"그리고 아시다시피 서로 다른 메서드의 내부 변수는 서로 독립적입니다."

"어 허."

"메서드가 자신을 호출하는 상황을 상상해 보십시오. 이를 재귀라고 합니다. 예를 들면 다음과 같습니다."

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);
 }
}
화면 출력:
10
9
8
7
6
5
4
3
2
1
Boom!

"메서드가 코드에서 자신을 호출하는 것을 볼 수 있지만 솔직히 무슨 일이 일어나고 있는지 이해할 수 없습니다."

"음, 다른 메서드가 호출될 때 발생하는 것과 거의 같습니다."

"아니요, 저는 변수에 어떤 일이 일어나는지 묻고 있습니다. 그 값은 어떻게 됩니까? 그리고 메서드를 어떻게 종료합니까? 아니면 모든 것을 한 번에 종료합니까?"

"다행입니다. 모든 것이 훨씬 간단합니다. 자신을 호출하는 메서드가 여러 번 곱해졌다고 상상해 보십시오. 그러면 유사한 상황이 발생합니다."

재귀 메서드 호출 실제로 일어나는 일
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);
 }
}
화면 출력: 화면 출력:
3
2
1
Boom!
3
2
1
Boom!

"즉, 메서드가 호출될 때마다(심지어 자체적으로도) 이 메서드에 대한 데이터를 저장하는 새 변수가 생성됩니다. 공유 변수가 없습니다."

"호출할 때마다 새 값을 가진 메서드 인수의 또 다른 복사본이 메모리에 생성됩니다. 이전 메서드로 돌아가면 해당 변수가 거기에서 사용됩니다. 즉, 재귀 중에 실제로 다른 메서드를 호출 하지만 우리와 같은 코드! "

"알겠습니다. 그런 방법을 종료하는 방법은 어떻게 작동합니까? 예를 들어?"

"좋아요. 예는 천 단어의 가치가 있습니다. "여기에 귀하의 예가 있습니다."

재귀 메서드 호출 재귀 메서드 호출
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);
 }
}
화면 출력: 화면 출력:
3
2
1
Boom!
1
2
3
3
2
1
Boom!
1
2
3

"알겠습니다. 이해한 것 같습니다. 왜 재귀가 필요한가요?"

"원래 작업과 동일한 별도의 하위 작업으로 나눌 수 있는 아주 많은 작업이 있습니다. 예를 들어 XML 트리의 모든 요소를 ​​살펴봐야 합니다. 각 요소는 여러 자식 요소를 가질 수 있으며 자신의 자식 요소."

"또는 디렉토리와 모든 하위 디렉토리에 있는 파일 목록을 표시해야 합니다. 따라서 현재 디렉토리의 파일을 표시하는 메소드를 작성합니다. 그런 다음 모든 하위 디렉토리의 파일을 가져오려면 다음을 사용하여 메소드를 호출합니다. 다른 인수: 하위 디렉터리."

"예를 들어:"

디렉토리 및 하위 디렉토리의 모든 파일 표시
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());
 }
}

"8행 – dir 디렉토리에 있는 모든 파일(및 디렉토리) 목록을 가져옵니다."

"10-11행 – 파일이 실제로 디렉토리인 경우 printAllFiles를 다시 호출 하지만 이번에는 다른 인수인 하위 디렉토리를 사용합니다."

"13행 – 현재 파일의 이름을 표시합니다."

"알았어. 이해한 것 같아. 고마워, Bilaabo."