Algoritmos e Estruturas de Dados I Modularizao Profa

  • Slides: 38
Download presentation
Algoritmos e Estruturas de Dados I – Modularização Profa. Mercedes Gonzales Márquez

Algoritmos e Estruturas de Dados I – Modularização Profa. Mercedes Gonzales Márquez

Modularização • Sempre é possível dividir problemas grandes e complicados em problemas menores e

Modularização • Sempre é possível dividir problemas grandes e complicados em problemas menores e de solução mais simples. • Problemas simples: Resolução direta. • Problemas mais complexos: Quebrar em problemas menores. Cada problema menor pode se tornar um módulo.

Modularização O algoritmo principal é aquele por onde começa a execução, e chama, eventualmente,

Modularização O algoritmo principal é aquele por onde começa a execução, e chama, eventualmente, os demais módulos. Módulo é um algoritmo que, geralmente, resolve um pequeno problema, e que está subordinado a um outro algoritmo que solicitará seu acionamento. É possível que um módulo chame outro módulo.

Construindo módulos • Critérios para orientar o processo de decomposição. Dividir o problema em

Construindo módulos • Critérios para orientar o processo de decomposição. Dividir o problema em suas partes principais. Analisar a divisão obtida para garantir coerência. Se alguma parte ainda permanecer complexa, subdividi-la mais. Analisar o resultado para garantir entendimento e coerência.

Vantagens da Modularização • Evitar extensos blocos de programa e portanto difíceis de ler

Vantagens da Modularização • Evitar extensos blocos de programa e portanto difíceis de ler e entender. • Dividir o programa em partes que possam ser logicamente compreendidas de forma isolada. • Reaproveitar blocos de programa já construídos (por você ou por outros programadores), minimizando erros e facilitando alterações.

Definindo um módulo Um módulo é definido da seguinte forma: tipo nome(tipo parâmetro 1,

Definindo um módulo Um módulo é definido da seguinte forma: tipo nome(tipo parâmetro 1, . . . , tipo parâmetro. N) Inicio comandos Fim retorne valor de retorno • Todo módulo deve ter um tipo (inteiro, real). Esse tipo determina qual será o tipo de seu valor de retorno. Este módulo recebe o nome de função.

Definindo um módulo Um módulo é definido da seguinte forma: tipo nome(tipo parâmetro 1,

Definindo um módulo Um módulo é definido da seguinte forma: tipo nome(tipo parâmetro 1, . . . , tipo parâmetro. N) Inicio comandos Fim retorne valor de retorno • O módulo também pode executar uma ação sem produzir um valor de retorno. Neste caso o troca-se o tipo pela palavra “nulo” e o comando retorne deixa de existir. Este tipo de módulo recebe o nome de procedimento.

Definindo um módulo Um módulo é definido da seguinte forma: tipo nome(tipo parâmetro 1,

Definindo um módulo Um módulo é definido da seguinte forma: tipo nome(tipo parâmetro 1, . . . , tipo parâmetro. N) Inicio comandos Fim retorne valor de retorno • Os parâmetros são variáveis que são inicializadas com valores indicados durante a invocação do módulo. • O comando retorne devolve para o invocador do módulo o resultado da execução deste.

Invocando um módulo • Quando o nome de um módulo é encontrado, ocorre um

Invocando um módulo • Quando o nome de um módulo é encontrado, ocorre um desvio no algoritmo principal ou módulo chamador para que os comandos do módulo chamado sejam executados. Ao término do módulo, a execução retornará ao ponto subsequente ao da sua chamada. • Exemplo:

Invocando um módulo • Exemplo: Algoritmo <exemplo 1> real soma(real: x, real: y) Início

Invocando um módulo • Exemplo: Algoritmo <exemplo 1> real soma(real: x, real: y) Início retorne (x+y) Fim Início Escreva (“Digite dois números reais: “) Leia ( x, y ) Escreva (“A soma de” x, “e”, y, “eh: ”soma(x, y)) Fim

Parâmetros são canais pelos quais se estabelece uma comunicação bidirecional entre um módulo e

Parâmetros são canais pelos quais se estabelece uma comunicação bidirecional entre um módulo e o algoritmo chamador (algoritmo principal ou outro módulo). Os dados são passados pelo algoritmo chamador através de argumentos ou também chamados parâmetros reais, e são recepcionados por meio de parâmetros formais.

Parâmetros Formais: São os nomes simbólicos introduzidos no cabeçalho dos módulos, usados na definição

Parâmetros Formais: São os nomes simbólicos introduzidos no cabeçalho dos módulos, usados na definição dos parâmetros do mesmo. Parâmetros Reais (ou argumentos): São aqueles que substituem os parâmetros formais quando da chamada do módulo.

Passagem de Parâmetros l Por valor • O argumento ou parâmetro real é avaliado,

Passagem de Parâmetros l Por valor • O argumento ou parâmetro real é avaliado, gerando um valor que é copiado para a variável declarada no módulo (parâmetro formal) • Qualquer alteração do parâmetro formal não é "transmitida" para a variável do argumento. • O argumento da chamada (parâmetro real) pode ser uma constante, uma variável ou uma expressão: 5, v 1+5 -v 2

Passagem de Parâmetros Exemplo: Algoritmo <teste> Inteiro: x Modulo porvalor(inteiro: a) Inicio a← 5

Passagem de Parâmetros Exemplo: Algoritmo <teste> Inteiro: x Modulo porvalor(inteiro: a) Inicio a← 5 Fim Inicio x ← 10 porvalor(x) escreva (x) Fim

Passagem de Parâmetros l Por referência • O argumento ou parâmetro real tem que

Passagem de Parâmetros l Por referência • O argumento ou parâmetro real tem que ser uma variável: v 1, v 2. . . • A variável do argumento (parâmetro real) é associada com a variável declarada no módulo (parâmetro formal) durantea execução do mesmo. • Qualquer alteração da variável do módulo (parâmetro formal) acontece também na variável do argumento. • Usaremos a seguinte convenção: o símbolo & indicará a passagem por referência no argumento e * no parâmetro formal.

Passagem de Parâmetros Exemplo: Algoritmo <teste> Inteiro: x Procedimento porreferencia(inteiro: *a) Inicio *a ←

Passagem de Parâmetros Exemplo: Algoritmo <teste> Inteiro: x Procedimento porreferencia(inteiro: *a) Inicio *a ← 5 Fim Inicio x ← 10 porreferencia(&x) escreva (x) Fim

Variáveis globais e locais Todo módulo é constituído por um sequência de comandos que

Variáveis globais e locais Todo módulo é constituído por um sequência de comandos que operam sobre um conjunto de variáveis que podem ser globais ou locais. Variáveis globais : Podem ser usadas em módulos internos a outro módulo do algoritmo onde foram declaradas. Variáveis locais: Só podem ser usadas no módulo do algoritmo onde foram declaradas. Elas não possuem significado fora deste módulo.

Variáveis globais e locais Uma variável local é criada (alocada na memória) no momento

Variáveis globais e locais Uma variável local é criada (alocada na memória) no momento em que o módulo que a define é chamado. Uma variável local é liberada da memória no momento em que o módulo que a define termina. Uma variável local somente existe (só pode ser utilizada) dentro do módulo que a define.

Variáveis globais e locais Caso um mesmo identificador (nome de variável) seja declarado em

Variáveis globais e locais Caso um mesmo identificador (nome de variável) seja declarado em módulos distintos, esses identificadores são considerados distintos entre si (variáveis distintas) O uso de variáveis locais minimiza a ocorrência de “efeitos colaterais” : o programador pode definir e utilizar as variáveis que desejar em um módulo sem interferir em outros módulos.

Exemplos • Ex. 2 –Faça um algoritmo que calcule o número de combinações de

Exemplos • Ex. 2 –Faça um algoritmo que calcule o número de combinações de n eventos em conjuntos de p eventos, p <=n. • Sem o conceito de função, teríamos que repetir três vezes as instruções para calculo do fatorial de um numero x. Com o conceito de função, precisamos apenas escrever essas instruções uma única vez e substituir x por n, p, e (n-p) para saber o resultado de cada calculo fatorial.

Algoritmo <combinacoes> real fatorial(inteiro: x) real: fat ← 1 inteiro: i Inicio para i

Algoritmo <combinacoes> real fatorial(inteiro: x) real: fat ← 1 inteiro: i Inicio para i de x até 1 passo -1 repita fat ← fat * i fim para retorne fat Fim Inicio Inteiro: n, p, C Leia (n, p) Se ((p >= 0) e (n >= 0) e (p <= n) entao C ← fatorial(n)/(fatorial(p)*(fatorial(n-p))) escreva C Fim se Fim Três chamadas a função fatorial

 • Ex. 3 Modifique o algoritmo anterior para trocar os valores das variáveis

• Ex. 3 Modifique o algoritmo anterior para trocar os valores das variáveis p e n quando p>n, para satisfazer a condição do enunciado que exige que p<=n. Algoritmo <combinacoes> real fatorial(inteiro: x) nulo troca(int *x, int *y) inteiro: aux Inicio aux ←*x *x ← *y *y ← aux Fim Passagem por referência de p e n. Inicio Inteiro: n, p, C Leia (n, p) se (p > n) entao troca(&p, &n) Fim se Se ((p >= 0) e (n >= 0)) entao C ← fatorial(n)/(fatorial(p)*(fatorial(n-p))) escreva C Fim se Fim

Ex. 4 - Faça uma função para determinar se um número inteiro é par

Ex. 4 - Faça uma função para determinar se um número inteiro é par ou não. Utilize esta função para calcular o total de números pares dentre um total de n números inteiros positivos. Algoritmo <Pares_Impares> inteiro par(inteiro: w) Início se (mod(w, 2)=0) então retorne (1) senão retorne(0) fim se Fim Início inteiro: n, i, x, somapar=0 Leia (n) Para i de 1 até n repita Leia ( x ) somapar ← somapar+par(x) Fim para Fim O retorno de par(x) será 1 ou 0, permitindo fazer a contagem sem o uso explícito de um contador

Ex. 5. Escreva um algoritmo que leia as medidas dos três lados a, b

Ex. 5. Escreva um algoritmo que leia as medidas dos três lados a, b e c de um paralelepípedo, calcule e escreva o valor da sua diagonal. L=sqr(a 2+b 2) D=sqr(L 2+c 2) c D b L a Algoritmo <paralelepipedo> real hipotenusa(real: a, real: b) real: hip Início hip ←sqr(a**2+b**2) retorne(hip) A função hipotenusa é invocada com os parâmetros: fim (1) hipotenusa (a, b) e (2) c Início real: a, b, c, d leia (a, b, c) d←hipotenusa(a, b), c) escreva d Fim A função hipotenusa é invocada com os parâmetros: (1) a e (2) b

Ex. 6. Segundo a conjectura de Goldbach, qualquer número par, maior que 2, pode

Ex. 6. Segundo a conjectura de Goldbach, qualquer número par, maior que 2, pode ser escrito como a soma de dois números primos. Ex. 8=3+5, 16=11+5, 68=31+37, etc. Dado um conjunto de números inteiros positivos pares, fazer um algoritmo que calcule, para cada número, um par de números primos cuja soma seja igual ao próprio número. Adotar como flag um número negativo. Para verificar se um número é primo, fazer uma função que deverá retornar em uma variável lógica o valor verdadeiro, se o número for primo, e falso, em caso contrário.

Lembre-se que a raiz de n divide os divisores de n em dois grupos:

Lembre-se que a raiz de n divide os divisores de n em dois grupos: os menores e os maiores que a sua raiz, sendo os de um grupo de certa forma “complementares” aos do outro grupo. Então será suficiente procurarmos divisores triviais de n percorrendo somente até a raiz de n. Algoritmo <conjectura> inteiro primo(inteiro: n) inteiro: i Início i ← 2 enquanto (i<=sqr(n)) faça se (mod(n, i)=0) então retorne(0) fim se i ←i+1 fim enquanto retorne(1) fim Início inteiro: i, par leia (par) enquanto (par>0) faça para i de 1 até par repita se (primo(i) e primo (par-i)) então escreva (i, par-i) i ←par fim se fim para leia (par) fim enquanto Fim Se i é um primo então resta verificar se par-i é também um primo, o que fará que tenhamos os dois números cuja soma dará o número par.

Ex. 7. Fazer uma função que, dado um número inteiro N, retorne a soma

Ex. 7. Fazer uma função que, dado um número inteiro N, retorne a soma dos divisores deste número, exceto ele próprio. Fazer um algoritmo que, utilizando a função anterior, determine e escreva todos os pares de números amigos em um intervalo [A, B]. Os valores de A e B (A<B), inteiros maiores que zero , deverão ser lidos. Dois números inteiros M e N são amigos se a soma dos divisores de M, excluindo M, é igual a N e a soma dos divisores de N, excluindo N, é igual a M.

Algoritmo <amigos> Início inteiro soma_div(inteiro: n) inteiro: a, b, m, n inteiro: soma, i

Algoritmo <amigos> Início inteiro soma_div(inteiro: n) inteiro: a, b, m, n inteiro: soma, i leia (a, b) Início para m de a até b repita soma ← 1 n ← soma_div(m) i ← 2 se (n>=a e n<=b e soma_div(n)=m) enquanto (i<sqr(n)) faça escreva (m, n) se (mod(n, i)=0) então fim se soma←soma+ i + n/i fim se fim i ←i+1 fim enquanto se (i=sqr(n)) soma←soma+i fim se retorne(soma) fim Lembre-se que a raiz de n divide os divisores de n em dois grupos: os menores e os maiores que a sua raiz, sendo os de um grupo de certa forma “complementares” aos do outro grupo. Então se acharmos um divisor i menor que a raiz, também haverá um divisor n/i no grupo dos maiores que a raiz.

Funções com registros como parâmetros • Uma função não somente considera dados primitivos como

Funções com registros como parâmetros • Uma função não somente considera dados primitivos como parâmetros, podemos também ter necessidade de dados da passagem de dados tipo registro como no exemplo abaixo. Ex. 8. Calcular e escrever a área total de 10 tetraedros, dadas as coordenadas de cada um de seus quatro vértices. Para tanto, deverão ser utilizados os seguintes módulos: (a) Que calcula a distância entre dois pontos do espaço; (b) Que calcula a área de um triângulo em função de seus lados onde é o semi-perímetro do triângulo (a+b+c)/2.

Funções com registros como parâmetros Como os 4 vértices do tetraedro são pontos no

Funções com registros como parâmetros Como os 4 vértices do tetraedro são pontos no espaço, podemos criar um registro chamado ponto 3 d, que considere as três coordenadas de um ponto no espaço. Assim: Tipo ponto 3 d : registro real: x, y, z Fim registro • • Assim podemos usar um vetor de 4 elementos do tipo ponto 3 d que contenha os 4 vértices do tetraedro.

Funções com vetores como parâmetros • Um vetor passado como parâmetro é implicitamente passado

Funções com vetores como parâmetros • Um vetor passado como parâmetro é implicitamente passado por referência. • o acesso aos elementos de v não precisa do modificador * • Qualquer alteração de valor de um elemento de v é uma alteração no valor do vetor ‘original’. Exemplo: O seguinte procedimento lê um vetor de tamanho tam. nulo le_vetor(inteiro: vet[], inteiro: tam){ inteiro: i Para i de 1 até tam repita leia (vet[i])

Funções com vetores como parâmetros E no algoritmo principal dois vetores são declarados e

Funções com vetores como parâmetros E no algoritmo principal dois vetores são declarados e passados por referência para fazer a leitura dos seus dados. Inicio inteiro: vet 1[5], vet 2[5] le_vetor(vet 1, 5) le_vetor(vet 2, 5) Fim Acrescente um procedimento que faça a troca dos elementos entre dois vetores e outro procedimento que imprima os valores dos vetores. Faça a chamada do procedimento imprima antes da troca e depois da troca.

Ex 9. Escreva uma função chamada MAIORES com três parâmetros de entrada: Um valor

Ex 9. Escreva uma função chamada MAIORES com três parâmetros de entrada: Um valor inteiro x, um vetor de inteiros V e o tamanho n (1<n<50). A função deverá retornar a quantidade de inteiros em V maiores ou iguais que x. Escreva um algoritmo que, dado um conjunto de n números inteiros diferentes, use a função MAIORES para mostrar os números na ordem decrescente

Ex. 10 -A função ganhador determina o número que apareceu mais vezes dentre um

Ex. 10 -A função ganhador determina o número que apareceu mais vezes dentre um conjunto de n números. Supõe-se que os valores possíveis de cada número estão entre 1 e 6, inclusive, e que sempre haverá um único número vencedor. Obs. Os n números estão armazenados em um vetor V que é passado como parâmetro e o valor n é também passado por parâmetro. Sabendo-se que um jogo de dados ocorre 40 vezes por dia, faça um algoritmo que lendo os dados 30 dias correspondentes a um mês de jogo: (a) Determine o número ganhador do dia, utilizando-se a função anterior e escreva este número e a mensagem “RESULTADO DIARIO”; (b) Verifique também qual o número ganhador do mês e escreva este número e a mensagem “RESULTADO MENSAL DO JOGO”.

Os valores possíveis contidos no vetor V são os inteiros de 1 até o

Os valores possíveis contidos no vetor V são os inteiros de 1 até o 6, então é inteiro ganhador(inteiro: V[], inteiro: n) prático criar um vetor de 6 contadores, Inteiro: i, maior, cont[6] onde o valor contido no índice i deste Inicio vetor corresponderá ao número de ocorrências do valor i no vetor V. Para i de 1 até 6 repita Algoritmo <ganhadores> cont[i] ← 0 Fim Para i de 1 até n repita cont[V[i]] ← cont[V[i]]+1 Fim Para maior← 1 contmaior←cont[1] Para i de 2 até 6 repita Se (cont[i]>contmaior) então contmaior← cont[i] maior←i Fim se Fim Para Retorne(maior) Fim

Inicio inteiro: i Para i de 1 até 30 repita para j de 1

Inicio inteiro: i Para i de 1 até 30 repita para j de 1 até 40 repita leia dia[j] fim para mes[i] ← ganhador(dia, 40) fim para ganhador_mensal ← ganhador(mes, 30) Fim

Funções e Procedimentos Ex. 11 - Foi realizada uma pesquisa de algumas características físicas

Funções e Procedimentos Ex. 11 - Foi realizada uma pesquisa de algumas características físicas de 50 habitantes de uma certa região. De cada habitante foram coletados os seguintes dados: sexo, cor dos olhos (azuis, verdes ou castanhos), cor dos cabelos (louros, pretos ou castanhos) e idade. Faça um procedimento que leia esses dados em um vetor de registro. O vetor de registro deve ser enviado por referência. nulo leia (habitante: dados[]) inteiro: i Início Para i de 1 até 50 repita leia(dados[i]. sexo, dados[i]. cor_olhos, dados[i]. cor_cab) leia(dados[i]. idade) Fim para Fim Nota: No algoritmo principal deve ser definido o tipo habitante.

Funções e Procedimentos Faça um procedimento que receba o vetor de registro definido n

Funções e Procedimentos Faça um procedimento que receba o vetor de registro definido n exercício anterior, por referência, e retorne também por referëncia: a maior idade entre os habitantes e a quantidade de individuos do sexo feminino cuja idade está entre 18 e 35 (inclusive) e que tenham olhos verdes e cabelos louros. nulo informacoes(habitante: dados[], inteiro: *maioridade, *soma) inteiro: i Início *soma← 0 *maioridade ← 0 Para i de 1 até 50 repita se (dados[i]. idade>*maioridade) *maioridade ← *dados[i]. idade se (dados[i]. sexo=“F” e dados[i]. idade>=18 e dados[i]. idade<=35 e dados[i]. cor_olhos=“verdes” e dados[i]. cor_cab=“louros”) *soma ←*soma+1 fim se Fim para Fim