Revisão Algoritmos

42
REVISÃO ALGORITMOS

Transcript of Revisão Algoritmos

Page 1: Revisão Algoritmos

REVISÃO ALGORITMOS

Page 2: Revisão Algoritmos

Prof. Christiano Colen VenancioUNIPAC – Campus Vale do Aço – Ipatinga - 2007

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

2

Page 3: Revisão Algoritmos

INDICE

1 Introdução_____________________________________________________________________________4

2 Portugol_______________________________________________________________________________4

2.1 Tipos básicos_______________________________________________________________________________4

2.2 Comandos básicos__________________________________________________________________________4

2.3 Blocos e comandos básicos de controle_________________________________________________________4

2.4 Outras Estruturas de Repetição_______________________________________________________________6

2.5 Seleção de Múltipla Escolha__________________________________________________________________7

2.6 Definição de Novos Tipos de Dados____________________________________________________________7

2.7 Cadeia de Caracteres________________________________________________________________________8

2.8 Ordenação e Busca em Vetor_________________________________________________________________8

2.9 Ordenação pelo método Bolha________________________________________________________________9

2.10 Ordenação pelo método de Inserção__________________________________________________________11

2.11 Busca Linear______________________________________________________________________________13

2.12 Busca Binária_____________________________________________________________________________15

2.13 Estruturas Condicionais Encadeadas__________________________________________________________17

3 Matrizes______________________________________________________________________________17

3.1 Matrizes Bidimensionais____________________________________________________________________17

4 Modularização________________________________________________________________________18

4.1 Benefícios da Modularização________________________________________________________________19

4.2 Ferramentas para Modularização____________________________________________________________19

4.3 Modos de Transferência de Parâmetros_______________________________________________________20

4.4 Passagem por Valor________________________________________________________________________20

4.5 Passagem por Referência____________________________________________________________________20

4.6 Passagem por valor x por referência__________________________________________________________21

4.7 Criando Funções__________________________________________________________________________22

4.8 Criando Procedimentos_____________________________________________________________________22

4.9 Solicitando a execução de um módulo_________________________________________________________23

4.10 Exemplo de um Algoritmo Modularizado______________________________________________________24

5 Recursividade_________________________________________________________________________25

5.1 Exemplo de Problema Recursivo_____________________________________________________________25

5.2 Recursão X Iteração________________________________________________________________________26

6 Apontadores__________________________________________________________________________26

7 Estrutura de Dados Heterogênea__________________________________________________________27

7.1 Introdução________________________________________________________________________________27

7.2 Registros_________________________________________________________________________________27

7.3 Trabalhando com Registro__________________________________________________________________28

7.4 Vetores de Registro________________________________________________________________________29

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

3

Page 4: Revisão Algoritmos

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

4

Page 5: Revisão Algoritmos

1 Introdução

Esta apostila tem como objetivo revisar os conceitos de algoritmos, apresentando de uma maneira sintética os conceitos de algoritmos e portugol. Iremos introduzir o conceito de Matrizes e funções.

2 PortugolÉ uma linguagem de expressão de algoritmos. É considerada uma pseudolinguagem, cuja função é fornecer a notação para a criação de algoritmos.

2.1 Tipos básicosNo PORTUGOL existem quatro tipos básicos, isto é, tipos básicos de dados que podem ser utilizados: INTEIRO, REAL, CARACTER e LÓGICO.Uma variável pode ser entendida como um local onde se pode colocar qualquer valor do conjunto de valores possíveis do tipo básico associado. O nome da variável é o identificador tal como definido anteriormente. Por exemplo:Toda variável deve ser declarada conforme a sintaxe apresentada na figura abaixo.A semântica de uma declaração de variáveis corresponde à criação de locais na memória, rotulada com o nome do identificador (variável) e marcada com o tipo de valores que ela pode conter.

Diagrama que representa a definição de uma variável.Podemos ter uma sequencia de caracteres, denominada CADEIA. Abaixo segue um exemplo do uso desse tipo:

Cadeia : Nome;2.2 Comandos básicosO comando de ATRIBUIÇÃO é utilizado para atribuir um valor a uma variável. Para isso usa-se o símbolo ← , conforme a seguinte sintaxe:

A notação usada para expressões é basicamente uma forma linear comumente usada na matemática, que pode conter operadores:ARITMÉTICOS: +, -, /, *, raiz( ), **, sen( ), cos( ), mod, div,...LÓGICOS: e, ou, não ( Λ, V, . )RELACIONAIS: =, ≠, >, ≥ (ou >=), <, ≤ (ou <=)É importante observar que o resultado da expressão (do lado direito do comando de atribuição) deve ser coerente com o tipo declarado para a variável (do lado esquerdo).

2.19 Blocos e comandos básicos de controleUm bloco pode ser definido como um conjunto de comandos com uma função bem definida.Serve também para definir os limites onde as variáveis declaradas em seu interior são conhecidas.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

5

Page 6: Revisão Algoritmos

Exemplo:Uma seqüência simples é um conjunto de comandos separados por ponto e vírgula (;), que serão executadas numa seqüência linear de cima para baixo.Exemplo:comando1;comando2;comando3;...comandoN;

Quando a ação a ser executada depender de uma inspeção (teste), teremos uma alternativa, ou estrutura condicional, simples ou composta.Exemplo de uma estrutura condicional simples:

Exemplo de uma estrutura condicional composta:

Nos comandos apresentados, < condição > é qualquer expressão cujo resultado seja falso ou verdadeiro.Uma estrutura de repetição é quando um conjunto de ações é executado repetidamente enquanto uma determinada condição permanece válida (ou seja, quando o resultado de da expressão é um valor lógico verdadeiro).Exemplo de uma estrutura de repetição:

Enquanto o valor da < condição > for verdadeiro, as ações dos comandos são executadas e quando se tornar falso, o comando é abandonado. Se já da primeira vez o resultado é falso, os comandos não são executados.Até agora todos os valores calculados pelos algoritmos foram gerados e permaneceram na memória. Para obter ou para fornecer dados ao ambiente exterior ao algoritmo, por exemplo do teclado e para o vídeo, é preciso utilizar comandos de entrada e saída. O comando de entrada é leia e o comando de saída é imprima, e suas sintaxes são apresentadas a seguir.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

6

Page 7: Revisão Algoritmos

Exemplo de um algoritmo que usa comandos de entrada e saída:

2.4 Outras Estruturas de RepetiçãoSerão apresentadas a seguir outras duas estruturas de repetição que também podem ser utilizadas na construção de algoritmos usando o PORTUGOL, são elas: repita e para.A estrutura de repetição repita difere da enquanto no que diz respeito ao momento em que o teste da condição é submetido.

Na estrutura enquanto o teste é realizado antes da execução do primeiro loop, ou seja, pode ser que os comandos não sejam realizados sequer uma vez, caso a condição seja falsa já na primeira vez em que foi testada. Já na repita os comandos sempre serão executados pelo menos uma vez, até que a condição seja testada, no final da estrutura.

A estrutura de repetição para difere das estruturas enquanto e repita, pois utiliza uma variável de controle, que atua como um contador de repetições.

Observando o exemplo, percebe-se que foi utilizada uma variável do tipo inteiro (I), que deve ter sido declarada anteriormente. Esta estrutura irá executar os comandos 10 vezes, pois possui I variando automaticamente de 1 em 1 (passo 1) até 10, ou seja, não é necessário fazer o incremento deste dentro da estrutura de repetição.O comando abandone só tem sentido dentro de um comando de repetição (enquanto, repita e para). Além disso, estará sempre associado ao teste de uma condição com comando se.Sintaxe: abandone;A semântica do comando é a seguinte: quando o abandone é encontrado, o próximo comando a ser executado é o primeiro logo após o fim do comando de repetição mais interno onde este aparece.Exemplo:

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

7

Page 8: Revisão Algoritmos

2.5 Seleção de Múltipla EscolhaAlgumas vezes, em um problema necessitamos escolher uma entre várias alternativas, apesar da seleção encadeada ou aninhada ser uma opção para este tipo de construção, ela não é uma maneira elegante de construção, além de muitas vezes dificultar o entendimento de sua lógica. Neste caso, utilizamos a seleção de múltipla escolha.

Exercício: Determinar se uma letra digitada é vogal ou consoante..

2.6 Definição de Novos Tipos de DadosNem sempre os tipos básicos (inteiro, real, caracter e lógico) são suficientes para exprimir estruturas de dados em algoritmos. Daí a necessidade de novos tipos de dados serem criados. Um destes tipos é o vetor.No PORTUGOL a criação de um vetor segue as especificações:tipo nome_do_tipo = vetor [li:ls] <tipo_básico>; ou tipo nome_do_tipo = vetor [quantidade] <tipo_básico>;É dado um nome_do_tipo ao novo tipo de vetor criado, onde li é o limite inferior e ls é o limite superior de um intervalo que define o tamanho do vetor (valores inteiros), e tipo_básico é um dos tipos básicos já conhecidos. Esta especificação apenas indica um modelo para a criação de variáveis deste novo tipo. Para efetivar esta estrutura dentro do algoritmo, é necessário declará-la dando um nome a variável que será criada segundo o modelo especificado.Exemplo: um vetor que armazena as notas de todos os alunos de uma turma com 25 alunos.tipo v = vetor [1:25] real;v: NOTAS;O número de elementos de um vetor é dado por ls-li+1. Isto significa que as posições do vetor são identificadas a partir de li, com incrementos unitários até ls.

Cada elemento de um vetor é tratado como se fosse uma variável simples. Para referência a um elemento do vetor utiliza-se o nome do vetor e a identificação do elemento (índice) entre colchetes ([ ]).Por exemplo, se quisermos atribuir o valor de uma 45 a nota do 6o aluno (que é identificado pelo índice 6 do vetor de notas): NOTAS[6] <- 45;

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

8

Page 9: Revisão Algoritmos

Exemplo: O que será impresso no algoritmo abaixo?

Exercício: Um professor de uma turma com 30 alunos quer armazenar as notas de seus alunos em um vetor e depois calcular a média geral da turma. Escreva um algoritmo que solucione este problema usando uma estrutura de vetor.

2.7 Cadeia de CaracteresA maior parte dos processamentos efetuados atualmente exige a manipulação de cadeias de caracteres. Uma cadeia de caracteres é uma seqüência de letras, algarismos ou símbolos (sinais de pontuação parênteses etc). Portanto, uma cadeia de caracteres é uma lista linear (vetor) em que cada elemento é um caracter.Devido à grande utilização de cadeias de caracteres vamos definir o tipo de dados cadeia que descreve todas as seqüência de caracteres, bem como a cadeia vazia. O tipo de dados cadeia determina que toda cadeia seja finalizada pelo caracter ASCII 0(zero), ou seja a uma variável do tipo cadeia somente com caracter 0 indica que ela está vazia, e o seu tamanho é 0. Como exemplo, será criado primeiramente o tipo de dado cadeia, e depois uma variável do tipo cadeia. A atribuição de um valor válido a variável cadeia, a sua impressão e depois a leitura de uma cadeia através da instrução Leia.

Os valores atribuídos à variável frase devem estar entre aspas duplas, tal como “Entre com o seu nome:”.Quando a variável nome é inicializada pela instrução Leia, automaticamente é inserido o caracter 0 no final da cadeia. Lembremos que “a” e ‘a’ são valores pertencentes a tipos distintos. No primeiro caso, temos uma cadeia de tamanho 1 que contém apenas a letra a; no segundo, temos a letra a, que é um valor válido para tipo de dado caracter.

2.8 Ordenação e Busca em VetorA importância de mantermos “coisas” ordenadas é fundamental em muitas atividades. Você já imaginou se os sobrenomes dos assinantes da lista telefônica de São Paulo não estivessem dispostos em ordem alfabética? Seria uma tarefa monumental encontrar o telefone de um usuário da companhia telefônica, não?No processamento de dados, a tarefa de ordenação também exerce um papel fundamental, pois a ordem na qual os dados são processados por um programa pode exercer uma grande influência em seu desempenho e

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

9

Page 10: Revisão Algoritmos

simplicidade. Por esta razão, a ordenação (ou classificação) de dados tem sido um assunto estudado exaustivamente em Computação, e muitas soluções interessantes foram propostas ao longo dos últimos 40 anos.Na maioria das vezes, a ordenação de dados é realizada com o objetivo de facilitar a busca de dados. Isto porque se os dados a serem recuperados em um certo conjunto de dados estiverem dispostos segundo uma dada ordem, a tarefa de encontrá-los no conjunto se tornará mais rápida e simples.

2.9 Ordenação pelo método BolhaUm método simples de ordenação por troca é a estratégia conhecida como bolha que consiste, em cada iteração, “borbulhar” o maior elemento para fim da lista inicialmente percorre-se a lista dada da esquerda para a direita, comparando pares de elementos consecutivos, trocando de lugar os que estão fora de ordem. Considere um vetor de seis elementos com índices de 0 até 5:

A ordenação do vetor em ordem crescente é:

A idéia é comparar os elementos dois a dois e ir jogando os elementos maiores para as últimas posições do vetor até obter o vetor classificado. Uma vez que o maior elemento tenha atingido a mais alta posição é reduzido o tamanho do vetor a ser classificado, como se pode ver pelos passos no esquema que se segue:

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

10

Page 11: Revisão Algoritmos

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

11

Page 12: Revisão Algoritmos

2.10 Ordenação pelo método de InserçãoO algoritmo de ordenação por inserção simula o processo de ordenação utilizado por um jogador de baralho. Suponha que exista um maço de cartas de baralho em uma mesa e que um jogador retira uma carta desse maço por vez.O jogador utiliza sua mão direita para retirar uma carta do maço e sua mão esquerda para segurar as cartas retiradas com a mão direita. Inicialmente, a mão esquerda está vazia, pois todas as cartas estão na mesa. Após retirar a primeira carta, o jogador a põe imediatamente na mão esquerda, que está vazia.Em seguida, ele retira uma outra carta e a põe na mão esquerda, comparando-a com a carta lá existente. Se a carta retirada é menor do que a carta na mão esquerda, ela deve ficar à esquerda desta. Caso contrário, ela deve ficar à direita. Neste momento, as duas cartas na mão esquerda encontram-se ordenadas.O processo segue com a retirada da terceira carta. O jogador, então, insere a terceira carta na mão esquerda. Esta inserção é realizada comparando-se a carta retirada com as duas cartas já existentes na mão esquerda. Como tais cartas estão dispostas ordenadamente, a comparação se inicia pela carta mais à direita. Se a carta retirada é maior do que ela, então aquela é inserida à direita desta. Caso contrário, a carta retirada é comparada com a carta mais à esquerda. Caso ela seja maior do que esta, ela ficará entre as duas. Caso contrário, ela passa a ser a carta mais à esquerda das três.Para as demais cartas, o processo segue da mesma forma. A mão esquerda sempre conterá cartas ordenadas da esquerda para a direita. Digamos, então, que a mão esquerda possua n cartas. Ao tentarmos inserir uma nova carta na mão esquerda, devemos compará-la primeiro com a carta mais à direita, a n-ésima carta da esquerda para a direita. Se a nova carta é maior do que ela, colocamos a nova carta a sua direita. Caso contrário, comparamos a nova carta com a carta na (n-1)-ésima posição e assim por diante. Desta forma, após inserirmos a última carta do maço na mão esquerda, teremos nela as cartas completamente ordenadas.Vamos, agora, examinar um algoritmo de ordenação de dados que utiliza a idéia descrita antes para classificar um conjunto de números armazenados em um vetor. Este algoritmo inicia considerando o elemento na primeira posição do vetor como sendo a única “carta na mão esquerda” e o restante do vetor como sendo o “maço”.Daí, o algoritmo segue por inserir o elemento na segunda posição do vetor em sua posição correta. Isto é, comparando-o com o elemento na primeira posição e inserindo-o na primeira posição se necessário. Neste ponto, tem-se que o segmento do vetor formado pelas duas primeiras posições encontra-se ordenado. O algoritmo segue, então, com a inserção do terceiro elemento do vetor na posição correta do segmento formado pelas duas primeiras posições e sua própria posição.De forma geral, o algoritmo varre o vetor do segundo ao último elemento. Na i-ésima varredura, o algoritmo insere o (i + 1)-ésimo elemento do vetor na posição correta do segmento que vai do primeiro elemento do vetor até o (i + 1)-ésimo.O algoritmo encontra a posição correta de um elemento por compará-lo com os elementos do segmento do vetor a sua esquerda, da esquerda para a direita. A posição correta é encontrada quando o elemento do segmento sendo comparado é menor ou igual a ele. Obviamente, para se inserir um elemento no meio de um segmento de um vetor, deve-se deslocar os elementos que ficarão a sua direita uma casa para a direita. Caso contrário, danificaríamos o vetor. Considere a variável V como um vetor de números com n elementos.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

12

Page 13: Revisão Algoritmos

Vamos simular a ordenação pelo método de inserção, considerando um vetor com 6 elementos:

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

13

Page 14: Revisão Algoritmos

2.11 Busca LinearO algoritmo de busca a ser estudado nesta seção recebe um vetor de dados não ordenados e um elemento a ser encontrado neste vetor.O resultado do algoritmo é a posição em que o elemento se encontra no vetor, caso ele esteja lá, ou um valor inválido que represente o insucesso da busca, caso o elemento não esteja no vetor.A busca é realizada comparando o valor do elemento a ser encontrado com os elementos do vetor, um a um, da esquerda para a direita. O pior dos casos na busca linear, se dá quando o valor procurado é igual ao do último elemento do vetor, o algoritmo realizará a comparação do valor procurado com todos os elementos do vetor.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

14

Page 15: Revisão Algoritmos

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

15

Page 16: Revisão Algoritmos

2.12 Busca BináriaA idéia do algoritmo de busca binária é comparar um elemento do vetor ordenado de dados, sorteado aleatoriamente, com o elemento a ser encontrado.Se o elemento procurado é igual ao elemento sorteado, a busca termina. Entretanto, se o elemento sorteado for menor do que o elemento a ser encontrado, então devemos restringir a busca ao segmento do vetor à direita do elemento sorteado, pois o segmento formado pelos elementos à esquerda deste é formado apenas por elementos menores do que o elemento procurado.Raciocínio análogo pode ser aplicado caso o elemento procurado seja menor do que o elemento sorteado. O próximo passo é aplicar o mesmo processo de busca ao segmento que pode conter o elemento procurado. Este processo continua até o elemento ser encontrado ou não haver mais segmento para procurar o elemento. O algoritmo a seguir representa esta idéia.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

16

Page 17: Revisão Algoritmos

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

17

Page 18: Revisão Algoritmos

2.13 Estruturas Condicionais EncadeadasExistem casos em que é necessário se estabelecerem verificações de condições sucessivas, onde uma determinada ação poderá ser executada se um conjunto anterior de condições for satisfeito.Isto significa usar uma condição dentro de outra. Este tipo de estrutura pode possuir diversos níveis de condição, sendo chamada de aninhamento ou encadeamento de estruturas condicionais. Exemplo:

3 MatrizesUma matriz é uma estrutura de dados homogênea, ou seja, todos os elementos de uma matriz são do mesmo tipo. Um vetor é uma matriz unidimensional, a partir de agora serão apresentadas matrizes com mais de uma dimensão.3.1 Matrizes BidimensionaisA forma mais comum de trabalhar com matrizes é utilizando duas dimensões, apesar de que em alguns casos possa ser necessário trabalhar com mais de duas. Uma matriz bidimensional é composta por linhas e colunas. As linhas podem ser consideradas como a primeira dimensão e as colunas a segunda dimensão. É preciso definir o tamanho de cada uma dessas dimensões, ou seja, o número de linhas e o número de colunas que esta matriz deverá possuir.Exemplo: Definição de uma matriz com 8 linhas e 5 colunas.

Exemplo de algoritmo utilizando matriz com duas dimensões:Seja uma matriz a representação das notas obtidas pelos alunos em uma determinada disciplina. A quantidade de linhas deverá ser equivalente ao número de alunos, neste caso 25. Cada coluna deverá conter o valor de uma das avaliações de cada aluno, neste caso são 3 avaliações. O algoritmo deve preencher a matriz com as notas.

Exercício: Escreva um algoritmo que receba as notas referentes a três avaliações realizadas por 25 alunos, e as armazene numa matriz, juntamente com a média total obtida pelo aluno. Sabendo que: as duas primeiras avaliações têm peso de 35 cada uma e a terceira tem peso de 30 pontos. Além disso, para cada média total deve

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

18

Page 19: Revisão Algoritmos

ser enviada uma mensagem informando se o aluno foi aprovado (>=50) ou reprovado (<50) e qual foi a porcentagem da turma aprovada.

4 ModularizaçãoNo fim da década de 60, alguns problemas no desenvolvimento de sistemas de programação levaram os países desenvolvidos a um evento chamado “crise de software”. Os custos das atividades de programação mostravam a cada ano uma clara tendência a se elevarem muito em relação aos custos dos equipamentos, e isto era devido ao avanço tecnológico na fabricação dos equipamentos de computação e a lenta evolução de técnicas aplicadas ao desenvolvimento de software.A ausência de uma metodologia para a construção de programas conduzia a programas geralmente cheios de erros e com altos custos de desenvolvimento que, conseqüentemente, exigiam custos elevados para a sua correção e manutenção futuras. A programação estruturada foi o resultado de uma série de estudos e propostas de metodologias para desenvolvimento de software. Uma das técnicas aplicadas na programação estruturada, a modularização de programas é uma ferramenta para a elaboração de programas visando, os aspectos de confiabilidade, legibilidade, manutenibilidade e flexibilidade, dentre outros.A modularização é um processo que aborda os aspectos da decomposição de algoritmos em módulos. Módulo é um grupo de comandos, constituindo um trecho do algoritmo, com uma função bem definida e o mais independente possível em relação ao resto do algoritmo.Há dois tipos de módulos: Função: sempre retorna um e apenas um valor ao algoritmo que lhe chamou. Cada função tem associada ao

seu valor de retorno um tipo explícito. Da mesma maneira com que os parâmetros são fixos para todas as chamada o retorno também é fixo. Ela pode ser vista como uma expressão que é avaliada para um único valor, sua saída, assim como uma função em Matemática.

Procedimento: é um tipo de módulo usado para várias tarefas, não produzindo valores de saída, ou seja, nunca retornam valores. Em algumas linguagens não existem explicitamente.Exemplo – Seja um algoritmo para calcular o salário líquido de um empregado, com as seguintes etapas:

Onde “Determine o salário” pode ser refinado como:Calcule as vantagensCalcule as deduçõesSALARIOLIQ <- VANTAGENS – DEDUÇÕESNo refinamento anterior não houve preocupação de como o processo de cálculo das vantagens e deduções seria efetuado. Essas ações constituem funções bem definidas e que serão executadas por módulos específicos, neste caso, o algoritmo anterior ficaria:

Exemplo da descrição estrutural da modularização:

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

19

Page 20: Revisão Algoritmos

A maneira mais intuitiva de proceder a modularização de problemas é feita definindo um módulo principal de controle e módulos específicos para as funções do algoritmo. Recomenda-se que os módulos de um programa tenham um tamanho limitado, pois módulos muito grandes são difíceis de ser compreendidos e, em geral, são multifuncionais.As linguagens de programação dispõem de recursos que facilitam a construção e manipulação de módulos, permitindo não só a modularização dos comandos do programa, como também dos dados utilizados.Cada módulo pode definir as próprias estruturas de dados, suficientes e necessárias apenas para atingir o objetivo final do módulo. Todo módulo é constituído por uma seqüência de comandos que operam sobre um conjunto de objetos, que podem ser globais ou locais.Objetos globais são entidades que podem ser usadas em módulos internos a outro módulo do algoritmo onde foram declaradas.Objetos locais são entidades que só podem ser usadas no módulo do algoritmo onde foram declaradas. Estes objetos não possuem nenhum significado fora deste módulo.São exemplos de objetos globais ou locais: variáveis, arquivos, outros módulos, etc.A comunicação entre módulos deverá ser feita através de vínculos, utilizando-se objetos globais ou transferência de parâmetros.

4.1 Benefícios da ModularizaçãoA independência do módulo permite uma manutenção mais simples e evita efeitos colaterais no restante do algoritmo;. A elaboração do módulo pode ser feita independentemente e em época diferente do restante do algoritmo;. Testes e correções dos módulos podem ser feitos separados;. Um módulo pode ser utilizado em outros algoritmos que requeiram o mesmo processamento por ele executado.

4.2 Ferramentas para ModularizaçãoSub-rotinas e funções são módulos que servem aos objetivos:. Evitar que em certa seqüência de comandos necessária em vários locais de um algoritmo tenha que ser escrita repetidamente nesses locais;. Dividir e estruturar um algoritmo em partes fechadas e logicamente coerentes;. Aumentar a legibilidade de um algoritmo.Sub-rotinas e funções são módulos hierarquicamente subordinados a um algoritmo, comumente chamado de módulo principal. Da mesma forma uma sub-rotina ou uma função pode conter outras sub-rotinas e funções aninhadas.A sub-rotina e a função são criadas através das suas declarações em um algoritmo e para serem executadas, necessitam de ativação por um comando de chamada. A declaração de uma subrotina ou função é constituída de um cabeçalho, que a identifica e contém seu nome e uma lista de parâmetros formais, e de um corpo que contém declarações locais e os comandos.

As funções têm a característica de retornar ao algoritmo que as chamou um valor associado ao nome da função.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

20

Page 21: Revisão Algoritmos

Como esta função irá retornar um valor, este pode ser atribuído a alguma variável, contanto que esta seja de tipo compatível.

Ao terminar a execução dos comandos de uma sub-rotina ou função, o fluxo de controle retorna ao comando seguinte àquele que provocou a chamada.

4.19 Modos de Transferência de ParâmetrosOs parâmetros de uma sub-rotina ou função classificam-se em: de entrada – são aqueles que têm seus valores estabelecidos fora da sub-rotina ou função e não podem ser

modificados dentro dela. de saída – são aqueles que têm seus valores estabelecidos dentro da sub-rotina ou função. de entrada-saída – são aqueles que têm seus valores estabelecidos fora da sub-rotina ou função, mas

podem ter seus valores alterados dentro dela.A vinculação entre módulos pode ser feita através da transferência ou passagem de parâmetros, que associam parâmetros atuais com parâmetros formais. Dentre os modos de transferência de parâmetros, pode-se destacar: a passagem por valor, a passagem por resultado e a passagem por referência.Na passagem de parâmetros por valor, as alterações feitas nos parâmetros formais, dentro da sub-rotina ou função, não se refletem nos parâmetros atuais. O valor do parâmetro atual é copiado no parâmetro formal, na chamada da sub-rotina ou função. Assim, quando a passagem é por valor significa que o parâmetro é de entrada.Na passagem de parâmetros por resultado, as alterações feitas nos parâmetros formais, na sub-rotina ou função, refletem-se nos parâmetros atuais. O valor do parâmetro formal é copiado no parâmetro atual, ao retornar da sub-rotina ou função. Assim, quando a passagem é por resultado significa que o parâmetro é de saída.Na passagem de parâmetros por referência, a toda alteração feita num parâmetro formal corresponde a mesma alteração feita no seu parâmetro atual associado. Neste caso, quando a passagem é por valor significa que o parâmetro é de entrada-saída.Para definir o corpo precisamos identificar o conjunto de variáveis e instruções pararealizar sua tarefa.

4.4 Passagem por ValorOs valores dos parâmetros passados por valor são passados por um mecanismo denominado cópia. O valor do parâmetro (uma constante ou o valor de uma variável ou expressão) é atribuído ao parâmetro quando da chamada do procedimento/função.Até o momento utilizamos somente passagem por valor. Por exemplo, na chamada da função quadrado, x é um parâmetro passado por valor, e, assim sendo, o valor de x copiado para o parâmetro da função. Na chamada da função Quadrado(x), o valor da variável x é atribuído ao parâmetro num da função Quadrado, o parâmetro num assume o papel de uma variável do procedimento/função e o quadrado é calculado para esse valor. Na chamada da função Quadrado(y) , o parâmetro num recebe o valor da variável y, portanto o módulo retornará o quadrado da variável y.

4.5 Passagem por ReferênciaA passagem por referência ocorre quando alterações nos parâmetros, dentro da função, alteram os valores das variáveis que foram passadas para a função. Este nome vem do fato de que, neste tipo de chamada, não se passa para a função o valor das variáveis, mas sim suas referências (a função usa as referências para alterar os valores das variáveis, que foram passadas como parâmetro, fora da função).A referência de uma variável é seu endereço de memória, quando realizamos uma passagem de parâmetro por referência, o parâmetro não recebe a cópia do valor da variável, e sim, o endereço de memória onde está armazenada essa variável. Assim, qualquer alteração no valor do parâmetro feita pelo procedimento/função acarretará uma modificação no valor da variável passada como parâmetro.Para indicar que um parâmetro é passado por referência, na especificação dos parâmetros de um módulo utilizaremos a palavra-chave REF antes do tipo de dado do parâmetro.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

21

Page 22: Revisão Algoritmos

Por exemplo, para criarmos um procedimento para realizar a troca de valores entre duas variáveis devemos passar as suas respectivas referências para que o módulo possa alterá-las.Quando a chamada Troca(num1, num2) é executada, a variável a e b (que estão precedidas da palavra-chave REF) receberam o endereço de memória das variáveis num1 e num2 respectivamente. Quando as variáveis a e b forem alteradas no procedimento, esta atualização afetará o valor de num1 e num2. Se essas variáveis fossem passadas por valor esta atualização não seria possível.

Devemos observar que os parâmetros passados por referência devem ser obrigatoriamente variáveis, uma vez que não faz sentido modificar o valor de uma constante ou de uma expressão.

4.6 Passagem por valor x por referênciaSempre que desejarmos passar parâmetros para uma função, devemos distinguir e saber quando utilizar passagem de parâmetros por valor ou por referência. Quando a função/procedimento precisa apenas de um valor inicial para o parâmetro utilizaremos passagem por valor. Quando desejarmos que as atualizações realizadas pelo módulo alterem as variáveis externas a ele, devemos utilizar passagem por referência. Para exemplificar vamos criar módulos com passagem por valor e por referência.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

22

Page 23: Revisão Algoritmos

4.7 Criando FunçõesPara criar uma função utilizaremos a seguinte forma geral:

Em que: nome é um identificador único que representa o nome da função; os parâmetros são uma lista formada pela declaração dessas variáveis especiais definida pelo tipo de dado e

o nome do parâmetro da função. Essa lista de parâmetros também pode ser vazia. tipo de retorno é o tipo de dado do valor de retorno da função (REAL,INTEIRO, CARACTER ou

BOOLEANO). Exemplo de um lista de parâmetros: (inteiro num1, num2 ; caracter opção) Conjunto de instruções é a seqüência de instruções que compõe o módulo e que sempre finaliza com um

comando especial denominado a instrução de retorno que é da seguinte forma: RETORNA <valor de retorno>

valor de retorno é o valor de saída produzido pela função que deve ser do mesmo tipo de dado definido no tipo de retorno.

Logo após a descrição da interface podemos descrever o corpo do algoritmo da função correspondente. Para delimitar as instruções que fazem parte da função, utilizamos Fim-Função.Exemplo: Vejamos um exemplo de uma função. Suponha que desejemos construir uma função para calcular o quadrado de um número. O número deve ser passado para a função, que calculará o seu quadrado e o devolverá para o algoritmo que a solicitou. Vamos denominar esta função de Quadrado, como é mostrado a seguir:

4.8 Criando ProcedimentosA diferença entre funções e procedimentos é que o procedimento não retorna valor. Para criar um procedimento utilizaremos a seguinte forma geral:

Em que:

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

23

Page 24: Revisão Algoritmos

nome é um identificador único que representa o nome do procedimento; os parâmetros são uma lista formada pela declaração dessas variáveis especiais definida pelo tipo de dado

e o nome do parâmetro da função. Essa lista de parâmetros pode possuir vários parâmetros ou ser vazia. Conjunto de instruções é a seqüência de instruções que compõe o módulo.Como um procedimento não retorna valor, não é necessário utilizar a instruçãode retorno.Para delimitar os comandos que fazem parte do procedimento, utilizamos FIM-PROCEDIMENTO.

Exemplo: Suponha que desejemos construir um procedimento para apresentar informações do algoritmo.

4.9 Solicitando a execução de um móduloQuando queremos utilizar os módulos que criamos para resolver uma tarefa, ou seja solicitar sua execução, devemos fazer chamada ao módulo. A chamada ao módulo é a forma de solicitar a execução do módulo em um determinado passo do algoritmo.Funções e procedimentos não são diferentes apenas na forma como são implementados, mas também na forma como a solicitação da execução deles, ou simplesmente chamada, deve ser realizada.A chamada de uma função é usada como um valor constante que deve ser atribuído a uma variável ou como parte de uma expressão, enquanto a chamada de um procedimento é realizada com uma instrução.Para fazer a chamada de um módulo devemos especificar qual o nome módulo e passar valores iniciais para seus parâmetros. Esses valores iniciais devem ser do mesmo tipo de dado e especificados na mesma ordem em que foram definidos na interface do módulo.

Exemplo de chamadas do módulo Quadrado:

Exemplos de chamadas do módulo Apresentacao:

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

24

Page 25: Revisão Algoritmos

4.10 Exemplo de um Algoritmo ModularizadoUm algoritmo para realizar a soma dos quadrados de dois números inteiros utilizando a função Quadrado e o procedimento Apresentacao seria da seguinte forma:

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

25

Page 26: Revisão Algoritmos

5 RecursividadeUm objeto é dito recursivo se ele consistir parcialmente ou for definido em termos de si próprio.

Uma função é recursiva quando no corpo dessa função existe uma chamada a si própria, podendo utilizar os mesmos parâmetros de entrada (correndo riscos de provocar um ciclo infinito) ou outros.

5.1 Exemplo de Problema RecursivoImagine que temos um monte de pregos e queremos saber quantos são. Se pegarmos num prego, sabemos que temos um prego, mas não sabemos quantos ainda existem no monte restante... efetuamos a mesma operação (recursividade) e somamos o prego ao que já temos.Fazemos o mesmo até não existir mais pregos para contar, isto é, pegamos num e somamos aos que temos, repetimos a mesma operação perguntando sempre entre as operações, "ainda há mais pregos para contar?", caso haja, repetimos, caso contrário paramos.A recursividade é uma ferramenta muita poderosa quando bem implementada, senão pode ser muita perigosa. É preciso ter cuidado com as condições de parada, se faltar alguma condição de parada ou alguma condição de parada está errada pode acontecer um ciclo infinito.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

26

Page 27: Revisão Algoritmos

5.2 Recursão X IteraçãoParadigma iterativo: uma seqüência de instruções é executada de uma forma repetitiva, controlada por uma dada condição (ciclo iterativo).Paradigma recursivo: existência de casos simples, em que a resposta é determinada diretamente; ser possível uma decomposição recursiva de uma instância do problema, em instâncias mais simples da

mesma forma.Numa função recursiva, são criadas várias ativações dela própria que desaparecem à medida que a execução avança. Em cada momento apenas uma das ativações está ativa, estando as restantes à espera que essa termine para continuarem.Os dois paradigmas são equivalentes: dada uma função recursiva existe sempre uma iterativa e vice-versa.

Exemplos Mais Famosos de Problemas Recursivos

São dados três suportes (a, b e c) e n discos de tamanhos diferentes. Os discos estão empilhados num dos suportes por ordem crescente de tamanhos. Pretende-se mover os discos para outro suporte de modo que: em cada passo exatamente um disco seja movido de um suporte para o outro um disco não pode nunca estar por cima de um menor o terceiro suporte pode ser usado como auxiliar

6 ApontadoresÉ na memória RAM que são carregados os nossos programas e também onde são armazenadas as variáveis que fazem parte dos programas. A memória RAM pode ser vista como um enorme vetor de Bytes consecutivos, cada um ocupando uma posição bem determinada, que é identificada por um número único que varia entre 0 e a totalidade de Bytes.Para os programadores, é muito mais simples referenciar uma variável pelo seu nome do que referenciá-la pela posição que essa variável ocupa em memória. O compilador associa a cada nome de variável uma posição única em memória, capaz de suportar os dados do tipo dessa variável.Sempre que num programa se faz referência a uma variável, na realidade é o endereço ou conjunto de endereços que essa variável ocupa, que está sendo referenciado.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

27

Page 28: Revisão Algoritmos

O apontador é um mecanismo particularmente flexível de manipulação de dados, pois permite manipular diretamente dados contidos em endereços específicos de memória. Supondo que exista um apontador

denominado ptr, que como qualquer variável ocupa uma posição em memória. Como ptr é um apontador, deverá conter o endereço de memória de outra variável (notar que o endereço de uma variável não é mais do que o número da casa que ocupa em memória). A Figura abaixo mostra este exemplo.

7 Estrutura de Dados Heterogênea7.1 IntroduçãoUm registro é uma estrutura de dados que agrupa dados de tipos distintos ou, mais raramente, do mesmo tipo. Um registro de dados é composto por um certo número de campos de dados, que são itens de dados individuais.Por exemplo, suponha que desejemos criar um algoritmo que armazene informações referentes a 5 alunos, o seu nome e suas 2 notas bimestrais, com as estruturas de dados que temos até agora seriam necessárias duas estruturas distintas:Variáveiscaracter nome = matriz [ 5 ] [ 40 ]real notas = matriz [ 5 ] [ 2 ]

A primeira estrutura, nome, armazena os nomes dos 5 alunos e a estrutura notas as suas respectivas notas bimestrais. Nesse caso, seria mais fácil agruparmos os dois tipos de dados em uma mesma estrutura. É exatamente isto que se consegue fazer como a utilização de registros.

7.2 RegistrosOs tipos registros devem ser declarados ou atribuídos antes das variáveis, pois pode ocorrer a necessidade de declarar uma variável com o tipo registro anteriormente declarado. A declaração de um registro é realizada conforme a seguir:

Defina TipoREGISTRO< tipo do campo1 > < campo1 >,< tipo do campo2 > < campo2 >,. . .< tipo do campon > < campon >FIM-REGISTRO nome do tipo

Em que: < nome do tipo> é o nome do registro cuja estrutura está sendo criada, < campon> é o nome do n-ésimo campo do registro e <tipo do campon> é o tipo do n-ésimo campo do registro.

A lista de campos é uma relação de variáveis, com o seu respectivo tipo, podendo ser REAL, INTEIRO, LÓGICO, CARACTER ou outro tipo estruturado definido previamente. Como exemplo, vamos criar um registro para representar o nome de um aluno e suas notas bimestrais e sua média:Defina TipoREGISTROcaracter nome= vetor [40],real nota1,real nota2,real mediaFIM-REGISTRO NOTAS_ALUNOSVariáveisNOTAS_ALUNOS aluno

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

28

Page 29: Revisão Algoritmos

Nesse exemplo foi criado um tipo registro NOTAS_ALUNOS, o qual é um conjunto de dados heterogêneos (um campo tipo VETOR de caracter e cinco campos do tipo REAL). Desta forma é possível guardar em uma mesma estrutura vários tipos diferentes de dados. Uma vez que um tipo de dado registro tenha sido definido, podemos criar tantas variáveis daquele tipo desejarmos, assim como fazemos com qualquer outro tipo de dado. Por exemplo, para criarmos três registros do tipo NOTAS_ALUNOS:

VariáveisNOTAS_ALUNOS aluno1, aluno2, aluno3

Cada uma dessas três variáveis é um registro do tipo NOTAS_ALUNOS ,e, portanto, cada uma delas possui seis campos de dado: nome, nota1, nota2 e media. Assim como variáveis do tipo de vetores e matrizes, variáveis do tipo registros são manipuladas através de suas partes constituintes, os campos.

7.3 Trabalhando com RegistroExemplo: Considere o seguinte problema: Calcular a média aritmética das 2 notas bimestrais utilizando um tipo registro.

Em particular, uma variável registro é manipulada através de seus campos. Então, se desejarmos atribuir um valor a uma variável registro, temos de efetuar a atribuição de valores para seus campos constituintes.Por exemplo, a leitura de um registro é efetuada com a instrução LEIA seguido do nome da variável registro e seu campo correspondente separado por um caractere “.” ponto. Uma leitura de registros também poderá ser feita como:LEIA aluno

Nesse caso, está sendo feita uma leitura em todos os campos do registro. A atribuição de um campo em um registro é realizada de forma análoga a atribuição a uma variável. O processo de impressão é feito com instrução IMPRIMA, semelhante a leitura, podendo também imprimir todo o registro:IMPRIMA aluno

Note que a estrutura registro apresentada permite somente a leitura e escrita de um único conjunto de campos para um registro. Mais adiante será apresentado como fazer para conseguir ler e escrever mais de um registro.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

29

Page 30: Revisão Algoritmos

7.4 Vetores de RegistroRegistros nos fornecem uma forma de agrupar dados de natureza distinta. Entretanto, criarmos uma única variável de um registro não parece ser muito diferente de criarmos uma variável para cada campo do registro e tratá-las individualmente. Isto é, criar uma única variável de um registro não nos ajudaria a resolver nossos problemas mais facilmente do que com o que aprendemos antes.A grande força dos registros reside no uso deles combinado com vetores. Por exemplo, um grupo de 100 alunos iria requerer um conjunto de 100 variáveis registros, o que pode ser conseguido através da criação de um vetor de 100 elementos do tipo registro em questão. Um vetor de registros é criado da mesma forma que criamos vetores de qualquer um dos tipos que aprendemos até então. Suponha, por exemplo, que desejemos criar um vetor de 100 elementos do tipo NOTAS_ALUNOS. Isto é feito da seguinte forma:

Para manipular um registro individual do vetor alunos, utilizamos o nome da variável vetor e o índice do elemento correspondente ao registro que queremos acessar, como fazemos com um vetor de qualquer outro tipo. Daí, em diante, faremos como aprendemos anteriormente. Por exemplo, se quisermos atribuir o conjunto de valores “Sicrano de Tal”, 10.0, 7.0 ao primeiro registro de alunos, faremos da seguinte forma:

Para demonstrar a utilização de problemas com tabelas de dados heterogêneos, considere o seguinte problema:Exemplo: Efetuar a leitura de 2 notas bimestrais de n alunos, calcule a média de cada aluno e no final apresentar os dados, nome e média, classificados por nome. Considere n ≤20.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

30

Page 31: Revisão Algoritmos

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

31

Page 32: Revisão Algoritmos

No algoritmo, na seção de definição de tipos são declarados três tipos, o tipo cadeia e o tipo bimestre, e após isso o tipo registro NOTAS_ALUNOS, com os campos nome, notas e média.Sendo que nome é do tipo cadeia, e notas é do tipo bimestre, que é um vetor de número reais de 2 posições. O algoritmo utiliza o método de ordenação bolha, que, é efetuada com base no nome de cada aluno.

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

32

Page 33: Revisão Algoritmos

Prof. Christiano Colen VenancioUNIPAC Ipatinga - 2007

33