Italo Info


Programa com recursividade

As linguagens de programação modernas disponibilizam estruturas de repetição para o programador. No entanto, é possível simular qualquer repetição com funções, procedimentos, ou métodos recursivos. Por isso, esse artigo mostra um exemplo construido com recursividade, sem nenhum comando de repetição.

Um pouco sobre recursividade

As funções e procedimentos recursivos são chamadas dentro da própria função ou procedimento.

Exemplo:


procedure recursividade;
begin
  recursividade;
end;

O procedimento recursividade é chamado no corpo do próprio procedimento. No entanto, esse procedimento recursivo gera um loop infinito. Isto é, leva o programa a travar. Por isso, normalmente, as funções ou procedimentos recursivos têm uma condição de parada para evitar o loop infinito.

Por exemplo: como criar um procedimento em pascal que imprime os números de um a um número informado pelo usuário?

Abaixo a solução com comando "for":


program IMP_NUMS;
uses crt;

procedure imprime_numeros( n : integer);
begin
  for i := 1 to n do
    write( i,' ' );
end;

begin
  clrscr;
  write( 'Informe um numero: ' );
  readln( num );

  imprime_numeros( num );
  readln;
end.

Abaixo a solução com procedimento recursivo:


program IMP_NUMS_RECURSIVO;
uses crt;

procedure imprime_numeros( n : integer; i : byte );
begin
  if ( i <= n ) then    
    begin
      write( i,' ' );
      imprime_numeros( n, i+1 );
    end;
end;

begin
  clrscr;
  write( 'Informe um numero: ' );
  readln( num );

  imprime_numeros( num, 1 );
  readln;
end.

Perceba que nas duas soluções são necessárias uma variável contador que foi nomeada "i" e uma condição de parada que é quando o contador "i" torna-se igual ao número "n". Perceba que na versão recursiva o contador é inicializado com 1 e passado como segundo parâmetro para o procedimento "imprime_numeros", enquanto que, na versão não recursiva a variável contador é criada no próprio procedimento, necessitando apenas de um número como parâmetro. A variável contador, nas duas soluções, tem seu valor variado de 1 até o numero "n". Perceba também que o procedimento recursivo recebe um parâmetro a mais no programa principal. Ou seja, a variavel contador "i" é inicializada com valor 1 no programa principal.

Na função recursiva, o contador "i" é incrementado em 1 quando a função imprime_numeros é chamada de modo recursivo recebendo o parâmetro "i+1".

Abaixo um programa que fiz inteiramente com recursividade ( Sem nenhuma estrutura de repetição ):

Imagem capturada do programa:

Imagem do programa recursivo

O código fonte escrito em linguagem pascal:


program RECURSIVIDADE ;
uses crt;

type tvetor = array[ 1..100 ] of integer;

procedure imprime_numeros( n : word; i : byte );
begin
  if ( i <= n ) then
    begin
      write( i,' ' );
      imprime_numeros( n, i+1 );
    end;
end;

procedure imprime_divisores( n : word; i : byte );
begin
  if ( i <= n div 2 ) then
    begin
      if ( n mod i = 0 ) then
        write( i,' ' );
      
      imprime_divisores( n, i+1 );
    end
  else write( n );
end;

procedure eh_primo( n : word; i : byte; var eh : boolean );
begin
  if ( eh ) and ( i <= n div 2 ) then
    begin
      if ( n mod i = 0 ) then
        eh := false
      else eh_primo( n, i+1, eh );
    end;
end;

procedure imprime_primos( n : word; i : byte );
var eh_p : boolean;
begin
  if ( i <= n ) then
    begin
      eh_p := true;
      eh_primo( i, 2, eh_p );
      if ( eh_p ) then
        write( i,' ' );
      
      imprime_primos( n, i+1 );
    end;
end;

procedure sorteia_numeros( var vet : tvetor; max : word; tam, i : byte );
begin
  if ( i <= tam ) then
    begin
      vet[ i ] := random( max );
      sorteia_numeros( vet, max, tam, i+1 );
    end;
end;

procedure imprime_vetor( vet : tvetor; tam, i : byte );
begin
  if ( i <= tam ) then
    begin
      write( vet[ i ], ' ' );
      imprime_vetor( vet, tam, i+1 );
    end;
end;

procedure eh_palindromo( palavra : string; i : byte; var eh : boolean );
begin
  if ( eh ) and ( i <= length( palavra ) div 2 ) then
    begin
      if ( palavra[ i ] <> palavra[ length( palavra ) - i + 1 ] ) then
        eh := false
      else eh_palindromo( palavra, i+1, eh );
    end;
end;

function fatorial( n : word ) : word;
begin
  if ( n = 1 ) then
    fatorial := 1
  else fatorial := n * fatorial( n-1 );
end;

function fibo( n : word ) : word;
begin
  if ( n = 0 ) or ( n = 1 ) then
    fibo := 1
  else fibo := fibo( n-1 ) + fibo( n-2 );
end;

procedure imprime_serie_fibo( n : word; i : byte );
begin
  if ( i <= n ) then
    begin
      write( fibo( i ),' ' );
      imprime_serie_fibo( n, i+1 );
    end;
end;

procedure indice_do_maior( vet : tvetor; tam, i : byte; menor : integer; var indice : byte );
begin
  if ( i <= tam ) then
  begin
    if ( vet[ i ] < menor ) then
      begin
        indice := i;
        indice_do_maior( vet, tam, i+1, vet[ i ], indice );
      end
    else indice_do_maior( vet, tam, i+1, menor, indice );
  end;
end;

procedure ordena( var vet : tvetor; tam, i : byte );
var indice : byte;
aux : integer;
begin
  if ( i <= tam ) then
    begin
      indice := i;
      indice_do_maior( vet, tam, i+1, vet[ i ], indice );
      
      aux := vet[ i ];
      vet[ i ] := vet[ indice ];
      vet[ indice ] := aux;
      
      ordena( vet, tam, i+1 );
    end;
end;

procedure menu;
begin
  clrscr;
  writeln( '********************* Menu *********************' );
  writeln;
  writeln( ' (1) - Imprime numeros menores ou iguais a' );
  writeln( ' (2) - Imprime os primos menores ou iguais a' );
  writeln( ' (3) - Imprime divisores' );
  writeln( ' (4) - Verifica se eh palindromo' );
  writeln( ' (5) - Imprime fatorial' );
  writeln( ' (6) - Imprime serie fibbonacci' );
  writeln( ' (7) - Imprime ordenado' );
  writeln( ' (0/Esq) - Sair' );
  writeln;
  writeln( '************************************************' );
  writeln;
end;

{ ****** PROGRAMA PRINCIPAL ****** }


procedure prog_principal;

  const VET_QUANT: integer = 20;
  VET_MAX : integer = 100;

  var op : char;
  num : word;
  palavra : string;
  eh_p : boolean;
  fat : word;

  vet : tvetor;
  vtam : byte;

  Begin
    menu;
    op := readkey;
    if ( op <> '0' ) and ( op <> #27 ) then
    begin
      case op of
        '1': begin
          write( 'Informe um numero: ' );
          readln( num );
          
          writeln;
          write( 'Numeros: ' );
          imprime_numeros( num, 1 );
          readln;
        end;
        '2': begin
          write( 'Informe um numero: ' );
          readln( num );
          
          writeln;
          write( 'Primos: ' );
          imprime_primos( num, 1 );
          readln;
        end;
        '3': begin
          write( 'Informe um numero: ' );
          readln( num );
          
          writeln;
          write( 'Divisores de ',num,': ' );
          imprime_divisores( num, 1 );
          readln;
        end;
        '4': begin
          write( 'Informe uma palavra: ' );
          readln( palavra );
          
          eh_p := true;
          eh_palindromo( palavra, 1, eh_p );
          
          writeln;
          if ( eh_p ) then
            writeln( 'A palavra ',palavra,' eh palindromo' )
          else writeln( 'A palavra ',palavra,' nao eh palindromo' );
          readln;
        end;
        '5': begin
          write( 'Informe um numero: ' );
          readln( num );
          
          fat := fatorial( num );
          
          writeln;
          writeln( 'O fatorial de ',num,' eh: ', fat );
          readln;
        end;
        '6': begin
          write( 'Informe um número: ' );
          readln( num );
          
          writeln;
          write( 'Serie fibbonacci: ' );
          imprime_serie_fibo( num, 0 );
          readln;
        end;
        '7': begin
          sorteia_numeros( vet, VET_MAX, VET_QUANT, 1 );
          
          writeln;
          write( 'Numeros sorteados: ' );
          imprime_vetor( vet, VET_QUANT, 1 );
          
          ordena( vet, VET_QUANT, 1 );
          
          writeln;
          write( 'Numeros ordenados: ' );
          imprime_vetor( vet, VET_QUANT, 1 );
          readln;
        end;        
    end;
    
    prog_principal;
  end;
End;

Begin
  prog_principal;
End.

Baixe o código fonte aqui.

Finalizando...

É isso pessoal. Peço que quem tiver gostado, envie um comentário logo abaixo.

Até o próximo