1 1 Departamento de Ciência de Computadores Estruturas de Dados (CC114) 1 o Teste: 27/Abril/2011 FCUP 2010/11 duração: 2 horas 1. Teste A (indicar o teste que estão a fazer na folha de resposta) 2. Cotação de cada pergunta: 1. 35 / 2. 25 / 3. 40 (Total: 100 pontos) 3. Responda às questões de forma clara e concisa nas folhas de exame distribuídas. 1. (Valorização: 35%) Responda às seguintes questões: a) Analise o código seguinte, ilustre como ficam em memória a representação dos 3 vectores e respectivos conteúdos e diga o que é escrito como resultado na última linha de código. 1. int a[]= {1,3,5,7,9,11; 2. int b[]= new int[6]; 3. int c[]= new int[6]; 4. b=a; 5. for (int i=0; i<a.length; i++) 6. c[i]= a[i]; 7. a[3]= c[5]; 8. c[3]++; 9. System.out.println(a[3] + " " + b[3] + " " + c[3]); Saliente-se que a atribuição b=a (linha 4.) faz com que as variáveis a e b referenciem o mesmo vector (o vector a dado inicialmente na linha 1.). No ciclo-for (linhas 5 e 6) copia-se para o vector c os valores do vector a. Na linha 7, muda-se o valor de a[3] (ou seja b[3]) ficando igual a 11 que está em c[5]. Na linha 8. incrementa-se o valor de c[3] passando para 8. A linha 9 escreve como resultado: 11 11 8 Os vectores em memória ficam como se ilustra na figura seguinte: b) Escreva um método recursivo com assinatura double somareciprocos(int n) que aceita como argumento um inteiro não negativo (n > 0) e retorna um número em vírgula flutuante (double) que é a soma dos recíprocos de 1 a n. Por exemplo, somareciprocos(2) retorna 1.5, que é 1/1+1/2; e somareciprocos(4) retorna aproximadamente 2.0833, que é resultado de 1/1 + 1/2 + 1/3 + 1/4. Uma solução iterativa não será considerada.
double somareciprocos(int n) { if (n==1) return 1; return ((double)1/n) + somareciprocos(n-1); c) Dê uma ideia breve de como funciona o método de ordenação da bolha (bubble-sort) e ilustre o seu funcionamento na ordenação da sequência 8, 3, 7, 1, 4 (deverá mostrar os sucessivos passos que o método realiza). O método da bolha faz a comparação dos elementos do vector dois a dois, de tal modo que ao fim da primeira iteração, i.e. (n-1) comparações, temos a garantia que o maior elemento (se estivermos a ordenar por ordem crescente) terá deslizado até à última posição do vector. Repetimos este processo no máximo mais (n-2) vezes para garantir que colocamos os restantes elementos na posição correcta. A figura seguinte ilustra as sucessivas comparações: 2. (Valorização: 25%) Classes, vectores A empresa WeBuyYourDebt tem um sistema de informação para estar inteirada das cotações (ratings) dados por agências de notação às diversas entidades a quem compra dívida. Para isso tem definidas duas classes: a classe Rating representa informação sobre a a agência que definiu a cotação (nome), o nível da cotação ( AAA, AA, C, etc), se a entidade em questão está em vigilância pela agência ou não, e o valor decimal da taxa anual atribuída de acordo com a cotação; a classe BusinessEntity representa informação sobre uma entidade alvo e as correspondentes cotações. 2
class BusinessEntity { Rating ratings[]; /** * Usando os diversos ratings associados à entidade, calcular a taxa de juro. A taxa * final é a média dos diversos ratings acrescida de um spread definido como * constante: GLOBAL_SPREAD (adicionado à média calculada). * * No cálculo da média deve ter-se em conta se a entidade está em vigil^ancia (numa * watchlist). Se estiver, o valor do rating deve ser valorizado de WATCH_FACTOR * (ou seja multiplicado por). * * @return a taxa calculada */ public double calcinterestrate(); //... Um exemplo de um objecto representado pela classe BusinessEntity seria a informação sobre a CGD onde as várias cotações seriam dadas pela S&P, Moody s, etc. a) Implemente a classe Rating e respectivo constructor. O texto descreve 4 propriedades que caracterizam um rating, nomeadamente: nome da agência de notação que deu o rating - uma String o nível de cotação que a agência deu - uma String tem a entidade sob vigilância ou não - um boolean taxa de juro atribuída pela agência - um double. Percebendo isto a classe pode ser representada por: class Rating{ String agencianotificacao; String cotacaoatribuida; boolean emvigilancia; double taxajuro; Rating(String a, String c, boolean v, double t) { agencianotificacao= a; cotacaoatribuida= c; emvigilancia= v; taxajuro= t; // neste caso n~ao defini atributos privados pelo que n~ao // n~ao preciso de métodos de acesso ou de modificaç~ao 3
b) Implemente o método calcinterestrate() que calcula a taxa de juro a aplicar à entidade de acordo as regras definida na documentação dada. O problema consiste essencialmente em calcular uma média de um conjunto de valores. Cada valor antes de ser usado pode ter de ser multiplicado pelo WATCH FACTOR. Ao valor final de média temos de acrescentar o valor do GLOBAL SPREAD. class BusinessEntity { Rating ratings[]; public double calcinterestrate() { double taxa= 0; double watchfactor; int numratings= ratings.length; // primeiro somamos todas as taxas for (int i=0; i< numratings; i++) { // verificar se um dado rating deve ser valorizado if (ratings[i].emvigilancia) watchfactor= WATCH_FACTOR; else watchfactor= 1; // elemento neutro na multiplicaç~ao // calcula a soma acumulada das taxas de juro taxa= taxa + ratings[i].taxajuro*watchfactor; // por fim calcula a média acrescida do spread taxa= taxa/numratings + GLOBAL_SPREAD; return taxa; 3. (Valorização: 40%) Classes e Listas A liga dos campeões (champions league), organizada pela UEFA, é uma prova de selecção por etapas ou fases que levam ao apuramento do campeão europeu de um determinado ano. A primeira etapa importante é uma fase de qualificação (play-offs) que envolve algumas equipas campeãs de alguns países e outras que poderão ser segundos ou terceiros classificados nas suas ligas. Seguem-se outras etapas, fase de grupos com todas as equipas de um grupo a jogarem entre si, fase de eliminatórias e a final. Em cada etapa existe um conjunto de jogos realizados. De cada jogo registamos o nome da equipa visitada, o número de golos marcados pela equipa visitada, o nome da equipa visitante, e o número de golos da equipa visitante. Tendo em vista o registo dos resultados em memória para efeitos de elaboração de listagens várias, concebeu-se uma estrutura de dados conforme se ilustra na figura seguinte: 4
a) Os jogos que acontecem numa dada etapa são guardados numa lista ligada simples. Defina uma classe genérica LList<E> que implemente uma lista ligada simples, incluindo a implementação dos métodos construtores e a implementação de um método para adicionar um novo elemento no início da lista. Usando a definição dada nas aulas, precisamos de duas classes, uma a caracterizar um nó e outra a caracterizar a lista. Por simplicidade, e dado que não se pede no enunciado, não usamos atributos privados na classe que caracteriza um nó da lista, algo que deve ser feito numa solução mais geral: class Node<E> { E val; Node<E> next; Node(E v, Node<E> n) { val= v; next= n; class LList<E> { Node<E> first; int size; LList() { // construtor de lista vazia first= null; size= 0; boolean isempty() {return size==0; // adicionar na 1a posicao consiste em criar um novo nó // cujo atributo next referencie actual primeiro, ficando este // novo nó a ser o primeiro nó da lista void addfirst(e v) { first= new Node<E>(v,first); size++; 5
b) A ilustração mostra claramente um vector de objectos de uma classe Etapa que por sua vista faz referência a objectos de uma classe Jogo. Defina as duas classes, incluindo os métodos construtores correspondentes. Deve usar a definição genérica anterior de lista, caso não tenha respondido à pergunta anterior pode usar a classe correspondente do Java. Um objecto da classe Etapa precisa de ter apenas dois atributos, um nome da etapa (uma string) e uma referência para uma lista ligada com os jogos: class Etapa { String nome; // Qualific, Grupos, Elimina, Final LList<Jogo> jogos; // será a lista ligada de jogos Etapa(String n) { nome= n; jogos= new LList<Jogo>(); // inicialmente fica lista vazia A classe Jogo é muito simples e tem quatro atributos, os nomes das equipas e os golos que cada equipa marcou. class Jogo { String eqvisitada; // nome da equipa visitada int golosvisitada; // golos da equipa visitada String eqvisitante; // nome da equipa visitante int golosvisitante; // golos da equipa visitante Jogo(String casa, int gcasa, String fora, int gfora) { eqvisitada= casa; golosvisitada= gcasa; eqvisitante= fora; golosvisitante= gfora; c) Implemente na classe Etapa um método para inserir a informação de um jogo novo. A assinatura do método deverá ser: void adicionajogo(string eqcasa, int goloscasa, String eqfora, int golosfora);, onde os argumentos representam a informação relativa ao jogo. A implementação deste método requer apenas a criação de um objecto jogo e adicioná-lo à lista, por exemplo no início da lista. Lembrar que estamos na classe Etapa. class Etapa { String nome; LList<Jogo> jogos; void adicionajogo(string eqcasa, int goloscasa, String eqfora, int golosfora) { jogos.addfirst(new Jogo(eqCasa, goloscasa, eqfora, golosfora)); 6