꼬리 재귀 함수 호출을 통해 컴파일러는 일반적으로 정기적으로 재귀로 할 수없는 특수 최적화를 수행 할 수 있습니다. 꼬리 재귀 함수에서, 재귀 호출은 마지막으로 실행 된 것입니다. 이 경우, 각 호출에 대한 스택 프레임을 할당하는 대신 컴파일러는 코드를 재 작업하여 현재 스택 프레임을 재사용 할 수 있습니다. 즉, 테일 리퍼 시브 기능은 수백 또는 수천과 달리 단일 스택 프레임 만 사용합니다.
이 최적화는 컴파일러가 일단 꼬리 재귀 호출이 이루어지면 더 이상 실행할 코드가 없기 때문에 이전 변수 사본이 필요하지 않다는 것을 알고 있기 때문에 가능합니다. 예를 들어, 인쇄 명령문이 재귀 통화를 따르는 경우, 컴파일러는 재귀 통화가 반환 된 후 인쇄 할 변수의 값을 알아야하므로 스택 프레임을 재사용 할 수 없습니다.
이 "공간 절약"및 스택 재사용 방법에 대한 자세한 내용에 대한 자세한 정보를 원한다면 Wiki 페이지는 다음과 같습니다. 꼬리 통화
편집 : 나는 이것이 QuickSort에 어떻게 적용되는지 설명하지 않았습니까? 글쎄, 일부 용어는 그 기사에서 모든 것을 혼란스럽게 만드는 기사에서 던져졌습니다 (그리고 그 중 일부는 명백한 잘못입니다). 주어진 첫 번째 함수 (QuickSort)는 왼쪽에 재귀 호출을하고 오른쪽에 재귀 호출을 한 다음 종료합니다. 오른쪽의 재귀 호출은 기능에서 발생하는 마지막 일입니다. 컴파일러가 꼬리 재귀 최적화를 지원하는 경우 (위에서 설명) 왼쪽 호출 만 새 스택 프레임을 만듭니다. 모든 올바른 호출은 현재 프레임을 재사용합니다. 이것은 저장할 수 있습니다 약간 스택 프레임이지만, 파티션이 꼬리 재귀 최적화가 중요하지 않은 일련의 통화를 생성하는 경우에도 여전히 어려움을 겪을 수 있습니다. 또한 오른쪽 통화는 동일한 프레임을 사용하더라도 왼쪽 통화는 이내에 오른쪽 통화는 여전히 스택을 사용합니다. 최악의 경우 스택 깊이는 N입니다.
설명 된 두 번째 버전은 다음과 같습니다 ~ 아니다 꼬리 재귀 퀵조트이지만 오히려 왼쪽 정렬 만 재귀 적으로 수행되고 루프를 사용하여 오른쪽 정렬이 수행되는 퀵조트입니다. 실제로,이 QuickSort (이전에 다른 사용자가 이전에 설명한대로)는 재귀 호출이 마지막으로 실행되는 것이 아니기 때문에 Tail Recursion Optimization을 적용 할 수 없습니다. 이것은 어떻게 작동합니까? 올바르게 구현하면 QuickSort에 대한 첫 번째 호출은 원래 알고리즘의 왼쪽 호출과 동일합니다. 그러나 오른쪽 재귀 호출도 호출되지 않습니다. 이것은 어떻게 작동합니까? 글쎄, 루프는 다음을 처리합니다. 오른쪽의 왼쪽. 정말 말도 안되는 소리이지만 기본적으로 많은 레프를 정렬하면 권리가 단일 요소가되고 정렬 될 필요가 없습니다. 이것은 올바른 재귀를 효과적으로 제거하여 기능을 덜 재귀 적으로 만듭니다. 그러나 실제 구현은 매번 왼쪽 만 선택하지 않습니다. 가장 작은면을 선택합니다. 아이디어는 여전히 동일합니다. 기본적으로 두 가지 대신 한쪽에 재귀적인 호출 만 수행합니다. 짧은면을 선택하면 스택 깊이가 적절한 바이너리 트리의 깊이 인 Log2 (N)보다 결코 더 크지 않도록합니다. 짧은면이 항상 현재 배열 섹션의 크기의 절반이 될 것이기 때문입니다. 그러나 기사에 의해 주어진 구현은 "왼쪽은 전체 트리"라는 동일한 최악의 시나리오로 어려움을 겪을 수 있기 때문에 이것을 보장하지는 않습니다. 이 기사는 실제로 더 많은 독서를 할 의향이 있다면 실제로 그것에 대한 좋은 설명을 제공합니다. QuickSort를 기반으로 한 효율적인 선택 및 부분 정렬