Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Algoritimos, Notas de estudo de Algoritmos

Apostila de um professor da UFLA que contém vários tópicos sobre algoritimos.

Tipologia: Notas de estudo

Antes de 2010

Compartilhado em 20/05/2010

vinicius-maretti-2
vinicius-maretti-2 🇧🇷

5

(2)

1 documento

1 / 22

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Universidade Federal de Lavras
Departamento de Ciência da Computação
APOSTILA DE AEDII
Autores
Antônio Maria Pereira de Resende Heitor Augustus Xavier Costa
Maurício A. Dias Gustavo Araújo
Abril de 2007
Lavras-MG
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16

Pré-visualização parcial do texto

Baixe Algoritimos e outras Notas de estudo em PDF para Algoritmos, somente na Docsity!

Universidade Federal de Lavras

Departamento de Ciência da Computação

APOSTILA DE AEDII

Autores

Antônio Maria Pereira de Resende Heitor Augustus Xavier Costa

Maurício A. Dias Gustavo Araújo

Abril de 2007 Lavras-MG

Í NDICE

  • 1 Introdução a Complexidade de Algoritmos.........................................................
  • 1.1 Introdução.............................................................................................................
  • 2 Algoritmos de Busca em Vetor............................................................................
  • 2.1 Introdução.............................................................................................................
  • 2.2 Busca Seqüencial
  • 2.2.1 Complexidade do algoritmo..................................................................................
  • 2.3 Busca Binária........................................................................................................
  • 2.3.1 Complexidade do algoritmo..................................................................................
  • 2.4 Critérios para Escolha do Algoritmo.....................................................................
  • 2.5 Exercícios Resolvidos...........................................................................................
  • 2.6 Exercícios Propostos.............................................................................................
  • 3 Algoritmos de Ordenação....................................................................................
  • 3.1 Introdução.............................................................................................................
  • 3.2 Ordenação por Seleção (Select Sort)....................................................................
  • 3.2.1 Complexidade do algoritmo..................................................................................
  • 3.3 Ordenação por Inserção (Insert Sort)....................................................................
  • 3.3.1 Complexidade do algoritmo..................................................................................
  • 3.4 Ordenação por Bolhas (Bouble Sort)
  • 3.4.1 Complexidade do algoritmo..................................................................................
  • 3.5 Ordenação Por Fusão (Merge Sort)......................................................................
  • 3.5.1 Complexidade do algoritmo..................................................................................
  • 3.6 Ordenação Rápida (Quick Sort)............................................................................
  • 3.6.1 Complexidade do algoritmo..................................................................................
  • 3.7 Critérios para Escolha do Algoritmo.....................................................................
  • 3.8 Exercícios Resolvidos...........................................................................................
  • 3.9 Exercícios Propostos.............................................................................................
  • 3.10 Exercícios/Trabalhos.............................................................................................
  • 3.11 Referências............................................................................................................

Existem várias maneiras de se medir a complexidade de um algoritmo, duas medidas básicas utilizadas são: tempo e espaço. A complexidade de espaço é medida através da quantidade de memória necessária para a execução do programa, por exemplo se a estrutura critica for um vetor, um algoritmo que utilize dois vetores terá complexidade de espaço 2n. Geralmente utiliza-se a complexidade de tempo para comparar algoritmos já que hoje em dia o espaço não é tão problemático quanto o tempo de execução. A complexidade de tempo de um algoritmo é medida pelo número de vezes que ele executa uma operação critica definida pelo usuário. Apesar de existirem várias notações de complexidade definiremos apenas O,Ω,Θ pois estas são suficientes para o que precisamos. Antes de começarmos as definições de notação, precisamos definir dominação assintótica. A definição de dominação assintótica é a seguinte: uma função g(n) domina assintoticamente outra função f(n) se existem duas constantes C e M tais que , para todo n >= M, temos |g(n)| <= C x |f(n)|, ou seja, uma função domina assintoticamente outra se após um determinado ponto m, a função multiplicada por uma constante é sempre maior que a outra. A figura abaixo exemplifica a situação:

1.3.1 Notação O(f(n)) – Big-O Esta notação é a mais comum quando se estuda complexidade. A definição utiliza a definição de dominação assintótica citada acima. A definição da notação é a seguinte: Uma função g(n) é O(f(n)) se existem constantes positivas c e m tais que g(n) <= c x f(n) para todo n >= m. Isso quer dizer que quando uma função complexidade de um algoritmo é O(f(n)), f(n) domina assintoticamente a função do algoritmo. Existem algumas classes de problemas que são as seguintes:

  • f(n) = O(1) – Complexidade constante, ou seja, independe do tamanho da entrada n. As instruções são executadas um numero fixo de vezes.
  • f(n) = O(log n) – Complexidade sub-linear ou logarítmica, ocorre geralmente em problemas que dividem-se em problemas menores em sua resolução.
  • f(n) = O(n) – Complexidade linear, ou seja, quando um pequeno trabalho é realizado sobre os elementos de entrada n. Esta situação é boa para algoritmos que tenham entrada e saída n.
  • f(n) = O(n log n) – Esta complexidade geralmente acontece com algoritmos que separam o problema em menores e unem as resoluções depois de encontrá-las.
  • f(n) = O(n^2) – Complexidade quadrática, ou seja, quando itens são processados aos pares, geralmente quando temos um anel dentro do outro.
  • f(n) = O(2^n) – Complexidade exponencial. São algoritmos péssimos em ponto de vista pratico. Geralmente são algoritmos utilizados para resolução de problemas na força bruta.
  • f(n) = O(n!) – Complexidade fatorial. Também classificados como exponenciais são algoritmos piores ainda que os apresentados acima. Péssimos na prática e resultado de aplicação da força bruta, não são recomendados para resolução de problemas.

A complexidade de um algoritmo pode ser avaliada ainda de três formas diferentes com relação à entrada dos dados. Existem três casos diferentes de entrada que são os seguintes:

  1. Melhor caso : ocorre quando a entrada de dados favorece a operação que deve ser feita, ocasionando assim em menos trabalho por parte do algoritmo.
  2. Pior caso : ocorre quando a entrada de dados está na pior forma possível fazendo com que o algoritmo trabalhe o máximo possível
  3. Caso médio ou Caso esperado : é calculado com a média ponderada entre as entradas possíveis multiplicadas por suas respectivas probabilidades de ocorrência. Geralmente, o caso estudado é o pior caso pois nem sempre temos o caso esperado e o melhor caso também tem uma probabilidade muito pequena de acontecer além do fato de que para a comparação o importante é sabermos qual a complexidade do caso que exige mais do algoritmo. A tabela de classes de problemas acima está ordenada de maneira crescente. Para podermos comparar dois algoritmos, primeiramente precisamos saber a qual classe pertencem os algoritmos. Se forem de classes diferentes a comparação fica fácil seguindo a ordem acima, porém se encontrarmos algoritmos que são da mesma classe de problemas, estes devem ser comparados por suas funções reais de complexidade de tempo, ou até mesmo por sua complexidade de espaço lembrando que o caso relacionado à complexidade deve ser o mesmo, ou seja, não devemos comparar pior caso de um algoritmo com o melhor caso de outro.

1.3.2 Notação Ω(f(n)) A notação Ω é a notação inversa da notação O, pois delimita uma cota assintótica inferior. Podemos então definir Ω como: uma função g(n) é Ω (f(n)) se existem constantes positivas c e m tais que g(n) >= c x f(n) para todo n >= m. Existe uma pequena diferença entre as duas notações que é a seguinte, se dizemos que um algoritmo é Ω (f(n)) simplesmente ele segue a definição acima, porém quando dizemos que um algoritmo é Ω (f(n)) associado a um problema, por exemplo no caso de ordenação por comparação, definimos o limite inferior matematicamente provado do problema associado a afirmação.

1.3.4 Notação Θ(f(n)) A notação Θ define o limite assintótico exato, ou seja, define uma função f(n) que quando multiplicada por duas constantes c1 e c2 dominará assintoticamente a função em questão superiormente e inferiormente. A definição é a seguinte : : uma função g(n) é Ω (f(n)) se existem constantes positivas c1,c2 e m tais que c1 x f(n) <= g(n) <= c2 x f(n) para todo n >= m.

1.4 Conclusão Após serem apresentados os conceitos básicos de complexidade de algoritmos, algumas notações com seus significados, características e exemplos, podemos concluir que a complexidade é um dado muito importante dos algoritmos e portanto será inserido ao apresentarmos cada algoritmo no material. A notação escolhida para isto é a big-oh devido a sua facilidade de entendimento e simplicidade de cálculo.

Capítulo 2 -

  1. fim para;
  2. (^) BuscaSequencial = pos;
  3. fim.

O algoritmo acima não é o mais otimizado, porém nos exercícios serão cobrados variações deste algoritmo, conduzindo o aluno a produzir algoritmos melhores dependendo da necessidade.

Capítulo 1 -.3.. Complexidade do algoritmo

Figura – Desempenho da Busca Seqüencial em Função do Tamanho da Estrutura

2.. Busca Binária

A busca em uma estrutura de dados será muito mais eficiente se os dados estiverem ordenados. No mundo real pode-se associar a busca binária a busca realizada por uma dada página em um livro. Por exemplo, seja um livro de 500 páginas, devidamente ordenadas, porém com muitas páginas faltando. Suponha-se que deseja-se encontrar a página 124. O melhor procedimento para encontrar essa página será abrir o livro ao meio. Se a página procurada, número 124, for maior do que a página aberta, então deve-se ignorar todas as páginas que estão do lado esquerdo e concentrar nas páginas que estão do lado direito. Caso contrário, se a página procurada, número 124, for menor do que a página aberta, então deve-se ignorar todas as páginas que estão do lado direito e concentrar nas páginas que estão do lado esquerdo. De maneira repetitiva pode-se repetir o passo mencionado. Considerando as páginas que se deve concentrar, por exemplo as páginas da esquerda, então deve-se abrir esse conjunto de páginas ao meio e repetir o processo até encontrar a página desejada ou não houver mais páginas a se considerar. Na computação, esse algoritmo consiste em comparar a chave dada pelo usuário com o valor que está na posição do meio de um vetor. Se o valor for igual, então encontrou-se o valor desejado. Caso contrário, existem dois casos. No primeiro caso, se a chave for menor do que o valor que está na posição do meio do vetor, então descarta-se toda a metade até o fim do vetor e concentra-se a busca na primeira metade do vetor. No segundo caso, se a chave for maior do que o valor que está na posição do meio do vetor, então descarta-se as posições do início até a metade do vetor e concentra-se a busca na segunda metade do vetor. Esse processo deve ser repetido até se encontrar o valor desejado ou não houver mais valores no vetor a procurar. Se o valor for encontrado então retorna-se a posição do vetor em que a chave foi achada. Caso contrário, retorna-se o valor -1 para sinalizar que o valor procurado não está presente na estrutura. O algoritmo da busca seqüência pode ser descrito, em forma de função, da seguinte forma:

  1. Função BuscaBinária(chave:inteiro; Vet:Vetor[1..N]):inteiro
  2. Variáveis
  3. começo:inteiro; //
  4. meio:inteiro;
  1. fim:inteiro;
  2. (^) Início
  3. começo F 0 D F 1;
  4. fim F 0 D F N;
  5. enquanto (começo < = fim) faça
  6. (^) meio F 0 D F fim + começo div 2;
  7. se ( Vet[meio] = chave )
  8. então retorne meio;
  9. senão
  10. se (Vet[meio] < chave)
  11. então começo F 0 D F meio + 1;
  12. (^) senão fim F 0 D F meio -1;
  13. fim se;
  14. fim se;
  15. fim enquanto;
  16. retorne -1;
  17. (^) fim.

A busca binária pode ser transformada em busca ternária, quaternária ou outra N-ária qualquer. Quanto maior a quantidade de dados, mais conveniente será utilizar um N maior. Porém, deve-se tomar o cuidado de se calcular adequadamente o N a ser utilizado. Caso contrário, se houver um vetor de um milhão de posições e aplicar-se um algoritmo de busca em vetor N-ária com N igual a um milhão, então, na prática, transformou-se o algoritmo de busca em vetor N-ária em um algoritmo seqüencial. Neste caso, o número de comparações será no mínimo de uma comparação e no máximo de um milhão de comparações.

Capítulo 1 -.4.. Complexidade do algoritmo

Figura – Desempenho da Busca Binária em Função do Tamanho da Estrutura

3.. Critérios para Escolha do Algoritmo

Supondo que você está envolvido no desenvolvimento de uma solução e precisa definir qual dos algoritmos de busca em vetor utilizar, o principal critério a ser considerados para se escolher o algoritmo de maneira técnica e consciente, diz respeito à Ordenação da estrutura. Quando a estrutura estiver ordenada, o algoritmo de busca binária deve ser utilizado, caso contrário, utiliza-se o seqüencial. Analisando os gráficos de complexidade dos algoritmos, podemos entender melhor essa escolha:

Figura – Comparação de Desempenho entre os Algoritmos de Busca Seqüencial e Binária

Capítulo 3 -

Algoritmos de Ordenação

Capítulo 1 -.5.. Introdução

Um algoritmo de ordenação tem por objetivo colocar uma coleção de dados em uma ordem pré-estabelecida. A ordenação é importante para facilitar a localização de informações como, por exemplo, o telefone de uma pessoa numa lista telefônica. Essa atividade seria impraticável se os nomes dos assinantes não estivessem ordenados alfabeticamente. Os principais algoritmos de busca existentes podem ser agrupados como:

  • Grupo de Algoritmos de Ordenação Não Recursivos;
  • Grupo de Algoritmos de Ordenação Recursivos;

A ordenação pode ser vista como uma atividade que, a partir de uma seqüência de N dados fornecidos como entrada, fornece uma saída com a mesma estrutura de dados, porém em alguma ordem pré-definida pelo programador. Essa ordem pode ser, por exemplo, crescente ou decrescente, utilizando algum campo do registro da estrutura de dados de entrada. A questão da ordenação é fundamental na computação. Ao longo da história, vários pesquisadores já propuseram diferentes algoritmos de ordenação, buscando reduzir o tempo necessário para realizá-la. Neste curso serão abordados os seguintes algoritmos de ordenação:

  • ;
  • ;
  • ;
  • ; e -. Os algoritmos de ordenação por seleção, inserção e bolhas são não recursivos, enquanto os algoritmos de ordenação por fusão e rápida são recursivos. Esses algoritmos encontram-se detalhados nas seções seguintes.

6.. Ordenação por Seleção (Select Sort)

Representa um dos métodos mais simples de compreender e executar. Suponha uma arrumadeira de hotel com várias chaves nas mãos, sendo que cada chave possui uma plaqueta com o número de um apartamento. Para facilitar seu trabalho do dia a dia, a arrumadeira mantém essas chaves organizadas em ordem crescente, a fim de evitar procurar uma por uma a cada novo apartamento a ser arrumado. Imagine que, sem querer, essas chaves caem no chão. Para continuar seu trabalho, a arrumadeira precisa catá-las do chão de modo que elas estejam devidamente ordenadas em sua mão após pegar todas as chaves. Um bom método consiste em procurar a chave de menor número, dentre as chaves que estão no chão, e, então, colocá-la na mão. Depois disto, repete-se o processo, procurando-se a chave de menor número, dentre as que estão no chão, e colocando-a na mão imediatamente atrás da primeira chave catada. E assim sucessivamente, repete-se o processo, procurando-se a chave de menor número, dentre as que estão no chão, e colocando-a na mão imediatamente atrás da última chave catada. Na computação, pode-se notar que seu comportamento, de modo genérico, consiste em achar o menor número e colocá-lo na primeira posição. Em seguida, acha-se o segundo menor número e coloca-o na segunda posição. E assim sucessivamente até não mais haver valores a serem ordenados. Dessa forma, no final de sua execução a estrutura de dados conterá um conjunto de dados devidamente ordenado, na ordem crescente ou decrescente, de acordo com o tipo de ordenação desejada.

primeira carta. Caso seja verdade, então a primeira carta é empurrada para a direita de forma a abrir espaço para que a segunda carta, menor do que a primeira, entre no eu devido lugar. Na seqüência, o jogador segura a terceira carta e a compara com a segunda. Caso seja menor, então empurra-se a segunda carta para o lugar da terceira e prossegue-se comparando se a terceira carta é menor do que a primeira. Caso seja, então a primeira carta também é empurrada para a direita, abrindo vaga para que a terceira carta entre na primeira posição por ser a menor carta dentre as comparadas. Isto é feito sucessivamente, até que não haja mais cartas para serem comparadas. Na computação, pode-se notar que o comportamento desse algoritmo, de modo genérico, consiste em achar comparar uma carta X com suas anteriores. Quando a carta X for menor, então a carta maior deve ser empurrada para a direita, a fim de garantir vaga para a carta X. A cada comparação realizada, deve-se empurrar a carta comparada para a direita, caso ela seja maior do que X. Quando a carta X for comparada com outra carta menor do que ela, então a carta X deve ser inserida imediatamente após essa maior carta. Após comparar a última carta com as demais, inserindo-a no seu devido lugar, a ordenação estará completada. Este algoritmo apresenta melhores resultados em estruturas com grau de ordenação elevado ou quando inserimos dados novos em estruturas já ordenadas. O algoritmo pode ser representado da seguinte forma:

  1. Procedimento Inserção ( var Vet : Vetor[1..N] )
  2. variáveis auxiliar, i, j : inteiro;
  3. inicio
  4. para j de 2 até N faça
  5. início
  6. auxiliar <- Vet[j];
  7. i = j – 1;
  8. enquanto ( ( i > 0 ) e ( Vet[i] > auxiliar ) )
  9. Vet[i + 1] = Vet[i];
  10. i = i – 1;
  11. fim do enquanto;
  12. Vet[i + 1] <- auxiliar;
  13. fim para;
  14. fim

Capítulo 1 -.7.. Complexidade do algoritmo

O maior custo deste algoritmo está em tentar se descobrir onde abrir espaço para inserir a carta que se deseja colocar na ordem. Pelo fato dos valores a esquerda já estarem ordenados, pode-se melhorar o desempenho do algoritmo de ordenação por inserção, aplicando-se o algoritmo de busca binário para localizar o ponto onde o valor deverá ser inserido.

8.. Ordenação por Bolhas (Bouble Sort)

É um algoritmo tão simples de se compreender e executar quanto os anteriores. Na computação, pode-se notar que o comportamento desse algoritmo, de modo genérico, consiste em percorrer a estrutura de dados comparando-se as posições justapostas (lado a lado). A cada comparação verifica-se se o elemento da direita é menor do que o elemento à esquerda. Caso seja menor, então eles estão em ordem contrária, por isto devem

ser trocados de posição um com o outro. Caso seja maior, então a ordem está correta, por isto, mantêm-se suas posições. Esse procedimento de comparar todos os elementos dois a dois, deve ser repetido N vezes, onde N representa o tamanho do vetor. No final desse procedimento, a estrutura estará ordenada. O algoritmo pode ser representado da seguinte forma:

  1. Procedimento Bolha( var Vet:Vetor[1..N] )
  2. início
  3. para i de 1 até N faça
  4. j F 0 D F N;
  5. enquanto ( j > i )
  6. se ( Vet[j] < Vet[j - 1] )
  7. auxiliar <- Vet[j];
  8. Vet[j] <- Vet[j - 1];
  9. Vet[j - 1] <- auxiliar;
  10. fim se
  11. j = j – 1;
  12. fim enquanto;
  13. fim para;
  14. fim

Capítulo 1 -.8.. Complexidade do algoritmo

Porém pelo fato de percorrer a estrutura várias vezes, não é recomendado para algoritmos que tenham necessidade de serem rápidos.

9.. Ordenação Por Fusão (Merge Sort)

Este algoritmo é um pouco mais complexo que os algoritmos acima. Desenvolvido por John von Neumann em 1945, o algoritmo consiste na idéia de divisão e conquista. A entrada é feita em um vetor ( ou também em uma lista por exemplo ) com n elementos e cria-se um vetor auxiliar para que a ordenação seja armazenada. Se n for ímpar, divide-se em chão(n/2) e chão(n/2+1), se n for par tem-se duas divisões com n/2 elementos. Todas elas começando do primeiro elemento ao meio e do meio ao ultimo elemento. A figura abaixo ilustra os passos do algoritmo para um vetor de valores aleatórios.

Figura – Ilustração do Funcionamento do Algoritmo de Ordenação por Fusão

Na prática o algoritmo consiste de duas funções básicas denominadas Fusão e Fundir. A função Fusão divide o vetor em partes menores e em seguida chama a função Fundir para unir de maneira ordenada as partes dividas. A função Fundir compara os elementos do vetor dividido e os ordena e de juntar os elementos ordenados, para as partes do vetor como mencionado acima e como ilustrado na figura.

  1. Procedimento Fusão(var vetor:Vetor[1..N], inicio, fim)
  2. inicio
  3. se (fim > início ) então

Capítulo 1 -.9.. Complexidade do algoritmo

Complexidade de tempo: Θ( n log2 n ) Complexidade de espaço: Θ( n log2 n )

É possível implementar o merge sort utilizando somente um vetor auxiliar ao longo de toda a execução, tornando assim a complexidade de espaço adicional igual a Θ(n). É possível também implementar o algoritmo com espaço adicional Θ(1).

10.. Ordenação Rápida (Quick Sort)

Em 1960, o estudante Hoare visitou a Universidade de Moscou e, durante esta visita, inventou o algoritmo de ordenação chamado Quick Sort, publicado anos depois com as devidas alterações. Seu funcionamento também baseia-se no princípio de dividir para conquistar, da mesma forma que o algoritmo de ordenação por fusão. Na computação, pode-se notar que o comportamento desse algoritmo, de modo genérico, consiste em dividir o vetor em partes menores, sendo que a cada divisão, os menores elementos devem ficar a esquerda da posição onde será feita a divisão, e os maiores elementos à direita. No final dessa divisão, obtém-se vários vetores de apenas um elemento. Após isto, o algoritmo passa a montar as partes de maneira ordenada. Ao término dessa montagem o vetor está ordenado. Na prática o algoritmo consiste de duas funções básicas denominadas SelecionaPivo e OrdenaRápido. A função SelecionaPivo sorteia uma posição do vetor e o elemento dessa posição é denominado de pivô. O procedimento OrdenaRápido compara todos os elementos do vetor com o pivô. Se o elemento for menor do que o pivô então o elemento deve ser colocado a esquerda desse pivô. Se o elemento for maior do que o pivô então o elemento deve ser colocados a direita desse pivô. A idéia básica do algoritmo é dividir a estrutura de dados em duas partes através de um pivô. Feito isto percorre-se a estrutura para antes do pivô e para depois procurando elementos maiores que o pivô e menores que o pivô respectivamente. Quando encontrados, os elementos são trocados de lugar já que estão na parte errada da divisão da estrutura. Tal procedimento é feito até que os auxiliares de busca se cruzem em algum ponto do vetor. Abaixo temos o algoritmo em linguagem de alto nível estruturado:

Função SelecionaPivo(v N : inteiro ):inteiro

Variáveis

pos:inteiro;

início

{A função Sorteio escolhe aleatoriamente um valor de 1 até N. sendo que os valores têm a mesma probabilidade de serem sorteados} retorne sorteio( N ; DistribuiçãoUniforme);

fim.

Procedimento OrdenaRápido(Var vetor:Vetor; inicio, fim:inteiro)

Variáveis antes, depois, pivô : inteiro;

inicio

antes = inicio depois = fim pivô = SelecionaPivo( N );

repita enquanto (vetor[antes] < pivô) antes <- antes + 1 enquanto (vetor[depois] > pivô) depois <- depois - 1 se (depois >= antes) então auxiliar = vetor[antes]; vetor[antes] = vetor[depois] vetor[depois] = auxiliar depois <- depois - 1 antes <- antes + 1 fim se; até (antes > depois) se (depois > inicio) OrdenaRápido(vetor, inicio, depois); se (antes < fim) OrdenaRápido(vetor, antes, fim); fim.

A figura na página seguinte ilustra a situação em um vetor aleatório:

Figura – Ilustração do Funcionamento do Algoritmo de Ordenação Rápida

10...1.. Complexidade do algoritmo

Quicksort is a well-known sorting algorithm developed by C. A. R. Hoare that, on average, makes Θ(n log n) comparisons to sort n items. However, in the worst case, it makes Θ(n2) comparisons. Typically, quicksort is significantly faster in practice than other Θ(n log n) algorithms, because its inner loop can be efficiently implemented on most architectures, and in most real-world data it is possible to make design choices which minimize the possibility of requiring quadratic time. Quicksort is a comparison sort and, in efficient implementations, is not a stable sort.

11.. Critérios para Escolha do Algoritmo

Supondo que você está envolvido no desenvolvimento de uma solução e precisa definir qual dos algoritmos de busca em vetor utilizar, o principal critério a ser considerados para se escolher o algoritmo de maneira técnica e consciente, diz respeito à Ordenação da estrutura. Quando a estrutura estiver ordenada, o algoritmo de busca binária deve ser utilizado, caso contrário o seqüencial. Analisando os gráficos de complexidade dos algoritmos, podemos entender melhor essa escolha:

12.. Exercícios Resolvidos

ANEXO I

Práticas de programação, dicas sobre como comentar o código,

ANEXO II

Práticas para testar o

ANEXO III - Construindo Bibliotecas em Pascal

CRIANDO BIBLIOTECAS EM PASCAL

Definição de Biblioteca

Biblioteca é um arquivo que contém uma estrutura de dados e um conjunto de funções e procedimentos que podem ser reusados por um programa de computador. Por exemplo, ao escrever um programa em Pascal, um programador não precisa programar os comandos writeln e read , todas as vezes que cria um novo programa. Ao invés disto, o programador declara a linha de comando “uses crt;”, que nada mais faz do que dizer ao programa que ele se utilizará da biblioteca chamada crt, e é dentro desta biblioteca que se encontra programada a função read e o procedimento writeln. Outro uso para as Unit é para definir Tipos Abstratos de Dados, por exemplo, uma fila, pilha, vetor, árvores, grafo, dentre outros, onde a estrutura de dados e as funções e procedimentos são colocados na mesma biblioteca, podendo ser reutilizado por outros programas.

Estrutura de uma UNIT

Quando um programador deseja escrever um programa em Pascal, ele deve obedecer a seguinte estrutura: program ; uses ; const <declaração de constante >; var <declaração de variaveis > begin end.

Quando você quiser escrever uma biblioteca você deve obedecer a seguinte estrutura: Unit ; {deve ter o mesmo nome do arquivo.pas}

Interface <Declaração das funções que a biblioteca conterá>

Implementation

<Código das funções declaradas em “Interface”>

End. (final da Unit}

Exemplo de uma Unit

Unit ROTINAS; {O nome da biblioteca DEVE ser o mesmo do arquivo, sem a extensão “.pas”}

Interface { Contém o protótipo de todas as funções dessa biblioteca} Function COMP_CIRC (R:real) : real; {calcula comprimento de um circulo de raio R} Function AREA_CIRC (R:real) : real; {calcula área de um circulo de raio R}

Implementation {Contém o código dos procedimentos e das funções declaradas} Const PI=3.1416; {Qualquer função ou procedimento enxerga esta constante, bem como