Anda di halaman 1dari 10

Notas de Aula de o de Computadores Algoritmos e Programac a

F L AVIO K EIDI M IYAZAWA com a colaborac a o de T OMASZ KOWALTOWSKI

Instituto de Computac a o - UNICAMP

Vers ao 2000.1

Estas notas de aula n ao devem ser usadas como u nica fonte de estudo. O aluno deve ler outros livros dispon veis na literatura. Nenhuma parte destas notas pode ser reproduzida, qualquer que seja a forma ou o meio, sem a permiss ao dos autores. Os autores concedem a permiss ao expl cita para a utilizac a o e reproduc a o deste material no contexto do ensino de disciplinas regulares dos cursos de graduac a o sob a responsabilidade do Instituto de Computac a o da UNICAMP.

c Copyright 2000

Instituto de Computac a o UNICAMP Caixa Postal 6176 13083970 CampinasSP fkm,tomasz @ic.unicamp.br

ii

es e procedimentos como par 12 Passagem de func o ametros


A linguagem pascal permite passar rotinas como par ametros. Isto nos possibilita fazer rotinas focalizadas em um m etodo de forma bem mais gen erica usando rotinas particulares para cada tipo de dado, que s ao passadas como par ametros. Mas antes de apresentar a sintaxe destas declarac o es de par ametros, precisamos fazer algumas observac o es entre dois dos principais padr oes da linguagem Pascal: o do Pascal Extendido e o Borland Pascal. Existem algumas diferenc as entre estes dois padr oes e a passagem de func o es e procedimentos como par ametros e uma delas.

12.1

Diferenc as entre Borland/Turbo Pascal e Extended Pascal

Borland Pascal O padr ao Borland Pascal apresenta declarac a o de novos tipos associados a procedimentos ou func o es, mas n ao aceita a descric a o do tipo do procedimento ou func a o na declarac a o do par ametro. Assim, para declarar um par ametro que e um procedimento ou func a o precisamos primeiro denir tipos associados a estas rotinas e s o depois declarar as rotinas como par ametros usando estes tipos. type IdenticadorTipoFuncao = function(Lista de Par ametros): Tipo Retorno Func a o; IdenticadorTipoProcedure = procedure(Lista de Par ametros); O tipo da rotina e igual a declarac a o do cabec alho da rotina, tirando o identicador da rotina. Com isso, podemos declarar um par ametro que e uma rotina como um par ametro normal. Obs.: No Turbo Pascal e necess ario colocar a opc a o de func es e procedimentos com enderec amento far (Opti o a o das rotinas. No Free Pascal ons, Compiler, Force Far Calls: On) ou colocar a diretiva $F+ antes da declarac e necess ario compilar o programa com a opc a o de -So na linha de comando. Extended Pascal O padr ao Extended Pascal n ao apresenta declarac a o de novos tipos como sendo procedimentos ou func o es. Estes par ametros devem ser declarados diretamente na declarac a o do par ametro. As sintaxes das declarac o es de par ametro como procedimento ou func a o e a mesma que a usada nos cabec alhos de func o es. Exemplo: procedure P(function F(x: real): real); No cabec alho do procedimento P, temos a declarac a o de um par ametro chamado F que e uma func a o. F e uma func a o que tem um par ametro real e retorna um valor real. O padr ao do pascal extendido (Extended Pascal standard) foi completado em 1989 e e tanto um padr ao ANSI/IEEE como ISO/IEC. Exemplo 12.1 No exemplo das guras 38 e 39, temos um procedimento chamado imprime, com 4 par ametros: dois n umeros reais ( e ), uma func a em os dois o (fun) e uma string (msg). O procedimento imprime um texto que cont valores reais e o resultado da chamada da func a umeros. Note que esta rotina poderia ter sido o sobre estes dois n chamada com qualquer func a ametros com valores reais e retorna um valor real. No caso, a rotina o que tem dois par imprime foi chamada com as func o es maximo, minimo e media. Note que na declarac a ametros. A declarac a o, foram colocados identicadores associados aos par o destes tipos necessita que tenhamos identicadores, mas seu nome n ao precisa estar associado aos nomes dos identicadores na descric a o da rotina. A traduc a o de programas escritos em Extended Pascal para Borland Pascal e simples, uma vez que precisamos apenas mudar a declarac a o de rotinas que s ao par ametros, de forma a usar tipos. J a a traduc a o de um programa escrito em Borland Pascal para Extended Pascal pode ser mais complicada, se aquele usar os tipos de rotinas dentro de estruturas como vetores e registros. A partir de agora usaremos apenas uma destas sintaxes. Escolhemos a sintaxe do Borland Pascal, uma vez que esta sintaxe pode ser usada na maioria dos compiladores Pascal, tais como: Turbo Pascal (vers ao 5 em diante), Borland Pascal, Delphi, gpc (Gnu Pascal Compiler) e Free Pascal. Acreditamos que futuras padronizac o es da linguagem Pascal venham a contemplar este tipo de sintaxe. 115

program ParametroFuncaoBorlandPascal; type TipoFuncao function(a,a : real):real; TipoMsg string[100]; function maximo(a,b : real):real; begin if (a b) then maximo : a else maximo : b; end; function minimo(a,b : real):real; begin if (a b) then minimo : b else minimo : a; end; function media(a,b : real):real; begin media : (a b)/2; end; procedure imprime(a,b : real; fun: tipoFuncao; msg : TipoMsg); begin writeln(msg, de ,a:7:2, e ,b:7:2, e: , fun(a,b):7:2); end; var n1,n2 : real; begin write(Entre com dois n umeros: ); readln(n1,n2); imprime(n1,n2,maximo,O m aximo); imprime(n1,n2,minimo,O m nimo); imprime(n1,n2,media,A m edia); end.

program ParametroFuncaoExtendedPascal; type TipoMsg string[100]; function maximo(a,b : real):real; begin if (a b) then maximo : a else maximo : b; end; function minimo(a,b : real):real; begin if (a b) then minimo : b else minimo : a; end; function media(a,b : real):real; begin media : (a b)/2; end; procedure imprime(a,b : real; function fun(a,a : real):real; msg : TipoMsg); begin writeln(msg, de ,a:7:2, e ,b:7:2, e: , fun(a,b):7:2); end; var n1,n2 : real; begin write(Entre com dois n umeros: ); readln(n1,n2); imprime(n1,n2,maximo,O m aximo); imprime(n1,n2,minimo,O m nimo); imprime(n1,n2,media,A m edia); end.

Figura 38: Exemplo de rotinas como par ametros em Bor- Figura 39: Exemplo de rotinas como par ametros em Exland Pascal tended Pascal

116

12.2

o para encontrar ra es M etodo de bissec a zes de func o

Um m etodo para encontrar soluc o es de uma func a o e atrav es do m etodo de bissec a o. Para usar estes m etodo devemos ter:

# $%%&

Uma func a o  para poder calcular um valor de  tal que  Um intervalo de busca da soluc a o

"!

. .

# $%%& , de tal forma que '(0)123546!

Note que o segundo item nos garante que ou e soluc a o, ou e soluc a o ou deve existir uma soluc a o  no intervalo tal que    7! (veja a gura seguinte).
f(x)

f(a) a f(b) m b x

A id eia e dividir este intervalo em duas partes pelo meio, 8 , digamos das condic o es seguintes: 1. 2.

# 9$@8A& e # 8B$%%& . Devemos ter pelo menos uma

'C0)D8EF46! 8E0)G23F46!
.

Se 'CH)98EI4P! ent ao necessariamente temos uma soluc a o dentro do intervalo # $@8A& e repetimos o mesmo ario, teremos uma soluc a o processo, desta vez interando com o intervalo # 9$@8A& no lugar do intervalo # $%%& . Caso contr dentro do intervalo # 8B$%%& e continuamos o processo neste intervalo. A cada interac a o o tamanho do intervalo diminui para metade do tamanho do intervalo anterior. Assim, o processo pode parar quando o comprimento do intervalo for sucientemente pequeno. Com isto, podemos escrever uma rotina que encontra uma soluc a o para uma certa func a o (recebida pela rotina como par ametro) e o intervalo de atuac a o. alido tal que '(Q)G2354R! . Para encontrar tal intervalo, O m etodo de bissec a o j a pressup oe um intervalo # 9$%%& v podemos comec ar com um intervalo sucientemente grande #  $SUT1& , dividimos este intervalo em partes pequenas, digamos em V partes iguais, #  $SXW@& , # 9W$S`Ya& , b3b3b , # `TGc W $SUT1& e vericamos se algum destes intervalos digamos # Ud c W3$SUd& , egf ih tal que ' d )%' dqp0W F4r! . Caso exista tal intervalo, usamos o m etodo da bissec a o no intervalo, caso $3b3b3bG$%V e contr ario terminamos sem sucesso. Naturalmente podem ocorrer inst ancias onde este m etodo n ao encontra soluc o es, mesmo que tal soluc a o se encontre em um dos intervalos iniciais. Al em disso, dicilmente este m etodo ir a encontrar soluc o es de func o es n ao negativas ou n ao positivas. O programa a seguir apresenta a implementac a o do m etodo descrito acima.

117

program ProgramaBicessao; const EPS 0.000000001; type TipoFuncaoReal function (x:real):real; Encontrando o intervalo, retorna sucesso true e a0 e ak atualizados com o intervalo, caso contr ario, retorna com sucesso false procedure EncontraIntervalo(f: TipoFuncaoReal ; var a0,ak: real;k:integer; var sucesso: boolean); var delta,a: real; begin a: a0; delta : (ak s a)/k; while (a t ak) and (f(a) u f(a delta) 0) do a : a delta; if (f(a) u f(a delta) 0) then sucesso : false else begin a0 : a; ak : a delta; sucesso : true; end; end; Encontrando soluc a o, retorna sucesso true e a raiz em soluc a o, cc. sucesso false procedure bicessao(f: TipoFuncaoReal; a,b:real; var sucesso:boolean;var solucao:real); var m : real; begin EncontraIntervalo(f,a,b,1000,sucesso); if (sucesso) then begin while (abs(a s b) EPS) do begin m : (a b)/2; if (f(a) u f(m) tH 0) then b: m else a: m; end; solucao : m; end; end; func a o real: f(x) x3 2.x2 s x 10 function f1(x : real):real; begin f1 : x u x u x 2 u x u x s x 10; end; f1

func a o real: f(x) (x s 5) u (x s 2) u (x s 3) u (x s 4) u (x s 6) function f2(x : real):real; begin f2 : (x s 5) u (x s 2) u (x s 3) u (x s 4) u (x s 6); end; f1

var sucesso : boolean; raiz: real; begin bicessao(f1, s 10,10,sucesso,raiz); if (sucesso) then writeln(Uma soluc ao de f(x)=x3+2.x2x+10 e: , raiz:10:8); bicessao(f2, s 10,10,sucesso,raiz); if (sucesso) then writeln(Uma soluc ao de , f(x)=(x-5)*(x-2)*(x-3)*(x-4)*(x6) e: , raiz:10:8); end.

118

Exerc cio 12.1 (Integral de func o alculo da integral de uma curva denida pode ser calculado por aproximac o es) O c es utilizando-se o m etodo dos trap ezios. Neste m etodo dividimos o intervalo de integrac a o em v partes iguais, digamos divididas pelos pontos   $@wW$3b3b3bG$@9x e calculamos a h a ezio substituindo a curva em cada intervalo 9d c W3$@9d e rea do trap $3b3b3b1$@v (veja a gura seguinte). O valor aproximado da integral por uma reta ligando os pontos d c W% e 9dy , denida e ezios. a soma das a reas dos v trap



dP

   x

x d$ onde dq0WC d c Ww69dy )G0$ Fs ds9d c Wg v Gb

$3b3b3b1$@v

Area de cada trap ezio

A1

A2

A3

A4

A5

a a um programa contendo uma func a Naturalmente, quanto maior o valor de v , melhor a aproximac o da integral. Fac o chamada integral com o seguinte cabec alho: function integral(f: TipoFuncaoReal; a,b: real; n: integer): real; onde TipoFuncaoReal e a ao; os valores e denem o um tipo de func o como declarado como programa de bicess intervalo de integrac a etodo de aproximac o o: # 9$%%& ; e o valor v indica a quantidade de intervalos a ser usado no m es.

x0

x1

x2

x3

x4

x5

12.3

o usando func es de comparac o Ordenac a o a

No exemplo 6.9 vimos como podemos ordenar um vetor colocando na posic a o correta o maior elemento n ao considerado a cada instante. Note que o algoritmo faz a selec a o do maior elemento fazendo v arias comparac o es entre dois elementos (se menor, igual ou maior). Em muitos problemas, cada elemento do vetor cont em informac o es de um objeto que cont em em geral v arias caracter sticas e estes podem ser ordenados de v arias maneiras, dependendo das caracter sticas consideradas. Por exemplo, vamos considerar que uma universidade, chamada UNICOMP, armazena os dados dos alunos usando o tipo TipoAluno, apresentado na p agina 90. Por simplicidade, vamos considerar os campos Nome, DataNascimento e CR. Para efeitos de busca e classicac a o, a universidade necessita que estes dados possam estar em ordem alfab etica pelo nome ou listados pelos alunos mais novos primeiro ou listados ordenados pelo CR em ordem decrescente. Como e apenas a comparac a o entre elementos que muda, podemos fazer apenas uma rotina de ordenac a o e usar diferentes func o es de comparac a o para decidir qual aluno vem antes de outro. A func a o para comparar dois elementos tem o seguinte formato: function Compara(var , : TipoAluno):char; a func a o retorna t , ou , se e menor, igual ou maior que , respectivamente. A seguinte func a o compara os nomes de dois alunos: function ComparaNome(Aluno1,Aluno2 : TipoAluno):char; var Nome1,Nome2 : TipoNome; begin if (Aluno1.Nome t Aluno2.Nome) then ComparaNome : < else if (Aluno1.Nome Aluno2.Nome) then ComparaNome : > else ComparaNome : =; end; 119

A seguir, vamos descrever a nova rotina de ordenac a o (atualizada a partir do exemplo 7.13) que pode usar a func a o de comparac a o por nome, dado acima. const MAX 100; type ss Incluir tipos em TipoAluno tss TipoVetorAluno array[1..MAX] of TipoAluno; TipoFuncaoComparacao function (a,b: TipoAluno):char; procedure SelectionSortAluno(fcomp: TipoFuncaoComparacao; var v : TipoVetorAluno; n:integer); var m,imax : integer; procedure TrocaAluno(var Aluno1, Aluno2 : TipoAluno); var AlunoAux : TipoAluno; begin AlunoAux: Aluno1; Aluno1: Aluno2; Aluno2: AlunoAux; end; function IndMaxAluno(fcomp : TipoFuncaoComparacao; var v:TipoVetorAluno; n:integer):integer; var i, Ind : integer; begin if (n tH 0) then Ind : 0 else begin a com o primeiro elemento do vetor Ind : 1; O maior elemento comec for i: 2 to n do if (fcomp(v[Ind],v[i]) <) then Ind: i; end; IndMaxAluno : Ind; end; begin for m: n downto 2 do begin imax : IndMaxAluno(fcomp,v,m); TrocaAluno(v[m],v[imax]); end; end; Note que a mudanc a (al em do tipo de dado) do programa apresentado no exemplo 6.9 est a no uso da func a o de comparac a o entre dois elementos, que e um par ametro usado na chamada da rotina SelectionSortAluno. Assim, a chamada da rotina SelectionSortAluno(ComparaAluno, V, n) far a a ordenac a o do vetor , com v elementos, usando a func a o de comparac a o ComparaAluno. I.e., o vetor car a em ordem alfab etica pelo nome. Agora, para fazer a ordenac a o em ordem crescente de idade (mais novos primeiro), podemos usar o mesmo programa usando apenas uma func a o de comparac a o diferente. Mas note que agora queremos os de maior data de nascimento primeiro. Para isso, vamos tapear a rotina de ordenac a o, usando uma func a o de comparac a o que responde dizendo que o aluno menor ( t ) que o aluno Y se a data de nascimento de W for na verdade maior que a de Y , e vice versa. Isto W e a com que a rotina ordene de maneira invertida. Lembre que a rotina de ordenac de maneira que os far a o foi feita menores cassem nas primeiras posic o es; assim, se usamos a rotina de comparac a o que diz que um elemento e menor quando na verdade e maior, e vice-versa, obteremos uma ordenac a o com os maiores nas primeiras posic o es. A rotina de comparac a o de alunos por data de nascimento (mais novos primeiro) pode ser dada pela seguinte func a o: function ComparaIdade(Aluno1,Aluno2 : TipoAluno):char; begin if (Aluno1.DataNascimento.Ano t Aluno2.DataNascimento.Ano) then ComparaIdade : > else if (Aluno1.DataNascimento.Ano Aluno1.DataNascimento.Ano) then ComparaIdade : < else if (Aluno1.DataNascimento.Mes t Aluno1.DataNascimento.Mes) then ComparaIdade : > else if (Aluno1.DataNascimento.Mes Aluno1.DataNascimento.Mes) then ComparaIdade : < else if (Aluno1.DataNascimento.Dia t Aluno1.DataNascimento.Dia) then ComparaIdade : > else if (Aluno1.DataNascimento.Dia Aluno1.DataNascimento.Dia) then ComparaIdade : < else ComparaIdade : =; end; Note tamb em que o uso da func a o de comparac a o permite fazer comparac o es de elementos levando em considerac a o v arios dados para desempate. O programa nal e dado a seguir.

120

program OrdenaAlunoIdadeNome; const MAX 100; type ss Incluir tipos em TipoAluno tss TipoVetorAluno array[1..MAX] of TipoAluno; TipoFuncaoComparacao function (a,b: TipoAluno):char; function ComparaNome(Aluno1,Aluno2 : TipoAluno):char; var Nome1,Nome2 : TipoNome; begin if (Aluno1.Nome t Aluno2.Nome) then ComparaNome : < else if (Aluno1.Nome Aluno2.Nome) then ComparaNome : > else ComparaNome : =; end; ComparaNome function ComparaIdade(Aluno1,Aluno2 : TipoAluno):char; begin Inserir c odigo da func a o ComparaIdade, visto anteriormente. end; procedure SelectionSortAluno(fcomp: TipoFuncaoComparacao; var v : TipoVetorAluno; n:integer); var m,imax : integer; procedure TrocaAluno(var Aluno1, Aluno2 : TipoAluno); var AlunoAux : TipoAluno; begin AlunoAux: Aluno1; Aluno1: Aluno2; Aluno2: AlunoAux; end; function IndMaxAluno(fcomp : TipoFuncaoComparacao; var v:TipoVetorAluno; n:integer):integer; var i, Ind : integer; begin if (n tH 0) then Ind : 0 else begin a com o primeiro elemento do vetor Ind : 1; O maior elemento comec for i: 2 to n do if (fcomp(v[Ind],v[i]) <) then Ind: i; end; IndMaxAluno : Ind; end; begin for m: n downto 2 do begin imax : IndMaxAluno(fcomp,v,m); TrocaAluno(v[m],v[imax]); end; end; procedure ImprimeVetorAluno(var v : TipoVetorAluno; n:integer; msg:TipoString); cio: Rotina para imprimir os Alunos na tela end; begin Exerc procedure LeVetorAluno(var v:TipoVetorAluno;var n:integer); cio: Rotina para ler Alunos end; begin Exerc var i, n, Ind : integer; V : TipoVetorFunc; begin LeVetorAluno(V,n); SelectionSortFunc(comparaNome,v,n); ImprimeVetorFunc(v,n,Ordenados por nome (ordem alfab etica) ); SelectionSortFunc(comparaIdade,v,n); ImprimeVetorFunc(v,n,Ordenados por idade (mais novos primeiro) ); end.

121

Exerc cio 12.2 A universidade UNICOMP deseja dar bolsas de estudo para os alunos que apresentam melhores valores do Coeciente de Rendimento (CR). Assim, fac a uma func a a o de comparac o para ordenar os alunos, colocando os de maiores valores do CR primeiro. Caso dois alunos possuam o mesmo valor de CR, estes devem ser desempatados pelo RA.

12.4

Exerc cios

dado uma func 1. E a o redf e um intervalo # $%%& tal que 'Cg)h23itj! . Fac a uma func a o recursiva que f # $%%& usando o m etodo da bissec a o (dividindo sucessivamento o intervalo ao meio) encontra uma soluc a o  h tal que kj! . A func a o pode dar o resultado dentro de uma precis ao de !C$S!h!h! (diferenc a entre a soluc a o verdadeira e a soluc a o encontrada pela rotina) e deve ter o seguinte cabec alho: function Bissecao( : TipoFuncao; $% : real): real; onde e a func a o para a qual calcularemos a soluc a o e # $%S& dene o intervalo que cont em a soluc a o. O tipo TipoFuncao e denido como: type TipoFuncao = function (x:real):real; 2. Para calcular a integral l7m

 i

pode-se usar a aproximac a o de uma soma nita de valores amostrados:

lTnpoq52rtsi W Y usirvg DwgR)3)3)rtsi x c v x c Y usi x c W x  e Ddw7'n $ x25sC@yGv$zvE T b o o h O n umero de pontos de amostragem e v{ e e a dist ancia entre dois pontos de amostragem adjacentes. O o valor l da integral e aproximado pela seq ue ncia l0W3$lYr$l v $3b3b3b , que converge se a func a o e sucientemente bem
comportada (suave). O m etodo acima e chamado de m etodo de Simpson. etodo de Simpson. A func a o tem Escreva uma func a o que calcule a integral de uma func a o  usando o m a o # $%%& e o valor V . A func a o retorna a aproximac a o da como par ametros: a func a o  , o intervalo de integrac a o para calcular as integrais: integral de | no intervalo # 9$%%& . Aplique sua func onde

Y  Y  

{}r~ Y zw|  

3. Fac a um programa para manipular um cadastro de alunos, nos moldes do exemplo da sec a o 12.3, de maneira a ter as seguintes opc o es: (a) Iniciar cadastro vazio (inicialmente o cadastro j a comec a vazio (n umero de elementos igual a zero)). (b) Inserir um novo elemento no cadastro (se o cadastro estiver cheio, avise que n ao h a mem oria dispon vel). (c) Ordenar o cadastro por nome em ordem alfab etica. (d) Ordenar o cadastro por idade, mais novos primeiro. (e) Ordenar o cadastro por idade, mais velhos primeiro. (f) Ordenar o cadastro por RA, ordem crescente. (g) Ordenar o cadastro por CR, maiores primeiro. Sempre que o programa executar alguma destas opc o es, ele deve imprimir a lista de alunos na ordem do vetor e imprimir logo em seguida o menu antes de pedir por nova opc a o. Al em disso, o programa deve usar apenas de uma rotina de ordenac a o para ordenar os alunos. Os diferentes tipos de ordenac a o s ao denidos usando func o es de comparac a o espec cas para cada tipo de ordenac a o que devem ser passadas como par ametros da rotina de ordenac a o.

122

Anda mungkin juga menyukai