Perfeitamente possível. Pensei em algo bastante simples, dá uma olhada e veja se entende
publicclassRecursaoVetor{/** Exemplo que preenche um vetor com os valores iguais a cada indice. */privatestaticvoidpreencheVetor(int[]vetor,intpos){if(pos==vetor.length-1)return;vetor[pos]=pos;preencheVetor(vetor,pos+1);}publicstaticvoidmain(Stringargs[]){int[]vetor=newint[10];preencheVetor(vetor,0);for(inti=0;i<vetor.length;++i)System.out.print(i+" ");}}
Odyo
entendi.
eu posso falar que um método recursivo funciona como uma laço ?
Que consome mais memória …
tô apanhando um pouco pra pensar recursivamente … !
cassio
Funciona de forma parecida a um laço, se você pensar no aspecto repetitivo de uma chamada recursiva. Repetitivo pois uma função (ou método) recursivo chama a si mesma n vezes, até que uma dada condição seja satisfeita e a função (ou método) retorne.
O consumo de memória realmente é um pouco maior, pois as chamadas são empilhadas e liberadas da memória somente quando a condição trivial (quando a função pára de chamar a si mesma) é alcançada e todas as chamadas retornam.
T
thingol
Outra forma de preencher o vetor usando recursividade.
A idéia é a seguinte:
Se o vetor tiver apenas 1 elemento, atribua um valor a esse elemento.
Para preencher um vetor, você precisa preencher suas duas metades.
classPreencherVetorRecursivo{/** * @param vec O vetor a ser preenchido * @param start A posição inicial a ser preenchida * @param end A posição final a ser preenchida MAIS UM (como o método String.substring) * @param val O valor que deve ser usado para preencher o vetor. */publicstaticvoidpreencher(int[]vec,intstart,intend,intval){if(start>=end)return;// 0 elementos, ou então chamada inválidaif(start+1==end){// ou seja, só um elementovec[start]=val;}else{// Preencher a primeira metadepreencher(vec,start,(start+end)/2,val);// Preencher a segunda metadepreencher(vec,(start+end)/2,end,val);}}publicstaticvoidmain(String[]args){int[]valores=newint[1234];finalintTHE_ANSWER=42;// Efetuando o preenchimento recursivo...preencher(valores,0,valores.length,THE_ANSWER);// Aqui estamos checando para ver se todos os valores são realmente 42// - não se esqueça que em Java, ao alocar um vetor os valores são 0 ou null.booleanok=true;for(inti=0;i<valores.length;++i){if(valores[i]!=THE_ANSWER){ok=false;break;}}if(!ok){System.out.println("Não conseguiu preencher o vetor adequadamente");}else{System.out.println("O vetor foi adequadamente preenchido.");}}}
T
thingol
Estou dando esse exemplo de “quebrar o vetor no meio” porque ele se parece um pouco com o quicksort, que também funciona de forma parecida.
Muitos problemas recursivos se resolvem quebrando o problema em pedaços, até que o problema seja suficientemente pequeno para ser resolvido de maneira simples.
No exemplo que lhe passei, eu quebrei o problema em 2, e cada subproblema em 2, até que o problema fosse bem pequeninho (preencher apenas 1 posição do vetor).
Mantu
Pra você ter noção do quanto um algoritmo recursivo consome mais memória que um não-recursivo, e já que vc quer um exercício, faça algo assim, pra brincar e testar:
Cria aí uma classe que exiba na tela os elementos 1, 2, 3 … 10, 15, 20, 25, 30, 40 de uma Fibonacci. Só que nesse seu programa, crie dois métodos distintos para buscar o n-ésimo elemento da série de Fibonacci, um recursivo e outro não recursivo. No main da sua classe, faça o programa então exibir algo assim na tela:
Existem maneiras e maneiras de fazer a recursividade. Nem sempre a recursividade usa assim mais memória.
O jeito que o Cassio lhe passou “explode” em Java quando o número de elementos do vetor é por volta de 90.000; o meu jeito (quebrando o problema sempre em “metades”) “explode” bem mais devagar. Na prática, meu jeito não deve explodir a pilha (stack) do Java - isso porque o maior tamanho de um vetor em Java são 2^31 elementos e com esse valor uso apenas 32 níveis de recursão, em vez de 2^31 níveis de recursão.
T
thingol
Nem sempre métodos recursivos são tão lentos quanto se pensa. É questão de saber algumas técnicas.
A que vou mostrar agora é a tal de “memoizing”. Rode este programa e você vai ver que Fibonacci não é tão lento assim recursivamente.
importjava.util.*;/** * "Memoizing" (que eu vou traduzir por "memorização") é uma técnica de acelerar programas * recursivos guardando resultados já calculados. * Embora existam maneiras mais simples e eficientes de calcular os números de Fibonacci, vou * mostrar uma técnica genérica que não exige mexer muito no seu algoritmo. * Como vocês devem saber: * fibonacci (0) = 0 * fibonacci (1) = 1 * fibonacci (n) = fibonacci (n - 1) + fibonacci (n - 2) */classFibonacciComMemorizacao{Map<Integer,Integer>preCalculado=newTreeMap<Integer,Integer>();publicFibonacciComMemorizacao(){preCalculado.put(0,0);// fibonacci (0) = 0preCalculado.put(1,1);// fibonacci (1) = 1}publicintfibonacci(intn){if(n==0){return0;}elseif(n==1){return1;}elseif(n>1){// fibonacci (n) = fibonacci (n - 1) + fibonacci (n - 2)Integerf=preCalculado.get(n);// vamos ver se já foi calculado antes...if(f!=null){// volto o valor pré-calculado!returnf;}else{// Não tem jeito, tem de calcular pela fórmula recursivaf=fibonacci(n-1)+fibonacci(n-2);// E agora vamos guardar o resultadopreCalculado.put(n,f);returnf;}}else{thrownewIllegalArgumentException("Definido apenas para os números positivos.");}}publicstaticvoidmain(String[]args){FibonacciComMemorizacaofcm=newFibonacciComMemorizacao();Integer[]valores={1,2,3,4,5,6,7,8,9,10,15,20,25,30,35,40};/* Valores esperados: (veja a seqüência http://www.research.att.com/~njas/sequences/A000045)Fibonacci (1) = 1Fibonacci (2) = 1Fibonacci (3) = 2Fibonacci (4) = 3Fibonacci (5) = 5Fibonacci (6) = 8Fibonacci (7) = 13Fibonacci (8) = 21Fibonacci (9) = 34Fibonacci (10) = 55Fibonacci (15) = 610Fibonacci (20) = 6765Fibonacci (25) = 75025Fibonacci (30) = 832040Fibonacci (35) = 9227465Fibonacci (40) = 102334155 */for(inti=0;i<valores.length;++i){System.out.println("Fibonacci ("+valores[i]+") = "+fcm.fibonacci(valores[i]));}}}
T
thingol
Eu usei, no “memoizing”, um Map<Integer,Integer> em vez de um int[] (como você também poderia fazer) para exemplificar uma técnica genérica.
É que nem sempre os valores recursivos são assim tão contíguos, como é o caso do Fibonacci.
T
thingol
Sugestão: modifiquem meu programa para usar BigInteger em vez de long. Se você calcular fibonacci (10000), vai ver que o valor é: