Eu conheço o conceito geral de recursão. Me deparei com o conceito de recursão da cauda enquanto estudava o algoritmo quicksort. Neste vídeo de algoritmo de ordenação rápida do MIT às 18:30 segundos, o professor diz que este é um algoritmo recursivo de cauda. Não está claro para mim o que realmente significa recursão da cauda.
Alguém pode explicar o conceito com um exemplo adequado?
Algumas respostas fornecidas pela comunidade SO aqui .
Respostas:
A recursão de cauda é um caso especial de recursão em que a função de chamada não faz mais cálculos depois de fazer uma chamada recursiva. Por exemplo, a função
é recursivo de cauda (já que a instrução final é uma chamada recursiva), enquanto esta função não é recursiva de cauda:
já que faz algum cálculo após o retorno da chamada recursiva.
A recursão da cauda é importante porque pode ser implementada com mais eficiência do que a recursão geral. Quando fazemos uma chamada recursiva normal, precisamos inserir o endereço de retorno na pilha de chamadas e pular para a função chamada. Isso significa que precisamos de uma pilha de chamadas cujo tamanho seja linear na profundidade das chamadas recursivas. Quando temos recursão de cauda, sabemos que, assim que retornarmos da chamada recursiva, retornaremos imediatamente também, para que possamos pular toda a cadeia de funções recursivas retornando e retornando diretamente para o chamador original. Isso significa que não precisamos de uma pilha de chamadas para todas as chamadas recursivas e podemos implementar a chamada final como um simples salto, o que economiza espaço.
fonte
def recurse(x): if x < 0 return 1; for i in range 100{ (do calculations) recurse(x)}
Dito de forma simples, a recursão da cauda é uma recursão em que o compilador pode substituir a chamada recursiva por um comando "goto", para que a versão compilada não precise aumentar a profundidade da pilha.
Às vezes, projetar uma função recursiva de cauda exige que você precise criar uma função auxiliar com parâmetros adicionais.
Por exemplo, esta não é uma função recursiva da cauda:
Mas esta é uma função recursiva da cauda:
porque o compilador pode reescrever a função recursiva para uma função não recursiva, usando algo como isto (um pseudocódigo):
A regra para o compilador é muito simples: quando você encontrar "
return thisfunction(newparameters);
", substitua-o por "parameters = newparameters; goto start;
". Mas isso pode ser feito apenas se o valor retornado pela chamada recursiva for retornado diretamente.Se todas as chamadas recursivas em uma função puderem ser substituídas assim, é uma função recursiva de cauda.
fonte
Minha resposta é baseada na explicação dada no livro Estrutura e Interpretação de Programas de Computador . Eu recomendo este livro para cientistas da computação.
Abordagem A: Processo Recursivo Linear
A forma do processo para a Abordagem A é assim:
Abordagem B: Processo Iterativo Linear
A forma do processo para a Abordagem B é assim:
O processo iterativo linear (abordagem B) é executado em espaço constante, mesmo que o processo seja um procedimento recursivo. Também deve ser observado que, nesta abordagem, um conjunto de variáveis define o estado do processo em qualquer ponto viz.
{product, counter, max-count}
. Essa também é uma técnica pela qual a recursão da cauda permite a otimização do compilador.Na Abordagem A, há mais informações ocultas mantidas pelo intérprete, que são basicamente a cadeia de operações diferidas.
fonte
A recursão de cauda é uma forma de recursão na qual as chamadas recursivas são as últimas instruções na função (é daí que a parte da cauda vem). Além disso, a chamada recursiva não deve ser composta com referências a células de memória que armazenam valores anteriores (referências diferentes dos parâmetros da função). Dessa forma, não nos importamos com valores anteriores e um quadro de pilha é suficiente para todas as chamadas recursivas; recursão de cauda é uma maneira de otimizar algoritmos recursivos. A outra vantagem / otimização é que existe uma maneira fácil de transformar um algoritmo recursivo de cauda em um algoritmo equivalente que usa iteração em vez de recursão. Então, sim, o algoritmo do quicksort é realmente recursivo da cauda.
Aqui está a versão iterativa:
fonte