ELEMENTOS DE ALGORITMIA Introdução à Ciência dos Computadores
2006
Jorge Mota, Engº
Versão 6.5
Apontamentos para Apoio às aulas
Instituto Superior de Tecnologias Avançadas do Porto
Outubro/Novembro/Dezembro/Janeiro/Fevereiro de 2006/7
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
2
Resumo
Saber e dominar a arte de criação e documentação algoritmica, no
contexto das competências de um engenheiro informático e/ou multimédia
é uma hoje em dia uma competência fundamental e essencial para todas as
outras valências da actividade de engenheiro.
Nesse contexto e como suporte às aulas da disciplina de Introdução à
Ciência dos Computadores, elaborei, compilei e anotei estes elementos que
não pretendem ser substituto da bibliografia recomendada, mas meros
elementos de apoio de leitura rápida.
Jorge Mota, 2006
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
3
Abstract
To know and to master the art of algorithms and software Principes
creation and documentation, in the context of the abilities of an
IT/Multimedia engineer are nowadays a basic and essential competencie. In
this context and as a support to the lessons of disciplines of Introduction to
Computer Science of the ISTEC, I elaborated, compiled and I write down
these printed elements. This document doesn’t pretend to be a replacement
to the recomended bibliography, but only a rapid read complement.
Jorge Mota, 2006
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
4
Conteúdo
Resumo................................................................................................ 2
Abstract ............................................................................................... 3
1 Noção de Algoritmo ....................................................................... 6
2 Fluxogramas.................................................................................. 7
3 Conceito de PseudoCódigo ou PseudoLinguagem .........................11
3.1 Forma geral de um algoritmo em pseudocódigo ............................................ 11 3.2 Entrada de dados............................................................................................. 15 3.3 Saída de dados ................................................................................................ 16 3.4 Estruturas de controlo de fluxo....................................................................... 17 3.5 Estruturas de sequência .................................................................................. 17 3.6 Estruturas de Decisão ..................................................................................... 18 3.7 Estruturas de Decisão Simples ....................................................................... 18 3.8 Estruturas de Decisão Múltipla ...................................................................... 19 3.9 Estruturas de Repetição ou Loop.................................................................... 20 3.10 Ciclos contados............................................................................................... 20 3.11 Ciclos Enquanto.............................................................................................. 21 3.12 Ciclos Repetir … Até que (cond) ................................................................... 22
4 Exemplos de documentação de algoritmos usando pseudocódigo 23
4.1 Primeiro exemplo ........................................................................................... 23 4.2 Outro exemplo de Algoritmo em pseudocódigo ............................................ 24 4.3 Exemplos de implementações em linguagens de programação...................... 24 4.4 O conceito de subprograma ............................................................................ 26 4.5 O Conceito de variavel Local e Global .......................................................... 27 4.6 Procedimentos ................................................................................................ 27 4.7 Funções........................................................................................................... 29 4.8 Passagem de parãmetros por referência.......................................................... 31 4.9 Recursividade ................................................................................................. 32 4.10 Tipos de dados Variaáveis e Expressões ........................................................ 32 4.11 Operadores Aritméticos.................................................................................. 33 4.12 Operadores relacionais ................................................................................... 34 4.13 Operadores Boleanos...................................................................................... 35 4.14 Ficheiros de Texto .......................................................................................... 35
5 Introdução a implementação de algoritmos usando linguagem C .37
5.1 Forma Geral de um programa em C ............................................................... 37 5.2 Declaração e inicialização de variaveis e constantes...................................... 37 5.3 Expressões em C............................................................................................. 37 5.4 Implementação de estruturas de controlo de fluxo......................................... 37 5.5 Leitura(input) e Escrita(output) de dados....................................................... 37 5.6 Funções, argumentos e passagem de parâmetros ........................................... 37 5.7 Exemplos de programas em C........................................................................ 37 5.8 Arrays, Matrizes e Strings .............................................................................. 47 5.9 Ponteiros ......................................................................................................... 61
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
5
5.10 Estruturas avançadas de dados – Estruturas e uniões; Enumerações e tipos definidos pelo utilizador ............................................................................................. 62 5.11 Ficheiros de Texto em C, Rapor e VisualAlg................................................. 62
6 Ordenação e Pesquisa...................................................................64
6.1 Pesquisa .......................................................................................................... 64 Pesquisa sequencial ou linear.............................................................65
Pesquisa binária .................................................................................65
6.2 Ordenação....................................................................................................... 71 7 Bubble sort ...................................................................................71
Ordenação por Selecção .....................................................................77
Insertion sort .....................................................................................80
Shell sort ............................................................................................83
Quicksort ............................................................................................87
Complexidade do Quicksort ....................................................................................... 87 7.1 Filas, Listas e Pilhas ....................................................................................... 94
8 Execicios de algoritmia com cálculo numérico ..............................95
9 Bibliografia .................................................................................129
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
6
1 Noção de Algoritmo
Um algoritmo é uma sequência não ambígua de instruções que é
executada até que determinada condição se verifique. Mais especificamente,
em matemática, constitui o conjunto de processos (e símbolos que os
representam) para efectuar um cálculo. Os Algoritmos podem ser
implementados por programas de computadores. A área que estuda os
algoritmos designa-se Ciências da Computação.
A palavra algoritmo tem origem no sobrenome, Al-Khwarizmi, do
matemático persa do século IX, Mohamed Ben Musa, cujas obras foram
traduzidas no ocidente cristão no século XII, tendo uma delas recebido o
nome "Algorithmi de numero indorum", que versa sobre os algoritmos,
usando o sistema de numeração decimal e indiano. Outros autores,
contudo, defendem a origem da palavra em Al-goreten (raiz - conceito que
se pode aplicar aos cálculos).
O conceito de algoritmo é freqüentemente ilustrado pelo exemplo de
uma receita, embora muitos algoritmos sejam mais complexos. Eles podem
repetir passos (fazer iterações) ou necessitar de decisões (tais como
comparações ou lógica) até que a tarefa seja completada. Um algoritmo
corretamente executado não irá resolver um problema se o algoritmo
estiver incorreto ou não for apropriado ao problema.
Um algoritmo não representa, necessariamente, um programa de
computador, e sim os passos necessários para realizar uma tarefa. Sua
implementação pode ser feita por um computador, por outro tipo de
autômato ou mesmo por um ser humano.
Diferentes algoritmos podem realizar a mesma tarefa usando um conjunto
diferenciado de instruções em mais ou menos tempo, espaço ou esforço do
que outros. Por exemplo, um algoritmo para se vestir pode especificar que
você vista primeiro as meias e os sapatos antes de vestir a calça enquanto
outro algoritmo especifica que você deve primeiro vestir a calça e depois as
meias e os sapatos. Fica claro que o primeiro algoritmo é mais difícil de
executar que o segundo.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
7
Um Fluxograma é um tipo de diagrama, e pode ser entendido como
uma representação esquemática de um processo, muitas vezes feita através
de gráficos que ilustram de forma descomplicada a transição de informações
entre os elementos que o compõem. Podemos entendê-lo, na prática, como
a documentação dos passos necessários para a execução de um processo
qualquer.
Um diagrama é uma representação visual estruturada e simplificada
de um determinado conceito, idéia.
2 Fluxogramas
Um fluxograma tipico, representado de forma tradicional, contém
normalmente os seguintes simbolos:
INICIO e FIM, representados por ovais ou rectangulos arrendondados,
normalmente contém as palavras Inicio e Fim e uma frase que descreve o
processo representado, como por exemplo calcular média de 10 numeros.
SETAS, mostrando o que designamos por “fluxo de controlo” em
ciência de computadores. Uma seta que vai de um simbolo para outro
respresenta que o controlo passa de um simbolo para outro.
Passos do PROCESSAMENTO, representados por rectangulos.
Exemplos: "Adicionar 1 a X"; "Guardar as alterações"; "a<-1+b" ou similar.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
8
Entrada/Saidas, representadas por paralelogramas. Exemplo LER X de
um teclado; ESCREVER X no ecrã.
ESTRUTURAS de DECISÃO, representadas como diamantes. Estas
representam tipicamente uma questão do tipo SIM/NÃO ou True/False.
Este simbolo apresenta duas setas de fluxo a sair do simbolo, um
correspondente a hipotese SIM outra à Não. Estas setas devem sempre
estar etiquetadas, para não levantar dúvidas.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
9
Uma forma compacta de representação de CICLOS contados pode ser
apresentado por um Hexagono. Este simbolo apresenta três setas de fluxo a
sair/entrada no mesmo. Uma para baixo que representa o corpo do ciclo,
uma seta a entrar pelo lado direito que representa o retorno a condição de
ciclo e finalmente um a sair do lado direito que é o fluxo executado quando
termina o ciclo. Todas as setas de fluxo devem estar convenienetemente
etiquetadas.
Os ciclos ou Loops são representados explicitamente por uma
condição, um corpo do ciclo e uma seta de fluxo que retorna ao inicio.
Quando esta à colocada à entrada, então estamos prerante um ciclo
ENQUANTO, o corpo do ciclo só é executado enquanto a condição é
verdadeira e se na primeira passagem a condição for falsa então o corpo do
ciclo nunca é executado. Se o teste (condição) é colocado no final do corpo
do ciclo então estamos perante um ciclo do tipo REPETIR …ATÉ QUE (cond),
que se carcteriza por ser executado enquanto a condição for falsa, e o corpo
do ciclo é sempre executado pelo menos uma vez.
Enquanto
Repetir até que (cond)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
10
Muitos outros simbolos, representando significados mais ou menos
universais podem ser usados de que destacamos :
Um Documento representado por um rectangulo com umabase
ondulada;
Um ficheiro/Base de Dados representado por um Cilindro
Os fluxogramas contêm ainda outros simbolos como Conectores intra
página e inter páginas (respectivamente representados por um circulo e um
rectangulo/seta). Dentro destes deve ser indicado uma letra ou numero que
faz a correspondência entre ligações.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
11
3 Conceito de PseudoCódigo ou PseudoLinguagem
Pseudocódigo é uma forma genérica de escrever um algoritmo,
utilizando uma linguagem simples (nativa a quem o escreve, de forma a ser
entendido por qualquer pessoa) sem necessidade de conhecer a sintaxe de
nenhuma linguagem de programação. É, como o nome indica, um pseudo-
código e, portanto, não pode ser executado num sistema real (computador)
— de outra forma deixaria de ser pseudo.
Os livros sobre a ciência de computação utilizam frequentemente o
pseudocódigo para ilustrar os seus exemplos, de forma que todos os
programadores possam entendê-los (independentemente da linguagem que
utilizem).
Embora no caso da língua portuguesa existam alguns interpretadores
de pseudocódigo, nenhum tem a projecção das linguagens Pascal ou BASIC,
que no caso da língua inglesa se assemelham bastante a pseudo-código
(em inglês, claro).
3.1 Forma geral de um algoritmo em pseudocódigo
Introdução
Vamos usar como linguagem de represntação algoritmica o VisuAlg.
Esta interpretador é bem uma das muitas implementações disponiveis e
tem a vantagem de ser simples: é uma versão portuguesa dos
pseudocódigos largamente utilizados nos livros de introdução à
programação, conhecida como "Portugol". Tem comandos novos, com o
intuito de criar facilidades específicas para o ensino de técnicas de
elaboração de algoritmos.
A linguagem do VisuAlg permite apenas um comando por linha: desse
modo, não há necessidade de tokens separadores de estruturas, como o
ponto e vírgula em Pascal ou o ; em Linguagem C. Também não existe o
conceito de blocos de comandos (que correspondem ao begin e end do
Pascal e ao { e } do C), nem comandos de desvio incondicional como o
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
12
goto. Na versão actual do VisuAlg, com exceção das rotinas de entrada e
saída, não há nenhum subprograma embutido, tal como Inc(), Sqr(), Ord(),
Chr(), Pos(), Copy() ou outro.
Importante: para facilitar a digitação e evitar confusões, todas as
palavras-chave do VisuAlg foram implementadas sem acentos, cedilha, etc.
Portanto, o tipo de dados lógico é definido como logico, o comando
se..então..senão é definido como se..entao..senao, e assim por diante. O
VisuAlg também não distingue maiúsculas e minúsculas no reconhecimento
de palavras-chave e nomes de variáveis.
Formato Básico do Pseudocódigo e Inclusão de Comentários
O formato básico do nosso pseudocódigo é o seguinte:
algoritmo "semnome"
// Função :
// Autor :
// Data :
// Secção de Declarações
inicio
// Secção de Comandos
fimalgoritmo
A primeira linha é composta pela palavra-chave algoritmo seguida do
seu nome delimitado por aspas duplas. Este nome será usado como título
nas janelas de leitura de dados (nas futuras versões do VisuAlg, talvez
utilizemos este dado de outras formas). A secção que se segue é a de
declaração de variáveis, que termina com a linha que contém a palavra-
chave inicio. Deste ponto em diante está a secção de comandos, que
continua até a linha em que se encontre a palavra-chave fimalgoritmo. Esta
última linha marca o final do pseudocódigo: todo texto existente a partir
dela é ignorado pelo interpretador.
O VisuAlg permite a inclusão de comentários: qualquer texto
precedido de "//" é ignorado, até se atingir o final da sua linha. Por este
motivo, os comentários não se estendem por mais de uma linha: quando se
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
13
deseja escrever comentários mais longos, que ocupem várias linhas, cada
uma delas deverá começar por "//".
Tipos de Dados
Em algoritmia prevêmos quatro tipos de dados e am VisualAlg
também: inteiro, real, cadeia de caracteres e lógico (ou booleano). As
palavras-chave que os definem são as seguintes (observe que elas não têm
acentuação):
inteiro: define variáveis numéricas do tipo inteiro, ou seja, sem casas
decimais.
real: define variáveis numéricas do tipo real, ou seja, com casas
decimais.
caractere: define variáveis do tipo string, ou seja, cadeia de
caracteres.
logico: define variáveis do tipo booleano, ou seja, com valor
VERDADEIRO ou FALSO.
O VisuAlg permite também a declaração de variáveis estruturadas
através da palavra-chave vetor, como será explicado a seguir.
Nomes de Variáveis e sua Declaração
Os nomes das variáveis devem começar por uma letra e depois conter
letras, números ou underline, até um limite de 30 caracteres. As variáveis
podem ser simples ou estruturadas (na versão actual, os vetores podem ser
de uma ou duas dimensões). Não pode haver duas variáveis com o mesmo
nome, com a natural exceção dos elementos de um mesmo vetor.
A secção de declaração de variáveis começa com a palavra-chave var,
e continua com as seguintes sintaxes:
<lista-de-variáveis> : <tipo-de-dado>
<lista-de-variáveis> : vetor "["<lista-de-intervalos>"]" de <tipo-de-dado>
Na <lista-de-variáveis>, os nomes das variáveis estão separados por
vírgulas. Na <lista-de-intervalos>, os <intervalo> são separados por
vírgulas, e têm a seguinte sintaxe:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
14
<intervalo>: <valor-inicial> .. <valor-final>
Na versão actual do VisuAlg, tanto <valor-inicial> como <valor-final>
devem ser inteiros. Além disso, exige-se evidentemente que <valor-final>
seja maior do que <valor-inicial>.
Exemplos:
var
a: inteiro
Valor1, Valor2: real
vet: vetor [1..10] de real
matriz: vetor [0..4,8..10] de inteiro
nome_do_aluno: caractere
sinalizador: logico
Note que não há a necessidade de ponto e vírgula após cada
declaração: basta pular linha. A declaração de vetores é análoga à
linguagem Pascal: a variável vet acima tem 10 elementos, com os índices
de [1] a [10], enquanto matriz corresponde a 15 elementos com índices
[0,8], [0,9], [0,10], [1,8], [1,9], [1,10], ... até [4,10]. O número total de
variáveis suportado pelo VisuAlg é 500 (cada elemento de um vetor é
contado individualmente).
Constantes e operação de Atribuição
Consideramos três tipos de constantes:
Numéricos: são valores numéricos escritos na forma usual das
linguagens de programação. Podem ser inteiros ou reais. Neste último caso,
o separador de decimais é o ponto e não a vírgula, independente da
configuração regional do computador onde o VisuAlg está sendo executado.
O VisuAlg também não suporta separadores de milhares.
Caracteres: qualquer cadeia de caracteres delimitada por aspas
duplas (").
Lógicos: admite os valores VERDADEIRO ou FALSO.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
15
A atribuição de valores a variáveis é feita com o operador <-. Do seu
lado esquerdo fica a variável à qual está sendo atribuído o valor, e à sua
direita pode-se colocar qualquer expressão (constantes, variáveis,
expressões numéricas), desde que seu resultado tenha tipo igual ao da
variável.
Alguns exemplos de atribuições, usando as variáveis declaradas
acima:
a <- 3
Valor1 <- 1.5
Valor2 <- Valor1 + a
vet[1] <- vet[1] + (a * 3)
matriz[3,9] <- a/4 - 5
nome_do_aluno <- "José da Silva"
sinalizador <- FALSO
Na forma geral de um algoritmo encontramos três grandes conjuntos
de comandos(entrada de dados, saída de dados e estruturas de controlo de
fluxo):
3.2 Entrada de dados
leia (<lista-de-variáveis>)
Recebe valores digitados pelos utilizador, atribuindo-os às variáveis
cujos nomes estão em <lista-de-variáveis> (é respeitada a ordem
especificada nesta lista). É análogo ao comando read do Pascal e
semelhante ao Scanf() da linguagem C.
Veja no exemplo abaixo o resultado:
algoritmo "exemplo 1"
var x: inteiro;
inicio
leia (x)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
16
escreva (x)
fimalgoritmo
3.3 Saída de dados
escreva (<lista-de-expressões>)
Escreve no dispositivo de saída standard. Em VisualAlg esta é, na
área à direita da metade inferior da tela, o conteúdo de cada uma das
expressões que compõem <lista-de-expressões>. As expressões dentro
desta lista devem estar separadas por vírgulas; depois de serem avaliadas,
seus resultados são impressos na ordem indicada. É equivalente ao
comando write do Pascal ou printf() da linguagem C.
De modo semelhante ao C com a “string” de controlo, é possível
especificar o número de espaços no qual se deseja escrever um
determinado valor. Por exemplo, o comando escreva(x:5) escreve o valor
da variável x em 5 espaços, alinhado-o à direita. Para variáveis reais, pode-
se também especificar o número de casas fracionárias que serão exibidas.
Por exemplo, considerando y como uma variável real, o comando
escreva(y:6:2)escreve seu valor em 6 espaços colocando 2 casas decimais.
escreval (<lista-de-expressões>).
Idêntico ao anterior, com a única diferença que salta uma linha. É
equivalente ao writeln do Pascal ou scanf() com string de controlo que
comtemple \n (line feed).
Exemplos:
algoritmo "exemplo"
var x: real
y: inteiro
a: caractere
l: logico
inicio
x <- 2.5
y <- 6
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
17
a <- "teste"
l <- VERDADEIRO
escreval ("x", x:4:1, y+3:4) // Escreve: x 2.5 9
escreval (a, "ok") // Escreve: testeok (e depois pula linha)
escreval (a, " ok") // Escreve: teste ok (e depois pula linha)
escreval (a + " ok") // Escreve: teste ok (e depois pula linha)
escreva (l) // Escreve: VERDADEIRO
fimalgoritmo
Note que o VisuAlg separa expressões do tipo numérico e lógico com
um espaço à esquerda, mas não as expressões do tipo caractere, para que
assim possa haver a concatenação. Quando se deseja separar expressões
do tipo caractere, é necessário acrescentar espaços nos locais adequados.
"Entre com o valor de <nome-de-variável>"
3.4 Estruturas de controlo de fluxo
Como se repreentam as principais estruturas de controlo de fluxo,
entrada e saida de dados, comentários e declaração de variaveis em
pesudocódigo (vamos usar a notação do Visualalg).
3.5 Estruturas de sequência
Em Pseudocódigo vamos adoptar uma notação próxima do Pascal em
que a marcação do inicio e fim dos blocos são expressos pelo inicio e fim da
estrutura de controlo, declaração ou subprograma.
Exemplo:
inicio
A<-1+b
Escrevel(a)
Fimalgoritmo
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
18
3.6 Estruturas de Decisão
As estruturas de decisão são muito importantes em algoritmia e
programação. Na realidade podemos dizer que é com estas que
conseguimos implementar regras que tornam os nossos programas
“inteligentes”. Conseideramos dois tipos de estruturas de decisão
(condicionais) as de decisão simples e Múltipla.
3.7 Estruturas de Decisão Simples
se <expressão-lógica> entao
<seqüência-de-comandos>
fimse
Ao encontrar este comando, o VisuAlg analisa a <expressão-lógica>.
Se o seu resultado for VERDADEIRO, todos os comandos da <seqüência-de-
comandos> (entre esta linha e a linha com fimse) são executados. Se o
resultado for FALSO, estes comandos são desprezados e a execução do
algoritmo continua a partir da primeira linha depois do fimse.
se <expressão-lógica> entao
<seqüência-de-comandos-1>
senao
<seqüência-de-comandos-2>
fimse
Nesta outra forma do comando, se o resultado da avaliação de
<expressão-lógica> for VERDADEIRO, todos os comandos da <seqüência-
de-comandos-1> (entre esta linha e a linha com senao) são executados, e a
execução continua depois a partir da primeira linha depois do fimse. Se o
resultado for FALSO, estes comandos são desprezados e o algoritmo
continua a ser executado a partir da primeira linha depois do senao,
executando todos os comandos da <seqüência-de-comandos-2> (até a
linha com fimse).
Estes comandos equivalem ao if...then e if...then...else do Pascal.
Note que não há necessidade de delimitadores de bloco (como begin e end),
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
19
pois as seqüências de comandos já estão delimitadas pelas palavras-chave
senao e fimse. O VisuAlg permite o aninhamento desses comandos de
desvio condicional.
3.8 Estruturas de Decisão Múltipla
O VisuAlg implementa (com certas variações) o comando case do
Pascal ( ou switch da linguagem C). A sintaxe é a seguinte:
escolha <expressão-de-seleção>
caso <exp11>, <exp12>, ..., <exp1n>
<seqüência-de-comandos-1>
caso <exp21>, <exp22>, ..., <exp2n>
<seqüência-de-comandos-2>
...
outrocaso
<seqüência-de-comandos-extra>
fimescolha
Veja o exemplo a seguir, que ilustra bem o que faz este comando:
algoritmo "Times"
var time: caractere
inicio
escreva ("Entre com o nome de um time de futebol: ")
leia (time)
escolha time
caso "Flamengo", "Fluminense", "Vasco", "Botafogo"
escreval ("É um time carioca.")
caso "São Paulo", "Palmeiras", "Santos", "Corínthians"
escreval ("É um time paulista.")
outrocaso
escreval ("É de outro estado.")
fimescolha
fimalgoritmo
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
20
3.9 Estruturas de Repetição ou Loop
Em ciência dos Computadores e Algoritmia usamos três estruturas de
repetição comuns nos algoritmos: o ciclo contado para...ate...faca (similar
ao for...to...do do Pascal ou for(;;) do C), e os ciclos condicionados
enquanto...faca (similar ao while...do ou While {} do C) e repita...ate
(similar ao repeat...until ou repit …until cond do C). A sintaxe destas
estruturas de controlo de fluxo é explicada a seguir:
3.10 Ciclos contados
Para ... faça
Esta estrutura repete uma seqüência de comandos um determinado número de vezes.
para <variável> de <valor-inicial> ate <valor-limite> [passo <incremento>] faca <seqüência-de-comandos> fimpara
<variável >
É a variável contadora que controla o número de repetições do ciclo. Na versão actual, deve ser necessariamente uma variável do tipo inteiro, como todas as expressões deste comando.
<valor-inicial> É uma expressão que especifica o valor de inicialização da variável contadora antes da primeira repetição do ciclo.
<valor-limite > É uma expressão que especifica o valor máximo que a variável contadora pode alcançar.
<incremento >
É opcional. Quando presente, precedida pela palavra passo, é uma expressão que especifica o incremento que será acrescentado à variável contadora em cada repetição do ciclo. Quando esta opção não é utilizada, o valor padrão de <incremento> é 1. Vale a pena ter em conta que também é possível especificar valores negativos para <incremento>. Por outro lado, se a avaliação da expressão <incremento > resultar em valor nulo, a execução do algoritmo será interrompida, com a impressão de uma mensagem de erro.
fimpara
Indica o fim da seqüência de comandos a serem repetidos. Cada vez que o programa chega neste ponto, é acrescentado à variável contadora o valor de <incremento >, e comparado a <valor-limite >. Se for menor ou igual
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
21
(ou maior ou igual, quando <incremento > for negativo), a seqüência de comandos será executada mais uma vez; caso contrário, a execução prosseguirá a partir do primeiro comando que esteja após o fimpara.
<valor-inicial >, <valor-limite > e <incremento > são avaliados uma única vez antes da execução da primeira repetição, e não se alteram durante a execução do ciclo, mesmo que variáveis eventualmente presentes nessas expressões tenham seus valores alterados.
No exemplo a seguir, os números de 1 a 10 são exibidos em ordem crescente.
algoritmo "Números de 1 a 10" var j: inteiro inicio para j de 1 ate 10 faca escreva (j:3) fimpara fimalgoritmo
Importante: Se, logo no início da primeira repetição, <valor-inicial > for maior que <valor-limite > (ou menor, quando <incremento> for negativo), o ciclo não será executado nenhuma vez. O exemplo a seguir não imprime nada.
algoritmo "Numeros de 10 a 1 (não funciona)" var j: inteiro inicio para j de 10 ate 1 faca escreva (j:3) fimpara fimalgoritmo
Este outro exempo, no entanto, funcionará por causa do passo -1:
algoritmo "Numeros de 10 a 1 (este funciona)" var j: inteiro inicio para j de 10 ate 1 passo -1 faca escreva (j:3) fimpara fimalgoritmo
3.11 Ciclos Enquanto
Enquanto ... faça
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
22
Esta estrutura repete uma seqüência de comandos enquanto uma determinada condição (especificada através de uma expressão lógica) for satisfeita.
enquanto <expressão-lógica> faca <seqüência-de-comandos> fimenquanto
<expressão-lógica> Esta expressão que é avaliada antes de cada repetição do ciclo. Quando seu resultado for VERDADEIRO, <seqüência-de-comandos> é executada.
fimenquanto
Indica o fim da <seqüência-de-comandos> que será repetida. Cada vez que a execução atinge este ponto, volta-se ao início do ciclo para que <expressão-lógica> seja avaliada novamente. Se o resultado desta avaliação for VERDADEIRO, a <seqüência-de-comandos> será executada mais uma vez; caso contrário, a execução prosseguirá a partir do primeiro comando após fimenquanto.
O mesmo exemplo anterior pode ser resolvido com esta estrutura de repetição:
algoritmo "Números de 1 a 10 (com enquanto...faca)" var j: inteiro inicio j <- 1 enquanto j <= 10 faca escreva (j:3) j <- j + 1 fimenquanto fimalgoritmo
Importante: Como o ciclo enquanto...faca testa sua condição de parada antes de executar sua seqüência de comandos, esta seqüência poderá ser executada zero ou mais vezes.
3.12 Ciclos Repetir … Até que (cond)
Esta estrutrura repete uma seqüência de comandos até que uma determinada condição (especificada através de uma expressão lógica) seja satisfeita.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
23
repita <seqüência-de-comandos> ate <expressão-lógica>
repita Indica o início do ciclo.
ate <expressão-lógica>
Indica o fim da <seqüência-de-comandos> a serem repetidos. Cada vez que o programa chega neste ponto, <expressão-lógica> é avaliada: se seu resultado for FALSO, os comandos presentes entre esta linha e a linha repita são executados; caso contrário, a execução prosseguirá a partir do primeiro comando após esta linha.
Considerando ainda o mesmo exemplo:
algoritmo "Números de 1 a 10 (com repita)" var j: inteiro inicio j <- 1 repita escreva (j:3) j <- j + 1 ate j > 10 fimalgoritmo
4 Exemplos de documentação de algoritmos usando pseudocódigo
4.1 Primeiro exemplo
Abaixo fica o exemplo de um programa que faz a leitura de 10 números e calcula uma média de apenas numeros positivos.
S <- 0; C <- 0; PARA i<- 1 ATÉ 10 FAZ
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
24
LER (a); SE a >=0 ENTÃO S <- S+a C <- C+1 FIM SE; FIM PARA; MD <- S/C ESCREVER ("A média é:", MD)
4.2 Outro exemplo de Algoritmo em pseudocódigo
Exemplo de um algoritmo que irá retornar a soma de dois valores (também conhecidos como parâmetros ou argumentos) que são introduzidos na chamada da função:
função SomaDeDoisValores (A numérico, B numérico) inicio declare SOMA numérico SOMA <-- A + B retorne (SOMA) fim 4.3 Exemplos de implementações em linguagens de programação
4.3.1 Action Script function somaDeDoisValores (a, b) { trace(a + b) };
4.3.2 C/C++/Java/C#/D public int SomaDeDoisValores (int a, int b) { return a + b; }
4.3.3 Cobol compute c = a + b.
4.3.4 Delphi function SomaDeDoisValores( A, B: Integer ): Integer; begin Result := A + B; end;
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
25
4.3.5 Haskell soma :: Integer -> Integer -> Integer -- (assinatura) soma a b = a + b
A assinatura da função pode ser dispensada, mas normalmente é colocada no código por motivo de clareza.
4.3.6 JavaScript function SomaDeDoisValores(val1, val2) { return (parseInt(val1) + parseInt(val2)); }
Seguindo padrões de programação, usa-se a primeira letra maiúscula apenas em classes; em funções usa-se a primeira letra minúscula.
4.3.7 Logo defina SomaDeDoisValores [[a b]] [escreva soma :a :b]]
4.3.8 Pascal function SomaDeDoisValoresInteiros( A, B: Integer ): Integer; begin Result := A + B; end;
4.3.9 Perl sub SomaDeDoisValores { my ($int1,$int2) = @_; return $int1 + $int2; }
4.3.10 PHP function SomaDeDoisValores($VlrA, $VlrB) { return ($VlrA + $VlrB); }
4.3.11 Prolog somaDeDoisValores(A,B,Result):- Result is A+B.
4.3.12 Python def SomaDeDoisValores (a, b): return a + b
4.3.13 Ruby def soma_de_dois_valores(a, b) a + b
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
26
end
4.3.14 Scheme (define Soma (lambda (x y) (x + y)) )
4.3.15 VBScript function SomaDeDoisValores (a,b) SomaDeDoisValores=a+b end function
4.3.16 Visual Basic function SomaDeDoisValores(byval a as integer, byval b as integer) as integer SomaDeDoisValores = a + b end function
4.4 O conceito de subprograma
Subprograma é um programa. Deve corresponder a unidade atomica
de implementação algoritmica, resultado da simplificação de problemas pelo
método TOP-DOWN, ou seja à decomposição em problemas
sucessivamente mais simples, até que seja implementavel fácilmente e
suficientemente genérico para permitir a sua reutilização. Também costuma
receber os nomes de sub-rotina, procedimento, método, Função ou módulo.
Os subprogramas são chamados dentro do corpo do programa principal
como se fossem comandos/expressão. Após seu término, a execução
continua a partir do ponto onde foi chamado. É importante compreender
que a chamada de um subprograma simplesmente gera um desvio
provisório no fluxo de execução.
Há um caso particular de subprograma que recebe o nome de função.
Uma função, além de executar uma determinada tarefa, retorna um valor
para quem a chamou, que é o resultado da sua execução. Por este motivo,
a chamada de uma função aparece no corpo do programa principal como
uma expressão, e não como um comando.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
27
Em Fluxogramas representamos a chamada a um subprograma pelo
simbolo:
4.5 O Conceito de variavel Local e Global
Cada subprograma, além de ter acesso às variáveis do programa que
o chamou (são as variáveis globais), pode ter suas próprias variáveis (são
as variáveis locais), que existem apenas durante sua chamada.
Ao se chamar um subprograma, também é possível passar-lhe
determinadas informações que recebem o nome de parâmetros (são valores
que, na linha de chamada, ficam entre os parênteses e que estão separados
por vírgulas). A quantidade dos parâmetros, sua seqüência e respectivos
tipos não podem mudar: devem estar de acordo com o que foi especificado
na sua correspondente declaração.
Para se criar subprogramas, é preciso descrevê-los após a declaração
das variáveis e antes do corpo do programa principal.
4.6 Procedimentos
Na ferramenta VisuAlg (representação em pseudocódigo),
procedimento é um subprograma que não retorna nenhum valor
(corresponde a uma função que não devolve valores (void) em linguagem C
ou ao procedure do Pascal). Sua declaração, que deve estar entre o final da
declaração de variáveis e a linha inicio do programa principal, segue a
sintaxe abaixo:
procedimento <nome-de-procedimento> [(<seqüência-de-
declarações-de-parâmetros>)]
// Secção de Declarações Internas
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
28
inicio
// Secção de Comandos
fimprocedimento
O <nome-de-procedimento> obedece as mesmas regras de
nomenclatura das variáveis. Por outro lado, a <seqüência-de-declarações-
de-parâmetros> é uma seqüência de
[var] <seqüência-de-parâmetros>: <tipo-de-dado>
separadas por ponto e vírgula. A presença (opcional) da palavra-chave
var indica passagem de parâmetros por referência; caso contrário, a
passagem será por valor.
Por sua vez, <seqüência-de-parâmetros> é uma seqüência de nomes
de parâmetros (também obedecem a mesma regra de nomenclatura de
variáveis) separados por vírgulas.
De modo análogo ao programa principal, a secção de declaração
internas começa com a palavra-chave var, e continua com a seguinte
sintaxe:
<lista-de-variáveis> : <tipo-de-dado>
Nos próximos exemplos, através de um subprograma soma, será
calculada a soma entre os valores 4 e –9 (ou seja, será obtido o resultado
13) que o programa principal imprimirá em seguida. No primeiro caso, um
procedimento sem parâmetros utiliza uma variável local aux para
armazenar provisoriamente o resultado deste cálculo (evidentemente, esta
variável é desnecessária, mas está aí apenas para ilustrar o exemplo),
antes de atribuí-lo à variável global res:
procedimento soma
var aux: inteiro
inicio
// n, m e res são variáveis globais
aux <- n + m
res <- aux
fimprocedimento
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
29
No programa principal deve haver os seguintes comandos:
n <- 4
m <- -9
soma
escreva(res)
A mesma tarefa poderia ser executada através de um procedimento
com parâmetros, como descrito abaixo:
procedimento soma (x,y: inteiro)
inicio
// res é variável global
res <- x + y
fimprocedimento
No programa principal deve haver os seguintes comandos:
n <- 4
m <- -9
soma(n,m)
escreva(res)
A passagem de parâmetros do exemplo acima chama-se passagem
por valor. Neste caso, o subprograma simplesmente recebe um valor que
utiliza durante sua execução. Durante essa execução, os parâmetros
passados por valor são análogos às suas variáveis locais, mas com uma
única diferença: receberam um valor inicial no momento em que o
subprograma foi chamado.
4.7 Funções
A função é um subprograma que retorna um valor (corresponde ao
function da linguagem C). Na ferramenta VisualAlg e de modo análogo aos
procedimentos, sua declaração deve estar entre o final da declaração de
variáveis e a linha inicio do programa principal, e segue a sintaxe abaixo:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
30
funcao <nome-de-função> [(<seqüência-de-declarações-de-
parâmetros>)]: <tipo-de-dado>
// Secção de Declarações Internas
inicio
// Secção de Comandos
fimfuncao
O <nome-de-função> obedece as mesmas regras de nomenclatura
das variáveis. Por outro lado, a <seqüência-de-declarações-de-parâmetros>
é uma seqüência de
[var] <seqüência-de-parâmetros>: <tipo-de-dado>
separadas por ponto e vírgula. A presença (opcional) da palavra-chave
var indica passagem de parâmetros por referência; caso contrário, a
passagem será por valor.
Por sua vez, <seqüência-de-parâmetros> é uma seqüência de nomes
de parâmetros (também obedecem a mesma regra de nomenclatura de
variáveis) separados por vírgulas.
O valor retornado pela função será do tipo especificado na sua
declaração (logo após os dois pontos). Em alguma parte da função (de
modo geral, no seu final), este valor deve ser retornado através do
comando retorne.
De modo análogo ao programa principal, a secção de declaração
internas começa com a palavra-chave var, e continua com a seguinte
sintaxe:
<lista-de-variáveis> : <tipo-de-dado>
Voltando ao exemplo anterior, no qual calculamos e imprimimos a
soma entre os valores 4 e –9, vamos mostrar como isso poderia ser feito
através de uma função sem parâmetros. Ela também utiliza uma variável
local aux para armazenar provisoriamente o resultado deste cálculo, antes
de atribuí-lo à variável global res:
funcao soma: inteiro
var aux: inteiro
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
31
inicio
// n, m e res são variáveis globais
aux <- n + m
retorne aux
fimfuncao
No programa principal deve haver os seguintes comandos:
n <- 4
m <- -9
res <- soma
escreva(res)
Se realizássemos essa mesma tarefa com uma função com
parâmetros passados por valor, poderia ser do seguinte modo:
funcao soma (x,y: inteiro): inteiro
inicio
retorne x + y
fimfuncao
No programa principal deve haver os seguintes comandos:
n <- 4
m <- -9
res <- soma(n,m)
escreva(res)
4.8 Passagem de parãmetros por referência
Há ainda uma outra forma de passagem de parâmetros para
subprogramas: é a passagem por referência. Neste caso, o subprograma
não recebe apenas um valor, mas sim o endereço de uma variável global.
Portanto, qualquer modificação que for realizada no conteúdo deste
parâmetro afetará também a variável global que está associada a ele.
Durante a execução do subprograma, os parâmetros passados por
referência são análogos às variáveis globais. Na ferramenta
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
32
VisuAlg(pseudocódigo), de forma análoga a Pascal, essa passagem é feita
através da palavra var na declaração do parâmetro.
Voltando ao exemplo da soma, o procedimento abaixo realiza a
mesma tarefa utilizando passagem de parâmetros por referência:
procedimento soma (x,y: inteiro; var result: inteiro)
inicio
result <- x + y
fimprocedimento
No programa principal deve haver os seguintes comandos:
n <- 4
m <- -9
soma(n,m,res)
escreva(res)
4.9 Recursividade
Recursividade é a possibilidade de que um subprograma se possa
chamar a si mesmo. A função apresentada abaixo calcula recursivamente o
factorial do número inteiro que recebe como parâmetro:
funcao factorial (v: inteiro): inteiro
inicio
se v <= 2 entao
retorne v
senao
retorne v * fatorial(v-1)
fimse
fimfuncao
4.10 Tipos de dados Variaáveis e Expressões
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
33
Tipos de dados primitivos mais comuns em algoritmia (ciência dos
computadores):
Real (Numero do Tipo 3.1416)
inteiro (Numero do Tipo 23)
Caractere (Caracter do Tipo “a” ou “1”)
logico (Tipo falso ou verdadeiro)
Em pesudocódigo declaramos explicitamente os tipos na declaração
das variaveis e constantes na seccção Var.
Exemplo:
var x: real
y: inteiro
a: caractere
l: logico
Em linguagem C temos diferentes Classes, classificadores e operações
de casting de tipos, para alterar os tipos base enunciados. Assim por
exemplo atributos como register, volatil, signed, extern, static, long e
outros podem alterar significativamente os intervalos de valores
respresentaveis pelos diversos tipos base.
4.11 Operadores Aritméticos
+,-
Operadores unários, isto é, são aplicados a um único
operando. São os operadores aritméticos de maior precedência.
Exemplos: -3, +x. Enquanto o operador unário - inverte o sinal do
seu operando, o operador + não altera o valor em nada o seu
valor.
\ Operador de divisão inteira. Por exemplo, 5 \ 2 = 2. Tem a
mesma precedência do operador de divisão tradicional.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
34
+,-,*,/
Operadores aritméticos tradicionais de adição, subtração,
multiplicação e divisão. Por convenção, * e / têm precedência
sobre + e -. Para modificar a ordem de avaliação das operações, é
necessário usar parênteses como em qualquer expressão
aritmética.
%
Operador de módulo (isto é, resto da divisão inteira). Por
exemplo, 8 % 3 = 2. Tem a mesma precedência do operador de
divisão tradicional.
^
Operador de potenciação. Por exemplo, 5 ^ 2 = 25. Tem a
maior precedência entre os operadores aritméticos binários
(aqueles que têm dois operandos).
++ , --
Operadores Unários formalmente equivalente ao incremento
ou decremento de uma unidade.Exemplo em linguagem C: ++a é
equialente a a=a+1 (semelhante para o operador --). Lembra-se
no entanto que ++a e a++ t~em comportamentos diferentes
numa operação de atribuição. Exemplo: b=++a é diferente de
B=a++.No primeiro caso primeiro a variavel a é incrementada e
só depois atribuida a b, no segundo caso primeiro é feito a
atribuição e só depois é feito o incremento.
Operadores de Caracteres
+
Operador de concatenação de strings (isto é, cadeias de
caracteres), em peseudo código mas com implementação em
linguagens de programação muito distintas. Quando usado com dois
valores (variáveis ou constantes) do tipo "caractere" em
pseudocódigo o seu comportamento é conforme representado no
exemplo: "Rio " + " de Janeiro" = "Rio de Janeiro".
4.12 Operadores relacionais
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
35
=, <, >,
<=, >=, <>
Respectivamente: igual, menor que, maior que, menor ou igual a, maior ou igual a, diferente de. São utilizados em expressões lógicas para se testar a relação entre dois valores do mesmo tipo. Exemplos: 3 = 3 ( 3 é igual a 3?) resulta em VERDADEIRO ; "A" > "B" ("A" está depois de "B" na ordem alfabética?) resulta em FALSO. Lembra-se que em linguagem C o operador <> é impementado como !=.
4.13 Operadores Boleanos
nao
Operador unário de negação. nao VERDADEIRO = FALSO, e nao FALSO = VERDADEIRO. Tem a maior precedência entre os operadores lógicos. Equivale ao NOT do Pascal ou ao ! da linguagem C.
ou Operador que resulta VERDADEIRO quando um dos seus operandos lógicos for verdadeiro. Equivale ao OR do Pascal ou || da linguagem C.
e Operador que resulta VERDADEIRO somente se seus dois operandos lógicos forem verdadeiros. Equivale ao AND do Pascal ou ao && da Linguagem C.
Xou Operador que resulta VERDADEIRO se seus dois operandos lógicos forem diferentes, e FALSO se forem iguais. Equivale ao XOR do Pascal e não existe explicitamente em linguagem C.
4.14 Ficheiros de Texto
Uma forma muito comum de armazenamento ou leitura de dados é o
ficheiro de texto. Essencialmente usamos dois tipos de estrutura de
ficheiros de textoquanto ao tipo de acesso:
Os ficheiros SEQUÊNCIAIS
Os ficheiros ALEATÓRIOS ou RANDÔMICOS
Esta classificação deriva do facto do acesso nos primeiros ter que ser
feita sequêncialmente, e no segundo poder ser feita de forma aleatória.
Lembro no entanto que para este segundo tipo de organização os registos
do ficheiro são de dimensão fixa.
Comando Arquivo
Em pseudocódigo vamos utilizar o termo arquivo ou ficheiro como
sinônimos mas em VisualAlg será utilizado o termo arquivo. O VisuAlg
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
36
permite o armazenamento de dados em um arquivo-texto, obtendo deles os
dados ao através dos comandos leia.
Esta característica funciona da seguinte maneira:
1) Se não existir o arquivo com nome especificado, o VisuAlg fará uma
leitura de dados através da digitação, armazenando os dados lidos neste
arquivo, na ordem em que forem fornecidos.
2) Se o arquivo existir, o VisuAlg obterá os dados deste arquivo até
chegar ao seu fim. Daí em diante, fará as leituras de dados através da
digitação.
3) Somente um comando arquivo pode ser empregado em cada
pseudocódigo, e ele deverá estar na seção de declarações (dependendo do
"sucesso" desta característica, em futuras versões ela poderá ser
melhorada...).
4) Caso não seja fornecido um caminho, o VisuAlg irá procurar este
arquivo na pasta de trabalho corrente (geralmente, é a pasta onde o
programa VISUALG.EXE está). Este comando não prevê uma extensão
padrão; portanto, a especificação do nome do arquivo deve ser completa,
inclusive com sua extensão (por exemplo, .txt, .dat, etc.).
A sintaxe do comando é:
arquivo <nome-de-arquivo>
<nome-de-arquivo> é uma constante caractere (entre aspas duplas).
Veja o exemplo a seguir:
algoritmo "lendo do arquivo"
arquivo "teste.txt"
var x,y: inteiro
inicio
para x de 1 ate 5 faca
leia (y)
fimpara
fimalgoritmo
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
37
5 Introdução a implementação de algoritmos usando
linguagem C (a implementar na disciplina de Programação I)
5.1 Forma Geral de um programa em C
5.2 Declaração e inicialização de variaveis e constantes
5.3 Expressões em C
5.4 Implementação de estruturas de controlo de fluxo
5.5 Leitura(input) e Escrita(output) de dados
5.6 Funções, argumentos e passagem de parâmetros
5.7 Exemplos de programas em C
Vamos implementar exemplos muito simples em linguagem C para
compreender todo o ciclo de desenvolvimento de um algoritmo e a sua
implmentação numa linguagem de alto nível, a linguagem C. Para o efeito
vamos usar um compilador rudimentar o Pacific C 7.51 da Hitec para Ms-
Dos (Lembram-se !!!). Este compilador possui um interface em DOS
rudimentar que inclui um editor com capacidade de salientar
contextualmente as palavras e funções standards do C. Todo o ciclo de
compilação é executado neste ambiente:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
38
Os passos necessários a compilação de um programa executavel são:
1. Fazer um duplo click no simbolo do Editor do Compilador
PPD.EXE
2. Criar o programa em Linguagem C no editor. Salvar o programa
em directoria(pasta) apropriada.
3. Executar a compilação e linkagem, usando a opção
Compile/Compile and Link. Nesta fase o compilador verifica se
existem erros e assinala-os na janela inferior. Se occorrem
erros não é criado nenhum executavel capaz de correr em
Windows.
4. Correr o programa executando Run/Run Nome do programa
Exemplo 1 – Calcular a média de uma lista de 10 notas(inteiros)
resultantes de um teste numa turma.
PseudoCódigo em VisualAlg 2.0
algoritmo "Media_notas"
// Função : Calcular a media das notas de uma disciplina
// Autor : Jorge Mota
// Data : 08-11-2006
// Vamos cacular a media pela formula Media=Somatorio_notas/Numero de Notas
//Versão 1.0
var
i,n:inteiro
soma,media,nota:real
inicio
//inicialização de variaveis
Soma<-0
media<-0
nota<-0
i<-0
n<-0
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
39
// ler o numero de alunos dos quais se pretende ler notas
escreval("Numero de notas que quer ler :")
leia(n)
//Ciclo em que vamos ler a nota de cada aluno e a acumulamos em SOMA
para i<-1 ate n faca
escreva("Nota ")
escreval(i)
leia(nota)
soma<-soma+nota
fimpara
media<-soma/n
escreva("A Média da Turma é =")
escreval(media)
fimalgoritmo
Fluxograma (Visio)
Implementação em Linguagem C
Exemplo 2 – Calcular e imprimir os numeros primos até 100.
PseudoCódigo em VisualAlg 2.0
Fluxograma (Visio)
Implementação em Linguagem C
Exemplo 3 – Calcular e imprimir a tabuada dos 5.
PseudoCódigo em VisualAlg 2.0
Fluxograma (Visio)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
40
Implementação em Linguagem C
Exemplo 4 – Calcular o factorial de um número.
PseudoCódigo em VisualAlg 2.0
algoritmo "Calcular_o_factorial_de_10"
// Função : Calcula o factorial de 10 usando
//uma função generica factorial()
// Autor : Jorge Mota
// Data : 21-11-2006
// VERSÃO 1.0
var
Valor:inteiro
inicio
funcao factorial(n:inteiro):inteiro
var
i,f:inteiro
inicio
f<-1
para i<-n ate 1 passo -1 faca
f<-f*i
fimpara
retorne f
fimfuncao
// Indicar o numero a calcula
valor<-factorial(10)
escreval("O factorial de 10=",valor)
fimalgoritmo
Fluxograma (Visio)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
41
Implementação em Linguagem C
#include "stdio.h"
int factorial(int n);
main()
{
int valor;
valor=factorial(10);
printf("O factorial de 10=%d\n",valor);
}
int factorial(int n)
{
int i,f;
f=1;
for(i=n;i>=1;--i)
{
f=f*i;
}
return f;
}
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
42
Exemplo 5 – Calcular as raizes de uma equação do 2º Grau
Ax^2+Bx+C=0, e imprimir o resultado na forma :X1=a+|b|.
PseudoCódigo em VisualAlg 2.0
algoritmo "Calculo das Raizes de uma Equação do 2 grau"
// Função : Calcular pela formula resolvente as raizes reais se // A==0
// Neste caso usar a formula X1R<-((-b+sqrt(Delta))/(2*a))
// X2R<-((-b+sqrt(Delta))/(2*a))
// X1i<-0 e X2i<-0
// CASO DELTA SEJA MENOR QUE 0 ENTÃO
// x1r<-(-b)/(2*a)
// x1i<- SQRT(-DELTA)/(2*A)
// x2r<-x1r
// x2i<--x1i
// em ambos os casos delta<-b^2-4*a*c
// Autor : Jorge Mota
// Data : 28-11-2006
// Secção de Declarações de variaveis
// A,B,C,Delta,x1r,x2r,x1i,x2i como numeros reais
// temos que assegurar que a!=0
var
A,B,C,Delta,x1r,x2r,x1i,x2i real;
inicio
// Secção de Comandos
// Leitura de A,B,C
// A leitura de A tem que ser !=0
repita
escreva("A=")
leia(A)
fimrepita (A<>0)
//ler b
escreva ("B=")
leia(B)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
43
//Ler C
escreva("C=")
leia(C)
//Calcular o Delta
delta<-b^2-4*a*c
SE (delta>=0) entao
x1r<-((-b)+SRQT(delta))/(2*a)
x2r<-((-b)-SRQT(delta))/(2*a)
x1i<-0
x2i<-0
senao
x1r<-(-b)/(2*a)
x1i<-SQRT(-delta)/(2*a)
x2r<-x1r
x2i<-(-x1i)
fimse
//Escrever em formato numeros complexos
escreva("X1=")
escreva(x1r)
escreva("+i")
escreval(x1i)
//Escrever em formato numeros complexos
escreva("X2=")
escreva(x2r)
escreva("+i")
escreval(x2i)
//Termina
fimalgoritmo
Fluxograma (Visio)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
44
Implementação em Linguagem C
#include <stdio.h>
#include <math.h>
void main(void)
{
/*Calculo das raizes de uma equacao do 2 Grau
Jorge Mota
V1.0
28-11-06
IMPORTANTE: em Pacific C temos de dar uma indicação ao
Compilador para usar a biblioteca de virgula flutuante
ir a Options e ligar a opção Use floating point library
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
45
*/
//Declaracao e inicialização de Variaveis
//Se delta >=0 então tem raizes reais
//Senão tem raizes não reais
float A=0,B=0,C=0,Delta=0,X1R=0,X1I=0,X2R=0,X2I=0;
printf("Calcular as raizes da EQ Ax^2+Bx+C=0\n");
//Ler o coeficiente A
do
{
printf("\nA=");
scanf("%f", &A);
}
while (A==0);
//Ler o coeficiente B
printf("\nB=");
scanf("%f", &B);
//Ler o coeficiente C
printf("\nC=");
scanf("%f",&C);
//Processar as raizes
//Calcular Delta
Delta=(B*B-4*A*C);
//testar se delta >=0
if (Delta>=0)
{
X1R=((-B)+sqrt(Delta))/(2*A);
X2R=((-B)-sqrt(Delta))/(2*A);
X1I=0;
X2I=0;
}
else
{
X1R=(-B)/(2*A);
X1I=sqrt(-Delta)/(2*A);
X2R=X1R;
X2I=(-X1I);
}
//Escrever as raizes em formato numeros complexos a+i|b|
printf("\n-------------------------------------------");
printf("\nRaizes da Equação %fX^2+%fX+%f=0",A,B,C);
printf("X1=%10.2f+i%10.2f\n",X1R,fabs(X1I));
printf("X2=%10.2f+i%10.2f\n",X2R,fabs(X2I));
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
46
}
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
47
5.8 Arrays, Matrizes e Strings
Um array é uma colecção de variaveis partilhando um mesmo nome mas que podem ser acedidas individualmente usando um indice. O indice aprece entre parentises rectos ([ ]) depois do nome da variavel do tipo array. Ilustra na figura abaixo um array unidimensional com nome Notas contendo 4 elementos (numerados de 1 a 4). O que é mostrado são os nomes dos elementos não os seus valores.
Notas[1] Notas[2] Notas[3] Notas[4]
O numero entre parentises recto, como já referido anteriormente é o indice. Este distingue as diferentes “variaveis” agrupadas sobre o nome Notas. Nota Importante: O indice tem que ser um numero inteiro positivo. Em C o primeiro elemento é o Zero. Noutras linguagem como Visual Basic podemos establecer se começa em o ou 1. Em Raptor tem que ser um inteiro maior ou igual a 1.
Abaixo é mostrada uma forma diferente de visualizar a estrutura de um array, na primeira linha aparece o indice e na segunda o valor de cada elemento associados a cada indice.
Notas
1 2 3 4
87 93 77 82
O poder dos array nos programas é que nos permite processar inumeros valor com um simples ciclo contado (loop). O corpo do ciclo processa cada elemento do array através da indexação dos respecitos elementos.
Estudemos o exemplo: Calculo da média de 4 valores
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
48
Start
Numero_max_elementos ← 4
Soma ← 0
Contador ← 1
Contador>4
"Ler Valor:"GET Notas[contador]
Soma ← soma + Notas[contador]
contador ← contador + 1
Media ← soma / Numero_max_element
os
PUT "Media ="+Media¶
End
Yes
No
Loop
Note que para um programador é indiferente processar 4 ou 4000 valores. Esta é a grande vantagem do computador.
Exemplos com arrays:
Exercicio 1: Elabore um algoritmo que permita ler 6 notas de alunos de uma turma e os respectivos numeros, calcule qual a nota maxima e minima e mostre quais os respectivos numeros dos alunos que as obtiveram.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
49
Start
Maxima ← 0
imax ← 0
Minima ← 21
imin ← 0
i ← 1
i>6
"Leia Numero Aluno :"GET numero
"Leia Nota"GET nota
numeros[i] ← numero
notas[i] ← nota
nota>maxima
maxima ← nota
imax ← i
NoYes
nota<minima
minima ← nota
imin ← i
NoYes
i ← i + 1
PUT "O Aluno "+numeros[imax]+" tem a mais alta
Nota="+maxima¶
PUT "O aluno"+numeros[imin]+" Tem a nota
baixa="+minima¶
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
50
Exercicio 2: Altere o exercício anterior de forma que o algoritmo calcule a média da turma.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
51
Start
Maxima ← 0
imax ← 0
Minima ← 21
imin ← 0
i ← 1
i>6
"Leia Numero Aluno :"GET numero
"Leia Nota"GET nota
numeros[i] ← numero
notas[i] ← nota
nota>maxima
maxima ← nota
imax ← i
NoYes
nota<minima
minima ← nota
imin ← i
NoYes
i ← i + 1
PUT "O Aluno "+numeros[imax]+" tem a mais alta
Nota="+maxima¶
PUT "O aluno"+numeros[imin]+" Tem a nota
baixa="+minima¶
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
52
Resolução em pesudo-código: algoritmo "Calculo de Max_Min_Media" // Função : Calcular o valor maximo, minimo e media de 6 notas // Autor : Jorge Mota // Data : 05-12-2006 // Secção de Declarações var notas: vetor [1..6] de real numeros: vetor [1..6] de inteiro maxima,minima,media,soma,nota : real i,imax,imin,numero : inteiro inicio // Secção de Comandos //Inicialização de variaveis soma<-0 media<-0 maxima<-0 minima<-21 imax<-0 imin<-0 //Leitura e processamento para i<-1 ate 6 faca escreva("Numero do aluno=") leia(numero) escreva("Nota =") leia(nota) notas[i]<-nota numeros[i]<-numero soma<-soma+nota se (nota>maxima) entao maxima<-nota imax<-i fimse se (nota<minima) entao minima<-nota imin<-i fimse fimpara media<-soma/6 escreval("Nota maxima") escreval(maxima) escreval(imax) escreval("Nota minima") escreval(minima) escreval(imin) Escreva("Media =") escreval(media)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
53
fimalgoritmo
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
54
Exercicio 3: Calculo das médias por aluno e disciplinas.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
55
Start
NA ← 3
ND ← 3
Inicializa_array
i ← 1
j ← 1
i>NA
j>ND
"Nota do aluno numero "+i+" da disciplina "+j
GET notas[i,j]
notas[i, NA + 1] ← notas[i, NA + 1] +
notas[i, j]
temp ← notas[i, j] / ND
notas[ND + 1, j] ← notas[ND + 1, j] +
temp
PUT temp¶
j ← j + 1
notas[i, NA + 1] ← notas[i, NA + 1] / NA
j ← 1
i ← i + 1
Yes
No
Loop
PUT "Terminou !!!"¶
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
56
Start
NA ← 3
ND ← 3
Inicializa_array
i ← 1
j ← 1
i>NA
j>ND
"Nota do aluno numero "+i+" da disciplina "+j
GET notas[i,j]
notas[i, NA + 1] ← notas[i, NA + 1] +
notas[i, j]
temp ← notas[i, j] / 3
notas[ND + 1, j] ← notas[ND + 1, j] +
temp
PUT temp¶
j ← j + 1
notas[i, NA + 1] ← notas[i, NA + 1] / NA
j ← 1
i ← i + 1
Yes
No
Loop
PUT "Terminou !!!"¶
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
57
Pseudo-Código
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
58
5. Leitura validada de uma posição para o jogo do Galo:
Start
x ← 0
y ← 0
x >= 1 and x<=3 and y>=1 and y<=3
"X="GET x
"Y="GET y
x >= 1 and x<=3 and y>=1 and y<=3
PUT "ATENÇÂO SÓ PODE USAR VALORES ENTRE
[1 e 3]"¶
NoYes
PUT "X="+x+" Y="+y¶
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
59
6. Desenhe um algoritmo que escreva os primeiros n numeris de Fibonacci uma série de fibonacci.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
60
7. Desenvolva algoritmicamente em raptor o jogo do Galo?
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
61
5.9 Ponteiros
No campo da programação, um ponteiro ou apontador é um tipo de dado de uma linguagem de programação cujo valor se refere diretamente a um outro valor alocado em outra área da memória, através de seu endereço. Um ponteiro é uma simples implementação do tipo referência da Ciência da Computação.
5.9.1 Arquitetura
Ponteiros são uma abstração da capacidade de endereçamento fornecidas pelas arquiteturas modernas. Em termos simples, um endereço de memória, ou índice numérico, é definido para cada unidade de memória no sistema, no qual a unidade é tipicamente um byte ou uma word, o que em termos práticos transforma toda a memória em um grande vector. Logo, a partir de um endereço, é possível obter do sistema o valor armazenado na unidade de memória de tal endereço. O ponteiro é um tipo de dado que armazena um endereço.
Na maioria das arquiteturas, um ponteiro é grande o suficiente para indexar todas as unidades de memória presentes no sistema. Isso torna possível a um programa tentar aceder a um endereço que corresponde a uma área inválida da memória, o que é chamado de falha de segmentação. Por outro lado, alguns sistemas possuem mais unidades de memória que endereços. Nesse caso, um esquema mais complexo, como o de segmentação ou paginação, é utilizado para utilizar diferentes regiões da memória – a estudar em arquitectura de computadores.
Para fornecer uma interface consistente, algumas arquiteturas fornecem E/S mapeada em memória, o que permite que enquanto alguns endereços são referenciados como áreas de memória, outros são referenciados como registradores de dispositivos do computador, como equipamentos periféricos – muito utilizado em arquitectura de dispositivos embebidos.
5.9.2 Utilidade
Os Ponteiros são directamente suportados sem restrições em C, C++, D e Pascal, entre outras linguagens. São utilizados para construir referências, elemento fundamental para construir a maioria das estruturas de dados, especialmente aquelas não alocadas em um bloco contínuo de memória (heap), como listas encadeadas, árvores ou grafos. Também são utilizados para especificar o endereço de funções de re-chamada (callback), utilizando o conceito de ponteiro para função.
Em outras estruturas de dados, como listas encadeadas, ponteiros são usados como referências para intercalar cada elemento da estrutura com seus vizinhos (seja anterior ou próximo).
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
62
Os Ponteiros também são utilizados para simular a passagem de parâmetros por referência em linguagens que não oferecem essa construção (como o C). Isso é útil se desejamos que uma modificação em um valor feito pela função chamada seja visível pela função que a chamou. A mesma construção também é útil para que uma função possa retornar múltiplos valores.
Linguagens como C e C++ permitem que ponteiros possam ser utilizados para apontar para funções, de forma que possam ser invocados como uma função qualquer. Essa abordagem é essencial para a implementação de modelos de callback, muito utilizados actualmente em bibliotecas de código para manipulação de interfaces gráficas. Tais ponteiros devem ser do tipo do retorno da função o qual apontam. Ponteiros para função se assemelham a functores, ainda que o conceito função objeto seja mais abrangente.
Exemplos
Abaixo é mostrado o exemplo da declaração de uma lista encadeada em C, o que não seria possível sem o uso de ponteiros:
/* a lista encadeada vazia é representada por NULL ou algum outro símbolo */ #define LISTA_VAZIA NULL struct link { void *info; /* conteúdo do nó da lista */ struct link *prox; /* endereço do próximo nó da lista; LISTA_VAZIA se este é o último nó */ }; 5.10 Estruturas avançadas de dados – Estruturas e uniões;
Enumerações e tipos definidos pelo utilizador
5.11 Ficheiros de Texto em C, Rapor e VisualAlg
Um ficheiro é uma colecção de dados que reside num disco ou outro meio(dispositivo) persistente de armazenamento de dados (ex: pendrive). O mais comum dos tipos de ficheiros é o designado ficheiro de texto (text file), que é normalmente um conjunto organizado de linhas de texto que conseguimos ler. Este tipo de ficheiro pode ser criado com um programa tipo Notepad do Windows. Normalmente a extensão é .txt.
Os ficheiros são usados essencialmente pelos programas para guardar dados entre execuções. Exemplos o ficheiro com a máxima pontuação obtida num jogo ou o ficheiro de configuração de um determinado programa(INI). Um ficheiro como este pode conter um ou milhares de elementos (linhas).
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
63
Os ficheiros também são muito usados em programação para evitar a reintrodução de extensos conjuntos de dados. É normal na vida real que os programas trabalhem com centenas de milhares de dados ou mesmo milhões. Não parece facilmente realizável serem reintroduzidos de cada vez que se corre o programa!
Finalmente uma última utilização como forma de output final de um programa(saida). Nestes outputs podemos formatar os dados para os mais diversos efeitos – impressão, novo input etc.
Em Raptor os programas podem ler ou escrever directamente de ficheiros de texto por redireccionamento. No raptor quando estamos em modo leitura de ficheiro (ou escrita não podemos simultaneamente fazer leituras de outros dispositivos – ex: teclado ou output para a Master Console.
Em raptor a leitura dos dados do ficheiro é feita linha a linha e no caso de não conhecermos o tamanho do ficheiro podemos usar a função End_Of_Input, que devolve true nesta situação.
Exemplo de redireccionamento:
Chamamos a função,
Redirect_Input("file.txt")
ou
Redirect_Input("C:\Documents and Settings\file.txt");
Exercício:
Implementar em raptor um algoritmo que gere um ficheiro com 10000 valor aleatórios entre 1 e 10000.O nome do ficheiro deve ser “bateria_dados_10000.txt”
Resolução em Raptor:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
64
Start
Redirect_Output("bateria_dados_10000
.txt")
n ← 10
i ← 1
i>10
Num ← Floor(random * 10000)
PUT Num¶
i ← i + 1
Redirect_Output(no)
PUT "Terminou a Geração !"¶
End
Yes
No
Loop
6 Ordenação e Pesquisa
6.1 Pesquisa
Vamos considerar três tipos de pesquisa em sequências de dados ou valores (vectores, listas ou ficheiros) : Sequencial ou Linear, Dicotómica ou Binária e Hashing ou pesquisa por dispersão. Dada a complexidade deste último método o seu estudo fica para uma disciplina de estruturas de dados num próximo semestre.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
65
Pesquisa sequencial ou linear
Na área de informática, ou Ciência da Computação, costuma-se usar o termo busca linear para expressar um tipo de pesquisa em vectores ou listas de modo sequencial, ou seja, elemento por elemento, de modo que a função do tempo em relação ao número de elementos é linear, por outras palavras, cresce proporcionalmente. Num vector ordenado, essa não é a pesquisa mais eficiente, a pesquisa (ou busca) binária, por exemplo, é um tipo de pesquisa com o gráfico de tempo logaritmo, portanto muito mais eficiente[pt.wikipedia.org]. No entanto a pesquisa linear é a pesquisa que permite fazer buscas em sequências não ordenadas e como tal aplicável em grande numero de situação em que pretendemos conhecer as as características da sequência – maior valor; menor valor; primeiro valor; melhor valor; pior valor [ver capitulo 12, pág. 428 Introdução a Programação usando C, António Rocha FCA]. A complexidade desse algoritmo é da ordem de n, onde n é o tamanho do vector de busca.
Código em C /** * Retorna -1 caso não encontre ou a posição * caso encontre. */ int procura(char vetor[], int tamanho, char elementoProcurado) { int i; for (i = 0; i < tamanho; i++) { if (vetor[i] == elementoProcurado) { return i; } } return -1; }
Pesquisa binária
A pesquisa ou busca binária ( em inglês binary search algorithm) é um algoritmo de busca em vectores que requer acesso aleatório aos elementos do mesmo. Ela parte do pressuposto de que o vector está ordenado, e realiza sucessivas divisões do espaço de busca comparando o elemento procurado (chave) com o elemento no meio do vector. Se o elemento do meio do vector for a chave, a busca termina com sucesso. Caso contrário, se o elemento do meio vier antes do elemento procurado, então a busca continua na metade posterior do vector. E finalmente, se o elemento do meio vier depois da chave, a busca continua na metade anterior do vector. A complexidade desse algoritmo é da ordem de log2 n, onde n é o tamanho do vector de busca.
Um pseudocódigo recursivo para esse algoritmo: dados V o vector com elementos comparáveis, n seu tamanho e o elemento que se deseja encontrar:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
66
BUSCA-BINÁRIA (V[], inicio, fim, e} i recebe o índice no meio de inicio e fim se V[i] é igual a e então devolva o índice i # encontrei e senão se V[i] vem antes de e então faça a BUSCA-BINÁRIA(V, i+1, fim, e) senão faça a BUSCA-BINÁRIA(V, inicio, i-1, e)
Código em C int PesquisaBinaria(char chave,char k[],int N) { int inf,sup,meio; inf=0; sup=N-1; while (inf<=sup) { meio=(inf+sup)/2; if (chave==k[meio]) return meio; else if (chave<k[meio]) sup=meio-1; else inf=meio+1; } return -1; /* não encontrado */ } 6.1.1 Exercício - Pesquisa sequencial ou linear em lista desordenada, lida de um ficheiro externo (“dados.txt” com 10 elementos).
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
67
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
68
6.1.2 Exercício - Pesquisa Binária em lista ordenada. A lista é lida de ficheiro de texto com uma sequência ordenada. Implementação feita em Raptor.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
69
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
70
6.1.3 Exercício - Pesquisa Binária em lista ordenada com inserção na posição correcta na situação do elemento não constar na sequência. A lista de elementos é lido de ficheiro de texto exterior. Implementação feita em Raptor.
Start
Redirect_Input("c:\Dicotomica_
dados.txt")
n ← 10
i ← 1
i>=11
""GET Lista[i]
i ← i + 1
Redirect_Input(no)
"Qual o Valor a Procurar?"GET valor
inf ← 1
sup ← 10
Flag ← 1
(inf>sup) or (Flag=0)
meio ← floor((inf + sup) / 2)
Valor=Lista[meio]
Flag ← 0Valor<=Lista
[meio]
sup ← meio - 1 inf ← meio + 1
NoYes
NoYes
(Flag=0)
PUT "Encontrou o Valor na Posição
"+meio¶
PUT "Não Encontrou ..."¶
inserir_ordenada
NoYes
End
Yes
No
Loop
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
71
6.2 Ordenação
Algoritmo de ordenação em ciência da computação é um algoritmo que coloca os elementos de uma dada sequência numa certa ordem – por outras palavras, efectua a ordenação completa ou parcial. As ordens mais usadas são a numérica e a lexicográfica.
Existem várias razões para se ordenar uma sequência. Uma delas é a possibilidade se aceder seus dados de modo mais eficiente.
Em termos de algoritmos de ordenação vamos considerar duas grandes categorias:
1) Algoritmos de ordenação Interna
A lista de valores a ordenar encontra-se em estruturas de dados em memória (vectores ou listas).
1) Algoritmos de ordenação externa
Algoritmos que fazem a ordenação de listas de valores em ficheiros externos.
Todos os algoritmos que vamos estudar são da primeira categoria deixando para posterior disciplina (unidade curricular) no curso o estudo de algoritmos de ordenação externa.
7 Bubble sort
O bubble sort, ou ordenação por flutuação (literalmente "por bolha"), é um algoritmo de ordenação dos mais simples. A ideia é percorrer o vector diversas vezes, a cada passagem fazendo flutuar para o topo o menor elemento da sequência. Essa movimentação lembra a forma como as bolhas num tanque de água procuram o seu próprio nível, e daí o nome do algoritmo.
No melhor caso, o algoritmo executa (n2) / 2 operações relevantes. No pior caso, são feitas 2n2operações. No caso médio, são feitas (5n2) / 2 operações. A complexidade desse algoritmo é de Ordem quadrática. Por isso, ele não é recomendado para programas que precisam de velocidade e operam com uma quantidade elevada de dados.
O algoritmo pode ser descrito em pseudocódigo como segue representado abaixo. V é um VECTOR de elementos que podem ser comparados e n é o tamanho desse vector.
BUBBLESORT (V[], n) 1 houveTroca <- verdade # uma variável de controle 2 enquanto houveTroca for verdade faça 3 houveTroca <- falso 4 para i de 1 até n-1 faça 5 se V[i] vem depois de V[i + 1] 6 então troque V[i] e V[i + 1] de lugar e 7 houveTroca <- verdade
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
72
Implementação em C void bubble(int x[],int n) { int troca, i, j, aux; for (i = n-1; i > 0; i--) { // o maior valor entre x[0] e x[i] vai para a posição x[i] troca = 0; for (j =0 ; j < i-1; j++) { if (x[j] > x[j+1]) { aux = x[j]; x[j] = x[j+1]; x[j+1] = aux; troca = 1; } } if (!troca) return; } }
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
73
Implementação em Raptor Bubble Sort:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
74
Start
Carregar_Lista
Troca ← 1
i ← n
(i<=1) or (Troca=0)
Troca ← 0
j ← 1
(j>i - 1)
(Lista[j]>Lista[j + 1])
Swap
Troca ← 1
NoYes
j ← j + 1
i ← i - 1
Yes
No
Loop
PUT "Terminou!"¶
End
Yes
No
Loop
Implementação Bubble Sort
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
75
Start
temp ← Lista[j]
Lista[j] ← Lista[j + 1]
Lista[j + 1] ← temp
End
Start
Redirect_Input("c:\bateria_dados_100
0.txt")
n ← 100
k ← 1
k>n
""GET Lista[k]
k ← k + 1
Redirect_Input(no)
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
76
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
77
Ordenação por Selecção
O selection sort , ou ordenação por selecção, é baseado no seguinte principio: passar sempre o menor valor do vector para a primeira posição (ou o maior dependendo da ordem requerida), depois o do segundo menor valor para a segunda posição, e assim sucessivamente para os (n-1) elementos restantes, até aos últimos dois elementos.
Código em C void selectionSort(int vetor[],int tam) { int i,j; int min,aux; for (i=0;i<tam-1;i++) { min=i; for (j=i+1;j<tam;j++) { if (vetor[j]<vetor[min]) min=j; } aux=vetor[i]; vetor[i]=vetor[min]; vetor[min]=aux; } }
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
78
Implementação em Raptor do algoritmo de ordenação por Selecção:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
79
Implementação dos subprogramas Troca e Carregar Lista:
Start
temp ← Lista[i]
Lista[i] ← Lista[posicao]
Lista[posicao] ← temp
End
Start
Redirect_Input("c:\bateria_dados_100
0.txt")
n ← 100
k ← 1
k>n
""GET Lista[k]
k ← k + 1
Redirect_Input(no)
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
80
Insertion sort
Insertion sort, ou ordenação por inserção, é um algoritmo simples de ordenação, eficiente quando aplicado a um pequeno número de elementos. Em termos gerais, o que faz é percorrer um vector de elementos da esquerda para a direita e à medida que avança vai deixando os elementos mais à esquerda ordenados. O algoritmo de inserção funciona da mesma maneira como muitas pessoas ordenam cartas num jogo de cartas como o poquer.
Implementação em C void insertSort(int a[], size_t length) { int i, j, value; for(i = 1; i < length; ++i) { value = a[i]; for (j = i - 1; j >= 0 && a[j] > value; --j) { a[j + 1] = a[j]; a[j] = value; } } }
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
81
Implementação em Raptor:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
82
Start
Lista[j + 1] ← Lista[j]
Lista[j] ← Valor
End
Start
Redirect_Input("c:\bateria_dados_100
0.txt")
n ← 100
k ← 1
k>n
""GET Lista[k]
k ← k + 1
Redirect_Input(no)
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
83
Shell sort
Criado por Donald Shell em 1959, Shell sort é o mais eficiente algoritmo de classificação entre os de complexidade quadrática. Basicamente o algoritmo passa várias vezes pela lista dividindo o grupo maior em grupos menores. Nos grupos menores é aplicado o método da ordenação por inserção.
Código em C void shellSort( int * vet, int size ){ int i , j , value; int gap = 1; do {gap = 3*gap+1;} while ( gap < size ); do { gap /= 3; for ( i = gap; i < size; i++ ){ value =vet[i]; j = i - gap; while ( j >= 0 && value < vet[j] ){ vet [j + gap] =vet[j]; j -= gap; } vet [j + gap] = value; } } while ( gap > 1); }
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
84
Implementação em Raptor:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
85
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
86
Procedimento Inicializar a Lista com 100 elementos:
Start
Redirect_Input("c:\bateria_dados_100
0.txt")
n ← 4
k ← 1
k>n
""GET Lista[k]
k ← k + 1
Redirect_Input(no)
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
87
Quicksort
Algumas etapas do algoritmo Quicksort.
O algoritmo Quicksort é um método de ordenação muito rápido e eficiente, inventado por C.A.R. Hoare em 1960, quando visitou a Universidade de Moscou como estudante. Foi publicado em 1962 após uma série de refinamentos.
A sua premissa básica é dividir o problema de ordenar n itens em dois problemas menores. Em seguida, os problemas menores são ordenados de forma independente e os resultados são combinados para produzir a solução do problema todo [pt.wikipeia.org].
Complexidade do Quicksort
• Complexidade de tempo: θ(n lg2 n) no melhor caso e no caso médio e θ(n2) no pior caso;
• Complexidade de espaço: θ(lg2 n) no melhor caso e no caso médio e θ(n) no pior caso.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
88
Algoritmo em português estruturado proc quicksort (x:vet[n] int; ini:int; fim:int; n:int) var int: i,j,x,aux; início i <- ini; j <- fim; x <- x[(ini + fim) div 2]; repete enquanto (x[i] < x) faça i <- i + 1; fim-enquanto; enquanto (x[j] > x) faça j <- j - 1; fim-enquanto; se (i <= j) então aux <- x[i]; x[i] <- x[j]; x[j] <- aux; i <- i + 1; j <- j - 1; fim-se; até_que (i >= j); se (j > ini) então exec quicksort (x, ini, j, n); fim-se; se (i < fim) então exec quicksort (x, i, fim, n); fim-se; fim.
Implementação em raptor (versão recursiva – não executável em Raptor)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
89
Start
Carregar_Lista
inicio ← 1
fim ← n
Quicksort
PUT "Terminou!"¶
End
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
90
Implementação do procedimento quicksort:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
91
Start
i ← inicio
j ← fim
x ← Lista[floor((inicio + fim) / 2)]
Lista[i]>=x
i ← i + 1
Lista[j]<=x
j ← j - 1
i<=j
aux ← Lista[i]
Lista[i] ← Lista[j]
Lista[j] ← aux
i ← i + 1
j ← j - 1
NoYes
Yes
No
Loop
Yes
No
Loop
i>=j
j>inicio
fim ← j
Quicksort
NoYes
i<fim
inicio ← i
Quicksort
NoYes
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
92
Implementação da rotina que carrega a Lista:
Start
Redirect_Input("c:\bateria_dados_1000.txt")
n ← 10
k ← 1
k>n
""GET Lista[k]
k ← k + 1
Redirect_Input(no)
End
Yes
No
Loop
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
93
Implementação em C void sort(int array[], int begin, int end) { if (end - begin > 1) { int pivot = array[begin]; int l = begin + 1; int r = end; while(l < r) { if (array[l] <= pivot) { l++; } else { r--; swap(array[l], array[r]); } } l--; swap(array[begin], array[l]); sort(array, begin, l); sort(array, r, end); } }
Implementaçao usando 'fat pivot':
void sort(int array[], int begin, int end) { int pivot = array[begin]; int i = begin + 1, j = end, k = end; int t; while (i < j) { if (array[i] < pivot) i++; else if (array[i] > pivot) { j--; k--; t = array[i]; array[i] = array[j]; array[j] = array[k]; array[k] = t; } else { j--; swap(array[i], array[j]); } } i--; swap(array[begin], array[i]); if (i - begin > 1) sort(array, begin, i); if (end - k > 1) sort(array, k, end); }
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
94
7.1 Filas, Listas e Pilhas
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
95
8 Execicios de algoritmia com cálculo numérico
8.1.1 Notas sobre integração de uma função
Integral simples:
∫xDireita
xEsquerda
dxxf *)(
Este integral representa a área sob a curva no intervalo de xEsquerda a xDireita. A curva é definida pela função f(x). O “dx” indica que estamos a integrar em ordem ao eixo do x.
Representação Visual do Integral:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
96
8.1.2 Integração usando a Regra de Simpson
A regra de Simpson usa como forma de estimativa do valor de um integral, em dado intervalo, o calculo da área definida pela sub-divisão rectangular da mesma. Dado um intervalo de uma função f(x), o método subdivide o intervalo de integração em n sub-intervalos, calculando depois a área de cada sub-intervalo rectangular através da multiplicação da altura do mesmo pela largura de cada sub-divisão. A altura é dada pelo valor da função f(x) no ponto médio de cada sub-divisão, e a largura é dada pelo intervalo a dividir pelo numero de sub-divisões - n. Depois de calculadas todas as áreas o somatório destas é e estimativa de todo o integral no intervalo dado (área abaixo da função). É importante notar que quanto maior for o numero de sub-divisões maior a precisão da área total obtida.
Formulas importantes:
∑=
−∆+∆n
iXXixEsquerdafX
1)2/*(*
Que pode ser re-escrita como:
∑=
−∆+−n
iXxEsquerdafnxEsquerdaxDireita11
))2/1((*/)(
Descrição dos termos:
N=numero de sub-intervalos no intervalo de
nxEsquerdaxDireitaX /)( −=∆ = Largura do sub-intervalo
)2/*( XXixEsquerdaf ∆−∆+ = Altura do sub-intervalo
Representação Visual:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
97
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
98
Start
xEsquerda ← a
xDireita ← b
nDivs ← n
area ← 0
deltax ← (xDireita - xEsquerda) / nDivs
midpointx ← xEsquerda + DeltaX / 2
i ← 0
i>=nDivs
x ← midpointx
area ← area + (3 * x * x - 2 * x) * deltax
midpointx ← midpointx + deltax
i ← i + 1
Calculo do acumulado e funciona co
End
Yes
No
Loop
Parâmetros passados para a função
Start
a ← 1
b ← 2
n ← 1024
F_string ← "(3 * x * x - 2 * x)"
integrar_rect
PUT "Integrar "+F_string+" no intervalo de 0 a 2, então a
area= "+area¶
End
Quanto maior o numero de intervalos mais preciso o resultado
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
99
Start
xEsquerda ← a
xDireita ← b
nDivs ← n
area ← 0
deltax ← (xDireita - xEsquerda) / nDivs
midpointx ← xEsquerda + DeltaX / 2
i ← 0
i>=nDivs
x ← midpointx
area ← area + (3 * x * x - 2 * x) * deltax
midpointx ← midpointx + deltax
i ← i + 1
Calculo do acumulado e funciona como valor de retorno da função
End
Yes
No
Loop
Parâmetros passados para a função
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
100
Notas sobre integração usando a técnica de Monte Carlo
A técnica de integração de Monte Carlo baseia-se na estimativa obtida pela teoria das probabilidades. Dado um intervalo (xEsquerda, xDireita) de uma função, f(x) que está limitada por uma constante M, o método de Monte Carlo aleatoriamente selecciona pontos dentro da “caixa” de restrições horizontal (intervalo de integração) e vertical (constante M) e determina se o ponto fica acima ou a baixo da função. A probabilidade de que o ponto esteja abaixo de f(x) é igual, na proporção da “caixa” de restrição, à probabilidade de estar acima de f(x). Quantos mais pontos forem escolhidos mais precisa a estimativa e portanto mais precisa a área final estimada.
Formulas Importantes:
Área Total = M*(xEsquerda-xDireita)
A área abaixo de f(x) = Pr(Yaleatório<=f(Xaleatório))*M*(xDireita-xEsquerda)
Descrição dos termos da formula:
M = um valor y tal que M>=f(x) para todos os XEsquerda<=X>=Xdireita)
Yaleatório = Um Y aleatório escolhido de forma que 0<=Yaleatório<=M
Xaleatório = UmX aleatório de forma que xEsquerda<=Xaleatório<=xDireita
F(Xaleatório)=f(x) calculado no ponto Xaleatório
Pr(Yaleatório<=f(Xaleatório))= Probabilidade aleatória de o ponto estar abaixo de f(x)
Representação Visual:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
101
Anexo 2 Teste Tipo teórico Pergunta 1 (2 valor) Coloque por ordem crescente de data de aparecimento as seguintes linguagens de programação (da mais antiga para a mais recente) Fortran LISP BASIC C# JAVA C C++ Visual Basic Cobol Pergunta 2 (2 valores) Em termos metodológicos no desenho e implementação algoritmica usamos essencialmente duas abordagens a: Top-Down e a Bottom-up Explique de forma clara em que consistem estas abordagens e em que situações aplicaria um e outro ou ambos. Pergunta 3 (2 valores) Qual a diferença entre função e procedimento? Em ambos podemos usar parâmetros, explique o que são, para que se usam e que tipos de passagens existem( quanto ao modo como é feita a passagem) ? Pergunta 4 (3 Valores) a)Analise o seguinte algoritmo em VisualAlg 2.0 e escreva qual o resultado do mesmo para um numero de elementos igual a 10? b)Substitua a estrutura de controlo REPETIR … ATE () por uma ENQUANTO () FAZER … FIMENQUANTO algoritmo "FIBO" // Função :FIBO // Autor :JORGE MOTA // Data : 29-01-2007 // Secção de Declarações var
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
102
n,a,b,nFin: inteiro inicio // Secção de Comandos escreva("Numero de elementos:") Leia (nFin) n <- 0 a <- 0 b <- 1 REPITA escreval(a) escreval(b) n <- n + 2 a <- a + b b <- b + a ATE (n > (nFin-2)) fimalgoritmo Pergunta 5 (3 valores) Desenvolva um algoritmo em Raptor (fluxograma) que permita converter uma string para maisculas: Exemplo: esTe e um teste de algoritmia. ESTE E UM TESTE DE ALGORITMIA Pergunta 6 (3 valores) Implemente em raptor (fluxograma) e em C um algoritmo que calcule a altura ao solo de um passageiro durante um passeio na roda gigante tal que : Vamos imaginar, que uma roda leva 12 cadeiras igualmente espaçadas ao longo do seu perímetro, que o seu raio mede 10 metros e que o ponto mais baixo atingido ao longo do percurso círcular está a 0,5 metros do solo. Sabe-se também que uma roda demora cerca de 30 segundos a efectuar uma rotação completa.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
103
Com : h=10.sen(pt/15), t pertencente ao intrevalo fechado de [0,30]. Pergunta 7 (2 Valores) Implemente iterativamente o seguinte seguinte algoritmo (função) de cálculo de um factorial: funcao factorial (v: inteiro): inteiro
inicio
se v <= 2 entao
retorne v
senao
retorne v * factorial(v-1)
fimse
fimfuncao
Pergunta 8 (3 Valores) Explique o algoritmo de ordenação Bubble Sort, implemente o mesmo em raptor (Fluxograma) para uma ordenação crescente, partindo do princípio que a lista a ordenar está contida num array de nome LISTA e que tem n elementos.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
104
Teste Tipo Prática Pergunta 1 Implemente em linguagem Visual Raptor( ou em Fluxograma tradicional) e em linguagem C um algoritmo que permita estimar o valor do integral de uma função simples f(x): xx 23 2 − , no intervalo (0,3) usando a regra de integração numérica de Simpson. Notas para a implementação: A regra de Simpson usa rectângulos para aproximar a área (integral) no intervalo (a,b) de uma função f(x). A área de cada rectangulo é calculada usando como base a largura de cada rectangulo e como altura o valor da função f(x) calculada no ponto médio de cada rectângulo e no final é somado o conjunto das áreas. Este valor final é o valor aproximado do integral naquele intervalo.
Resposta
A regra de Simpson usa como forma de estimativa do valor de um integral, em dado intervalo, o calculo da área definida pela sub-divisão rectangular da mesma. Dado um intervalo de uma função f(x), o método subdivide o intervalo de integração em n sub-intervalos, calculando depois a área de cada sub-intervalo rectangular através da multiplicação da altura do mesmo pela largura de cada sub-divisão. A altura é dada pelo valor da função f(x) no ponto médio de cada sub-divisão, e a largura é dada pelo intervalo a dividir pelo numero de sub-divisões - n. Depois de calculadas todas as áreas o somatório destas é e estimativa de todo o integral no intervalo dado (área abaixo da função). É importante notar que quanto maior for o numero de subdivisões maior a precisão da área total obtida ( figura são usados 10 sub-divisões mas na implementação vamos usar 1024 para maior precisão).
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
105
8.1.3 Formulas importantes :
8.1.4 ∑=
−∆+∆n
iXXixEsquerdafX
1)2/*(*
Que pode ser re-escrita como:
∑=
−∆+−n
iXxEsquerdafnxEsquerdaxDireita11
))2/1((*/)(
Descrição dos termos:
8.1.5 N = numero de subintervalos no intervalo de integração
8.1.6 nxEsquerdaxDireitaX /)( −=∆ = Largura do subintervalo
8.1.7 )2/*( XXixEsquerdaf ∆−∆+ = Altura do subintervalo Implementação em Raptor
Start
a ← 1
b ← 2
n ← 1024
F_string ← "(3 * x * x - 2 * x)"
integrar_rect
PUT "Integrar "+F_string+" no intervalo de 0 a 2, então a
area= "+area¶
End
Quanto maior o numero de intervalos mais preciso o resultado
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
106
Start
xEsquerda ← a
xDireita ← b
nDivs ← n
area ← 0
deltax ← (xDireita - xEsquerda) / nDivs
midpointx ← xEsquerda + DeltaX / 2
i ← 0
i>=nDivs
x ← midpointx
area ← area + (3 * x * x - 2 * x) * deltax
midpointx ← midpointx + deltax
i ← i + 1
Calculo do acumulado e funciona como valor de retorno da função
End
Yes
No
Loop
Parâmetros passados para a função
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
107
Implementação em Linguagem C: /**********************************************************/ /* */ /* Autor: JM */ /* Data: 25 Janeiro, 2007 */ /* Disciplina: Introdução a Ciência dos Computadores */ /* Professor: Jorge Mota */ /* Descrição: Este programa integra uma função, embebida*/ /*No código e representada por F, no intervalo definido */ /*A a B usando a regra de Simpson. */ /* */ /**********************************************************/ #include <math.h> /* Usar a biblioteca matemática */ #include <stdio.h> #include <stdlib.h> #include <limits.h> #define SEED 5 /* Formula */ #define A 1.0 #define B 3.0 #define FORMULA (3 * x * x - 2 * x) #define F_STRING "(3 * x * x - 2 * x)" /* Esta é a função matemática a ser integrada. */ /* Tem uma variável x como entrada e devolve F(x). */ double f(double x) { return FORMULA; } /* Esta função integra f entre xEsquerda e xDireita usando a regra de simpson */ /* É feita uma divisão da função f em nDivs rectângulos */ /* e para cada rectângulo é calculada a área do mesmo usando como altura o ponto médio de cada sub-divisão. */ /* A função requer que no intervalo (xEsquerda e x Direita), calculemos o numero de divisões. */ /* O valor do integral no intervalo é o somatório das areas rectangulares. Quantas mais sub-divisões mais preciso é o resultado. */ double integrar_rect(double xEsquerda, double xDireita, double f(double), int nDivs) { int i; /* Variavel contadora */ double area = 0.0; /* area estimada */ double deltaX = (xDireita - xEsquerda)/nDivs; /* largura do Sub-divisão */ double midpointX; /* ponto medio */
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
108
midpointX = xEsquerda + deltaX/2.0; for (i = 0; i < nDivs; ++i) { area += f(midpointX) * deltaX; /* Acumula a área */ midpointX += deltaX; /* proximo rectangulo*/ } return area; } /* Main() é responsável por chamar o método que calcula a integração*/ /* e imprimir a area calculada */ int main(void) { int n; /* numero de rectangulos */ double s; /* area estimada pela regra de simpson */ srand(SEED); printf("\n"); printf("Integrar F(x) = %s de %5.3f to %5.3f\n", F_STRING, A, B); printf("\n"); s = integrar_rect(A, B, f, n); printf(" Regra de Simpson: Area com 1024 sub-intervalos = %9.6f\n", s); return 0; } Esta pergunta vale 20 valores em 20. Critérios para correcção: Se o aluno consegue descrever em português corrente os passos do algoritmo 10% Se aluno estrutura convenientemente o algoritmo em funções(Métodos e Constantes) 10% Se o aluno comenta correcta e completamente o código 10% Se o aluno define o algoritmo de integração correctamente, separando convenientemente variáveis, ciclo de calculo acumulado da área e impressão formatada do output em Raptor 30% Se o aluno define o algoritmo de integração correctamente, separando convenientemente variáveis, ciclo de calculo acumulado da área e impressão formatada do output em C 20% Se o Nome das variaveis está adequado a sua função e não gera confusão com nomes reservados 5% Se o algoritmo em Raptor funciona sem erros 10% Se o algoritmo em C funciona Correctamente 5%
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
109
Anexo: resolução da FREQUÊNCIA DE Janeiro de 2007
Licenciatura em Informática 1º Ano - 1º Semestre Introdução a Ciência dos Computadores – 1º Ano
Frequência - Resolução
Data : 5-02-2007 Duração : 60 Minutos Parte Teórica Prof. : Jorge Mota Numero : Nome : Pergunta 1 (2 valor) Explique o que é a Heap e a Stack num modelo de memória de uma linguagem de programação de alto nível como o C. Fale um pouco sobre a preocupação que deve ter com estas estruturas quando se usam ponteiros e alocação dinâmica de memória. Resposta: Uma arquitectura tradicional de memória para um programa em C, ou linguagens similares, inclui as seguintes áreas:
Heap Stack
Variaveis Globais Instruções Programa Em linguagens como o C podemos dinâmicamente alocar espaço na Heap, e usar este espaço para as nossas estruturas de dados. A gestão do espaço alocado fica da responsabilidade do programador que deve ter a responsabilidade de limpar (libertar) este espaço sempre que já não for necessário. Normalmente usa comandos de alocação dinâmica de espaço na
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
110
Heap, do tipo malloc(size). Este espaço é depois manipulado/ endereçado por estruturas tipo ponteiro. Se isto não acontece podemos criar situações de erro grave de sistema por falta de espaço, nomeadamente:
1) Quando a stack cresce e não dispõem de mais espaço. 2) Quando tentamos alocar mais espaço na Heap.
Esta é também uma fórmula comum de ataque aos programas, ficando o computador a mercê de um ataque de Hacker. A Stack é a área de memoria gerida pelo próprio programa, para as variaveis locais, parametros e outros. As variaveis globais e constantes usam o espaço reservado ao programa (no topo ou no inicio da memoria usada pelo programa). Pergunta 2 (2 valores) Implemente em VisualAlg e C um algoritmo que calcule os numeros primos até um determinado valor inteiro. Resposta: Um número primo é aquele que só é divisivel pela unidade e ele próprio. Se pretendemos imprimir a lista de numero primos até um valor, vamos fazer um ciclo que itera até este valor e para cada um testa se é primo (força bruta), se for é impresso senão passa ao seguinte. Para n=100 Temos a seguinte lista: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 Em VisulAlg: algoritmo "Primos" // Função : Calcular Primos // Autor : JM // Data : 23-02-2007 // Secção de Declarações var sai,i,j,n:inteiro inicio // Secção de Comandos escreva ("Ler quantos numeros(>4):") leia (n) escreval(2)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
111
escreval(3) para i<-4 ate n faca sai<-0 j<-2 enquanto (j<i) e (sai=0) faca se ((i%j)=0) entao sai<-1 senao j<-j+1 fimse fimenquanto se sai=0 entao escreval(i) fimse fimpara fim Em C: #include <stdio.h> void main(void) { int sai,i,j,n; printf("Numeros primos at-->"); scanf("%d",n); for(i=4;i<n;i++) { j=2; sai=0; while((j<i) && (sai==0)) { if (i%j==0) sai=1; else j=j+1; } if (sai==0) printf("\n%d ",i); } printf("\nTerminou o calculo"); } Pergunta 3 (2 valores) Na estruturação de algoritmos e implementação em linguagens de alto nível é comum decompormos o programa em problemas mais pequenos. A implementação destas unidades mais pequenas em linguagens como o C ou linguagens algoritmicas como o VisualAlg é feita sob a forma de funções ou
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
112
procedimentos. Explique como implementar em VisualAlg e C procedimentos e funções e como se processam os diversos tipos de passagens de parâmetros. Resposta: Quer o C quer o VisualAlg possuem Funções e Procedimentos e respectivas passagens de parãmetros por valor e referência. Usamos Funções sempre que pretendemos atomizar funcionalidades do nosso programa e que seja devolvido um valor. Em C isto é feito implicitamente designando o nome da <função>. Em VisualAlg 2.0 usamos a palavra reservada funcao. Para os procedimentos o C usa igualmente a forma implicita só que não é especificado nenhum tipo de dados a devolver - void. Já o visualAlg 2.0 utiliza a palavra reservada Procedimento. Todas estas construções suportam passagem de parãmetros por valor e referência ou seja no primeiro a variavel chamadora não é alterada e na segunda o que usamos é uma referência para a mesma memória onde está instanciada a variavél chamadora, quer dize,r é como usar um aliás para esta variavel. Sintaxe em VisualAlg:
funcao <nome-de-função> [(<seqüência-de-declarações-de-parâmetros>)]: <tipo-de-dado>
// Secção de Declarações Internas inicio // Secção de Comandos fimfuncao
procedimento <nome-de-procedimento> [(<seqüência-de-declarações-de-parâmetros>)] // Secção de Declarações Internas inicio // Secção de Comandos fimprocedimento
Passagem de parâmetros por referência (negrito) por valor a (italico):
procedimento soma (x,y: inteiro; var resultado: inteiro)
funcao soma (x,y: inteiro): inteiro
…
Em C:
Void nome(<tipo> var,<tipo> *var)
{
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
113
…
}
int nome(<tipo> var,<tipo> *var)
{
…
Return n
}
Pergunta 4 (3 Valores) a)Analise o seguinte algoritmo em VisualAlg 2.0 e escreva qual o resultado do mesmo para um numero de elementos igual a 12? b)Substitua a estrutura de controlo ENQUANTO () FAZER … FIMENQUANTO por uma REPETIR … ATE () . algoritmo "FIBO_ENQUANTO" // Autor :JORGE MOTA // Data : 29-01-2007 // Substituir um repetir por enquanto // Secção de Declarações var n,a,b,nFin: inteiro inicio // Secção de Comandos escreva("Numero de elementos:") Leia (nFin) n <- 0 a <- 0 b <- 1 enquanto (n<=nFin-2) faca escreval(a) escreval(b) n <- n + 2 a <- a + b b <- b + a
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
114
fimenquanto fimalgoritmo Resposta: a) n 0 2 4 6 8 10 12 a 0 1 3 8 21 55 144b 1 2 5 13 34 89 233N<=nFin-2 V V V V V V F Escreva a 0 1 3 8 21 55 Escreva b 1 2 5 13 34 89 Sequência Impressa: 0,1,1,2,3,5,8,13,21,34,55,89 b) algoritmo "FIBO_Repetir" // Autor :JORGE MOTA // Data : 23-02-2007 // Substituir um repetir por enquanto // Secção de Declarações var n,a,b,nFin: inteiro inicio // Secção de Comandos escreva("Numero de elementos:") Leia (nFin) n <- 0 a <- 0 b <- 1 repetir escreval(a) escreval(b) n <- n + 2 a <- a + b b <- b + a ate que (n>nFin-2) fimalgoritmo Pergunta 5 (3 valores) Desenvolva um algoritmo em Raptor (fluxograma) que permita converter uma string para maisculas e que tenham sido subtraídos os espaços a mais: Exemplo:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
115
esTe e um teste de algoritmia. ESTE E UM TESTE DE ALGORITMIA Nota : o underscore representa simbólicamente espaço. Resposta:
Start
"Ler Frase -->"GET Frase
comprimento ← Length_Of(Frase)
Frase_P ← ""
caracter ← ""
Flag ← 0
i ← 1
i>comprimento
c ← Frase[i]
c=32
(Flag=1) or (i=1)
Flag ← 1 caracter[1] ← c
Frase_P ← Frase_P + caracter
Flag ← 1
NoYes Flag ← 0
(c>=97) and (c<=122)
caracter[1] ← c - 32
Frase_P ← Frase_P + caracter
caracter[1] ← c
Frase_P ← Frase_P + caracter
NoYes
NoYes
i ← i + 1
PUT Frase_P¶
End
Yes
No
Loop
Pergunta 6 (3 valores)
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
116
Implemente em raptor (fluxograma) e em C um algoritmo que calcule a altura ao solo de um passageiro durante um passeio na roda gigante a partir do numero (inteiro) de cadeira que conta abaixo de si: Vamos imaginar, que uma roda leva 12 cadeiras igualmente espaçadas ao longo do seu perímetro, que o seu raio mede 10 metros e que o ponto mais baixo atingido ao longo do percurso círcular está a 0,5 metros do solo. Sabe-se também que uma roda demora cerca de 30 segundos a efectuar uma rotação completa.
Com : h=10.sen(α), t pertencente ao intervalo fechado de [0,30]. Resolução: Vamos considerar que o passageiro só conta as cadeiras de um dos lados. Assim temos o seguinte definição para o problema: Se o número de cadeiras é 0 então o passageiro esta a 0,5 m do solo. Se o número de cadeira é inferior a 3 então a altura aproximada é de h=10,5-(n)*10*sen(30). Se o número de cadeira é de 3 então a altura ao solo é de 10,5 m. Se o número esta entre 4 e 6 (ou seja 5) então h=10,5+n*10*sen(30). Se o número de cadeiras é de 7 então a altura é de 20,5 m ao solo.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
117
Pergunta 7 (2 Valores) Implemente iterativamente em fluxograma o seguinte seguinte algoritmo (função) de cálculo de um factorial: funcao factorial (v: inteiro): inteiro
inicio
se v <= 2 entao
retorne v
senao
retorne v * factorial(v-1)
fimse
fimfuncao
Resposta: Implementação em Fluxograma:
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
118
Start
n ← 10
factorial
End
Start
f ← 1
i ← n
i<1
f ← f * i
i ← i - 1
PUT "Factorial de"+n+" = "+f¶
End
Yes
No
Loop
Esta função é chamada com um parametro n, do tipo inteiro querepresenta o numero que se pretende calcular o factorial.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
119
Implementação em Linguagem C
#include "stdio.h"
int factorial(int n);
main()
{
int valor;
valor=factorial(10);
printf("O factorial de 10=%d\n",valor);
}
int factorial(int n)
{
int i,f;
f=1;
for(i=n;i>=1;--i)
{
f=f*i;
}
return f;
}
Pergunta 8 (3 Valores) Explique o algoritmo de ordenação Insertion Sort, implemente o mesmo em raptor (Fluxograma) para uma ordenação crescente, partindo do princípio que a lista a ordenar está contida num array de nome LISTA e que tem n elementos. Resposta:
Insertion sort, ou ordenação por inserção, é um algoritmo simples de ordenação, eficiente quando aplicado a um pequeno número de elementos. Em termos gerais, o que faz é percorrer um vector de elementos da esquerda para a direita e à medida que avança vai deixando os elementos mais à esquerda ordenados. O algoritmo de inserção funciona da mesma maneira como muitas pessoas ordenam cartas num jogo de cartas como o poquer.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
120
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
121
Anexo : Resolução da parte prática da frequência e exame de Janeiro/Fevereiro 2007
Engenharia Informática 1º Ano - 1º Semestre Introdução a Ciência dos Computadores – 1º Ano
Resolução parte prática da Frequência e exame.
Data : 5-02-2007 Duração : 60 Minutos Parte Prática Prof. : Jorge Mota Numero : Nome : Pergunta 1 Implemente em linguagem Visual Raptor( ou em Fluxograma tradicional) e em linguagem C um algoritmo que permita estimar o valor do integral de uma função simples f(x) exemplo: xx 23 2 − , no intervalo (1,3) usando técnica de integração de Monte Carlo. Notas para a implementação: ver descrição da técnica em abaixo.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
122
8.1.8 Formulas Importantes:
8.1.9 Área Total = M*(xEsquerda-xDireita)
8.1.10 A área abaixo de f(x) = Pr(Yaleatório<=f(Xaleatório))*M*(xDireita-xEsquerda)
8.1.11 Descrição dos termos da formula:
8.1.12 M = um valor y tal que M>=f(x) para todos os XEsquerda<=X>=Xdireita)
8.1.13 Yaleatório = Um Y aleatório escolhido de forma que 0<=Yaleatório<=M
8.1.14 Xaleatório = UmX aleatório de forma que xEsquerda<=Xaleatório<=xDireita
8.1.15 F(Xaleatório)=f(x) calculado no ponto Xaleatório
8.1.16 Pr(Yaleatório<=f(Xaleatório))= Probabilidade aleatória de o ponto estar abaixo de f(x)
A técnica de integração de Monte Carlo baseia-se na estimativa obtida pela teoria das probabilidades. Dado um intervalo (xEsquerda, xDireita) de uma função, f(x) que está limitada por uma constante M, o método de Monte Carlo aleatoriamente selecciona pontos dentro da “caixa” de restrições horizontal (intervalo de integração) e vertical (constante M) e determina se o ponto fica acima ou a baixo da função. A probabilidade de que o ponto esteja abaixo de f(x) é igual, na proporção da “caixa” de restrição, à probabilidade de estar acima de f(x). Quantos mais pontos forem escolhidos mais precisa a estimativa e portanto mais precisa a área final estimada.
Resposta
8.1.17
8.1.18 1) Especificar quantos numeros vão ser utilizados – n. No nosso caso vamos usar 1024.
2) Qual a função a usar. No nosso caso xx 23 2 − 3) Qual o valor de M, que deve ser maior que o maior valor da função para o intervalo de
integração.No nosso caso vamos usar 21.
8.1.19 4) Gerar numeros aleatórios na caixa de restrições que é imposta por: no eixo dos xx [ xEsquerda,xDireita] e em y por [0,21]
rx=(xDireita-xEsquerda)* random/(LONG_MAX))+xEsquerda ry=M*random()/(LONG_MAX) A constante LONG_MAX representa o máximo numero que pode ser gerado pelo random em raptor será igual a 1 e em gcc por exemplo está definida em limits.h 5)Iterar os 1024 pontos gerados aleatóriamente. No nosso caso implementado por um ciclo contado tendo o cuidado de para cada x e y gerado calcular o valor da função F(x) e verificar se é inferior ao Y gerado. No caso de ser incrementar o contador de pontos que depois nos irá permitir estimar a área. 6)Finalmente calcular a area pela proporção de numeros gerados que são inferiores a F(rx) relativamente a area da caixa de restrições.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
123
(contagem/nPontos)*(M*(xDireita-xEsquerda))
Implementação em Raptor: Programa principal, limita-se a inicializar variaveis e a chamar a função de cálculo pela técnica de integração de Monte Carlo(mc) e apresentar o valor calculado.
Start
LONG_MAX ← 1
M ← 21.0
A ← 1
B ← 3
nPontos ← 1024
MC
PUT "valor do integral para um calculo com 1024
pontos="+area¶
End
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
124
Função que implementa o calculo do integral pela técnica de integraçãode Monte Carlo (mc):
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
125
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
126
Finalmente o subprograma que implementa a função a integrar (Hardcoded):
Start
f_y ← 3 * x * x - 2 * x
End
Implementação em Linguagem C: /**********************************************************/ /* */ /* Autor: JM */ /* Data: 25 Janeiro, 2007 */ /* Disciplina: Introdução a Ciência dos Computadores */ /* Professor: Jorge Mota */ /* Descrição: Este programa integra uma função, embebida*/ /*No código e representada por F, no intervalo definido */ /*A a B usando a Técnica de Integração de Monte Carlo. */ /* */ /**********************************************************/ #include <math.h> /* Usar a biblioteca matemática */ #include <stdio.h> #include <stdlib.h> #include <limits.h> #define SEED 5 /* Formula */ /* #define A 1.0 #define B 3.0 #define M 21.0 #define FORMULA (3 * x * x - 2 * x) #define F_STRING "(3 * x * x - 2 * x)" */ /* Esta é a função matemática a ser integrada. */ /* Tem uma variável x como entrada e devolve F(x). */ double F(double x) { return FORMULA; } /* Esta função integra f entre xEsquerda e xDireita usando o método de integração de Monte Carlo */ /* É desenhado caixa usando os valores definidos pelo intervalo xEsquerda e xDireita e o minimo e máximo como base e topo do mesmo.
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
127
Para o valor máximo devemos estimar um valor adequado de acordo com a gráfico da função. */ /* São gerados pontos aleatóriamente dentro desta caixa de valores e determinado se o valor gerado se encontra acima ou abaixo da função F */ /* A fracção de pontos gerados abaixo da função é a mesma que a fracção da área da caixa abaixo da função ou seja o valor do integral da mesma no intervalo considerado. Esta consideração só é valida para um numero significativo de pontos*/ /*ATENÇÃO estamos a considerar que a constante LONG_MAX é o máximo valor possivel de ser gerado pela função rand(). Está sempre dependente do compilador. Neste caso consideramos que está definida em limits.h (gcc) */ double integrar_mc(double xEsquerda, double xDireita, double f(double), int nPontos, double M) { int i; /* Variavel contadora */ int contagem=0; /* Numero de ponto de abaixo da função*/ double rx; /* valor aleatório x no intervalo de valores da caixa*/ double ry; /* valor aleatório y no intervalo de valores da caixa*/ double f_y; /*valor de y= valor da função no ponto aleatório rx*/ for (i=0; i<nPontos;++i) { /*Escolher um pontos aleatório na caixa de valores. Os valores rx e ry devem escolhidos independentemente*/ rx=(xDireita-xEsquerda)* rand()/((double) (LONG_MAX))+xEsquerda); ry=M*rand()/((double) (LONG_MAX)); /* verificar se o ponto está abaixo da função*/ f_y=F(rx); if (ry<f_y) contagem++; } return (contagem/((double)(nPontos))*(M*(xDireita-xEsquerda))); } /* Main() é responsável por chamar o método que calcula a integração*/ /* e imprimir a area calculada */ int main(void) { int n; /* numero de pontos */ double mc; /* area estimada pela técnica de Monte Carlo */ srand(SEED); printf("\n"); printf("Integrar F(x) = %s de %5.3f to %5.3f\n", F_STRING, A, B); printf("\n"); n=1024; printf("n = %d\n", n);
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
128
mc = integrar_mc(A, B, F, n,M); printf("Método Monte Carlo: Area com n pontos = %9.6f\n", mc); return 0; } Esta pergunta vale 20 valores em 20. Critérios para correcção: Se o aluno consegue descrever em português corrente os passos do algoritmo 10% Se aluno estrutura convenientemente o algoritmo em funções(Métodos e Constantes) 10% Se o aluno comenta correcta e completamente o código 10% Se o aluno consegue especificar a forma de calculo dos numeros gerados aleatóriamente na caixa de restrições 10% Se o aluno define o algoritmo de integração correctamente, separando convenientemente variáveis, ciclo de calculo acumulado da área e impressão formatada do output em Raptor 20% Se o aluno define o algoritmo de integração correctamente, separando convenientemente variáveis, ciclo de calculo acumulado da área e impressão formatada do output em C 20% Se o Nome das variaveis está adequado a sua função e não gera confusão com nomes reservados 5% Se o algoritmo em Raptor funciona sem erros 10% Se o algoritmo em C funciona Correctamente 5%
Apontamentos de Apoio às aulas de Algoritmia do Professor Jorge Mota 2006
129
9 Bibliografia
[1] Rocha, António Adrego da, Introdução à Programação usando C ,
(FCA, 2006).
[2] Schildt, Herbert, C Completo e Total, (Osborne, 1997).
[3] Standish, Thomas A, Algorithms and Software Principles, (Addison-
Wesley, 1995).
[4] Souza, Cláudio Morgado, Manual do VisualAlg v2, (2006).
[5] http://www.apoioinformatica.inf.br/