Estruturas de Dados 2019/2020 (CC1007) - DCC/FCUP

Aula Prática #10 - Recursividade
(semana de 13/05 a 17/05)


Conteúdos das teóricas

Nesta aula iremos abordar conceitos de recursividade. Será por isso conveniente ver o que foi falado nas teóricas:


Exercício 1) Um primeiro exemplo

[ver slides 3 a 6]

  1. Testando várias maneiras de calcular o máximo.
    Faça download do código dado nas aulas para calcular o máximo de um intervalo dado de um array. Compile, teste e verifique que percebe exactamente como o código está a funcionar.
    Sugestão: no início de cada função recursiva imprima o valor de start e end se quiser ver como as chamadas recursivas estão a ser feitas (conselho válido para todas as funções recursivas)
  2. Calculando recursivamente a soma de um array.
    Usando como base o código do máximo, implemente e teste duas versões recursivas de um método para calcular a soma do elementos entre start e end do array v[]:

Exercício 2) Capicuas

[ver slide 10]

  1. Testando código de inverter um array.
    Faça download do código dado nas aulas para inverter um array de forma recursiva. Compile, teste e verifique que percebe exactamente como o código está a funcionar.
  2. Capicuas.
    Usando como base o código da inversão, implemente e teste um método recursivo para saber se o array representa uma capicua(uma capicua é um número que é igual quando lido da direita para esquerda ou da esquerda para a direita).

Exercício 3) Flood Fill

[ver slides 11 a 14]

  1. Testando código de flood fill.
    Faça download do código dado nas aulas para fazer "flood fill" de forma recursiva. Compile, teste e verifique que percebe exactamente como o código está a funcionar. Note que precisa de dar input ao programa (um exemplo é fornecido na página com o código). Se o ficheiro com input se chamasse floodfill.txt, uma maneira de executar o programa seria: java TestFloodFill < floodfill.txt.
  2. Resolvendo um problema.
    Usando como base o código anterior, resolva e submeta o problema [ED200] Contagem de Células, disponível no Mooshak de EDados no "Volume 5 (Complexidade e Recursividade)".

Exercício 4) Subconjuntos

[ver slides 15 a 17]

  1. Testando código de subconjuntos.
    Faça download do código dado nas aulas para gerar todos os subconjuntos de um dado array.
  2. Resolvendo um problema.
    Usando como base o código anterior, resolva e submeta o problema [ED201] PlayList, disponível no Mooshak de EDados no "Volume 5 (Complexidade e Recursividade)".

Exercício 5) Permutações

[ver slides 18 e 19]

  1. Testando código de permutações.
    Faça download do código dado nas aulas para gerar todas as permutações de um dado array.
  2. Resolvendo um problema.
    Usando como base o código anterior, resolva e submeta o problema [ED202] Procurando Pokemons, disponível no Mooshak de EDados no "Volume 5 (Complexidade e Recursividade)".

Exercícios extra para consolidação de conhecimentos

  1. Implemente um programa para resolver recursivamente o puzzle das 8 raínhas, imprimindo todas as soluções possíveis. O puzzle implica descobrir todas as maneiras em que é possível colocar 8 raínhas num tabuleiro de xadrez de tal modo que nenhuma raínha possa atacar outra raínha, ou seja, não existem duas raínhas na mesma linha, coluna ou diagonal. Um exemplo de solução seria:
  2. Tal como explicado na parte final de uma aula teórica, Uma maneira de representar as posições pode ser por exemplo... uma permutação de 8 números, representando as linhas das raínhas. Por exemplo, (5,3,1,7,2,8,6,4) representa a imagem anterior.
    Ao gerar as permutações, pode logo cortar os casos onde já sabe que nunca obterá solução (verificando se a nova raínha colocada não "ataca" nenhuma das raínhas já colocadas.

  3. Compile e teste o código exemplo do MergeSort, procurando perceber tudo o que está a ser feito.
  4. Usando como guia o código do MergeSort, implemente uma versão recursiva do QuickSort. Escolha em cada iteração um pivot aleatório (pode usar por exemplo a classe Random)
  5. Implemente um programa recursivo para gerar todos os possíveis quadrados mágicos de um dado tamanho n: um quadrado de n por n preenchido com todos os inteiros de 1 a n2 de tal modo que cada célula contenha um número diferente, e que cada linha, coluna ou diagonal dê a mesma soma.


Exercício de Desafio

O exercicio de desafio desta semana está pensado para poder ser usado com recursividade e está disponível para submissão no Mooshak, no volume de Desafios:

A solução óbvia com dois ciclos é Θ(n2) e não passa no tempo, pelo que é preciso algo melhor. A ideia é usar como "esqueleto" o Merge Sort e ao mesmo tempo que ordenamos... contamos as inversões - tudo isto em Θ(n log n).

Não vou dizer mais para não tirar a piada a fazerem o exercício, mas se precisarem de mais dicas, digam :)