모든 재귀 함수를 반복으로 코딩 할 수 있습니까? [닫은]


10

재귀의 장점은 무엇입니까?

일부 프로그래밍 언어는 테일 재귀를 최적화 할 수 있지만 여전히 일반적인 용어로 재귀는 일반 루프보다 많은 리소스를 소비합니다.

재귀 함수의 반복 버전을 사용할 수 있습니까?



답변:


10

예, 재귀 함수를 반복으로 코딩 할 수 있습니다. 기본적으로 컴파일러가 생성 한 코드를 호출하는 메소드가 처리 한 정보를 수동으로 유지 보수해야합니다.

즉, 각 항목이 전달 된 매개 변수와 모든 로컬 변수를 포함하는 구조 인 스택이 필요합니다. 항상 스택의 최상위 항목에서 작업합니다. 직접 전화해야하는 경우 새 항목을 작성하고 스택 위에 놓으십시오. 완료되면 아래의 항목을 노출시키는 스택의 최상위 항목을 가져 와서 이전 최상위 항목을 사용하여 반환 값을 추출하고 그에 따라 새 최상위 항목을 업데이트하십시오.

나는 이것이 보통 기계 코드에서 어떻게 구현되는지 확인하기 위해 컴파일러 책을 연구 할 것을 제안한다.


알겠습니다 그렇다면 재귀는 어떤 이점이 있습니까? 간단?
OscarRyz

2
@OscarRyz : 예, 더 우아합니다.
Michael K

@OscarRyz, 내가 설명한 방식 재귀입니다. 기본 CPU 명령어로는 수행되지 않습니다. 수동으로 수행하면 병렬화와 같은 작업을 수행하여 기본 명령어에 잘못 매핑됩니다.

15

재귀는 종종 반복보다 사물을 보는 더 자연스러운 방법입니다. 예를 들어, 이진 트리의 순서 순회를 고려하십시오 inorder(left); process(); inorder(right);. 스택을 명시 적으로 유지 관리하는 것보다 훨씬 간단합니다.

너무 깊이 들어 가지 않는 한 (스택을 날리는) 리소스 사용의 차이는 보통 사소합니다. 일반적으로 걱정하지 마십시오. 간단한 코드는 일반적으로 수동 최적화 코드보다 낫지 만 예외는 있습니다. 일반적으로 빠름보다 낫습니다.

재귀 알고리즘은 반복 알고리즘으로 표현할 수 있지만 암시 적으로 처리되는 호출 스택에 해당하는 명시 적 스택을 유지해야 할 수도 있습니다. 결국, 재귀 함수를 컴파일하면 스택을 조작하고 함수를 반복하는 데 의존하는 무언가를 얻습니다. 반복적입니다.

테일 재귀 함수는 루프로 쉽게 변환 할 수 있으며 스택이 필요하지 않지만 특별한 경우입니다.


8
나는 권리가 항상 빠른 것보다 낫다고 말하고 싶습니다 . 잘못된 일을 매우 빨리하는 코드는 누구에게나 좋지 않습니다.
메이슨 휠러

1
하지만 잘못된 일을 정말 빨리 할 수 있다면 어떨까요?!
RationalGeek

1
@jkohlhepp-즉시 모든 문제를 해결할 수 있습니다. 답은 0입니다.
자기 메모-이름을 생각하십시오.

2
명시 적 스택이 아닌 재귀를 사용하는 것이 더 효율적일 수 있습니다. 힙 할당, 메모리 조각화 및 가능한 지역성 문제가 필요 없습니다. 그러나 "오른쪽이 일반적으로 빠른 것보다 낫다"에서 소프트웨어가 처리해야하는 경우 스택 오버플로는 코드가 손상되었음을 의미합니다. 일반적으로 문제의 경우를 쉽게 발견 할 수 있습니다. (합리적으로) 균형 잡힌 나무의 재귀는 괜찮지 만, 매우 불균형하거나 연결된 목록에있는 나무의 재귀는 C와 같은 언어에서 심각한 버그 일 수 있습니다. 간단한 테스트에서도 살아남을 수 있으며 실제 배포시에만 충돌이 발생할 수 있습니다.
Steve314

1
나는 여러분 모두 메이슨의 의미를 이해하고 재미로 농담을하고 있다고 생각합니다. 물론 느린 올바른 프로그램이 잘못된 잘못된 프로그램보다 유용합니다.
Giorgio

4

재귀의 장점은 무엇입니까?

하노이 타워 문제를 반복적으로 해결해보십시오. 포기하면 반복 솔루션을 살펴보고 재귀 솔루션 과 비교하십시오. 어느 것이 더 간단합니까?

재귀 함수의 반복 버전을 사용할 수 있습니까?

네, 원칙적 으로요 그러나 트리 탐색과 같은 매우 일반적인 작업을 포함한 많은 문제의 경우 재귀 솔루션은 반복 솔루션보다 훨씬 간단하고 우아합니다.


3

재귀의 장점은 무엇입니까?

간단. 꼬리 호출 최적화가 없다면 물론 더 많은 리소스 (스택)가 필요하지만 deltree재귀없이 Java로 어떻게 구현 합니까? 트위스트는 delete()디렉토리가 비어있는 경우에만 디렉토리를 삭제할 수 있다는 것입니다 . 재귀와 함께 여기 있습니다 :

deltree(File fileOrDirectory) {
    if (fileOrDirectory.isDirectory()) {
        for (File subFileOrDirectory : fileOrDirectory.listFiles()) {
            deltree(subFileOrDirectory);
        }
    }
    fileOrDirectory.delete();
}

1
다른 답변에서 언급했듯이 스택으로.
Nicole

네,하지만 단순한는 얼마나? -)
투입 Joonas Pulakka

아, 재귀가 확실히 좋습니다. 나는 당신이 그것이 불가능하다고 말하고 있다고 생각했습니다.
Nicole

0

나는 재귀가 프로그래머 살아야 하는 도구 중 하나라고 생각합니다 . 재귀를 사용하면 알고리즘을 "생각"하고 생각한대로 해결할 수 있습니다. 그러나 나는 당신에게 경고해야합니다. 모두가 할 말이 몇 가지 있다는 점에서 모든 사람들이 재귀가 얼마나 예쁜지, 얼마나 간단하게 코드에 가져 오는지 이야기하고 있습니다.

  1. 우선, 알고리즘의 "재귀 적 방식"을 생각하는 것은 쉽지 않습니다. 팩토리얼 (n!) 또는 하노이 타워와 같은 기능을 구축하는 것은 빙산의 일각 일 뿐이며 바닥에 도달하려면 많은 시간이 필요합니다.
  2. 재귀가 코드에만 단순성을 가져 온다고 생각하지 마십시오. 때로는 반복적 인 방법이 추악하고 지저분하지만 비용 효과적입니다 (피보나치 문제의 재귀 솔루션을 살펴보십시오)

그런 것들을 염두에두고 재귀를 배우십시오! 재미 있고 복잡하며 두뇌를 박살낼 것입니다!

행운을 빌어 요!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.