Algoritmos I
Transcription
Algoritmos I
Algoritmos I Roberto de Beauclair Seixas Abu Abd-Allah ibn Musa al'Khwarizmi z Seu trabalho mais importante escrito em 830 nos dá a palavra álgebra. Æ classifica a solução de equações quadráticas e dá métodos geométricos para completar o quadrado. z Al'Khwarizmi também escreveu números Hindu-árabe. Æ Este texto de árabe está perdido mas uma tradução latina “Algoritmi de numero Indorum”, em inglês “Algoritmi de numero Indorum in English Al-Khwarizmi on the Hindu Art of Reckoning”, deu origem a palavra algoritmo que deriva do nome dele no título. z O primeiro uso do zero com lugar posicional na anotação básica provavelmente foi devida a al'Khwarizmi. 2 Algoritmo z Dicionário Webster: “Any special method of solving a certain kind of problem.” 3 Algoritmo z Dicionário Webster: “Any special method of solving a certain kind of problem.” ( parece coisa do McGuiver! ) 4 Algoritmo z Fundamentals of Computer Algorithms; E.Horowitz, S.Sahni; 1978: “A precise method useable by a computer for the solution of a problem.” 5 Algoritmo z Fundamentals of Computer Algorithms; E.Horowitz, S.Sahni; 1978: “A precise method useable by a computer for the solution of a problem.” 6 Pi com 24 casas How I want a drink, alcoholic of course, after the heavy lectures involving quantum mechanics. All of the geometry, Herr Planck, is fairly hard ... 3.14159265358979323846264... 7 Fibonacci 0,1,1,2,3,5,8,13,21,34,55,89,144,233,377 ... z Isto se parece um padrão simples, contudo determina a forma da concha de um molusco, o bico de um papagaio ou o brotando de folhas do talo de qualquer planta, foi revelado por Leonardo Pisano (depois Fibonacci) a quase 800 anos atrás. Pisano, o primeiro grande matemático de Europa medieval, descobriu estes números mágicos analisando a natalidade de coelhos em 1202. z A relação entre os números de Fibonacci se aproxima de 1,6180. Esta relação mágica os gregos chamava de “proporção divina” e seus templos, como por exemplo o Parthenon em Atenas, possuíam comprimento = 1,6180 × largura. z Antes dos gregos, os egípcios construíram suas pirâmides seguindo as mesmas regras: base = 1,6180 × altura. z Nos organismos vivos, as garras de um leão, os chifres de um carneiro, os dentes de elefantes, a concha de um caracol e etc., seguem a regra da “espiral dourada” (derivada do “retângulo dourado” onde largura = 1,6180 × altura) 8 Algoritmos I - Ementa z Motivação 9 Æ Presente, Passado e Futuro(?) z z z z z Modelos de Computação Fundamentos Matemáticos * Ordenação Busca Grafos 9 Presente Os próximos 7 slides foram adaptados de duas apresentações da TechMark Engenharia de Software: What the Hell is this? z Engenheiros Civis fazem Plantas antes de construírem prédios; z Engenheiros Eletrônicos fazem Esquemas antes de montarem aparelhos; z Engenheiros Mecânicos fazem Desenhos antes de produzirem máquinas; z Engenheiros de Software são superdotados pela Mãe Natureza, e não precisam de nada disso! Æ “Se prédios fossem construídos da mesma forma que fazemos sistemas, o primeiro pica-pau que aparecesse no planeta destruiria a humanidade” - Weinberg 11 A Engenharia de Software é uma área MUITO NOVA! z z z z O ser humano faz casas e abrigos há milhões de anos; O ser humano lida com eletricidade há milhares de anos; O ser humano produz máquinas e ferramentas há outros milhares de anos; O ser humano faz software há 40 anos. Æ Estamos nos primórdios da computação... 12 Conclusão “A formulação de um problema é freqüentemente mais essencial do que sua solução, a qual pode ser meramente uma questão de habilidade matemática ou experimental.” (LQVWHLQH,QIHOG DXWRUHVGH³$(YROXomRGD)tVLFD´ 13 “Tamanho” dos Sistemas Sistemas grandes (>12 meses) são melhor atendidos por metodologias completas e rigorosas, com passos formais, revisões estruturadas, documentos intermediários formais e ciclo de vida em cascata. O desenvolvedor deverá estar interessado em reuso a longo prazo. Sistemas menores (<6 meses) são mais adequados a metodologias leves, sem muito rigor, com passos intermediários informais e ciclo de vida iterativo. Documentação não é a base do projeto, mas apenas uma ferramenta de consulta. O desenvolvedor está interessado em reuso imediato. 14 Habilidades Técnicas dos Analistas e Programadores Constrói-se utilizando-se abordagens conservadoras, organizando-se bem o processo de desenvolvimento e utilizando-se de técnicas estruturadas, que capitalizam sobre conhecimentos existentes. Em compensação, você está mais próximo da obsolescência. Se a sua equipe é nova, aberta a mudanças e propensa a tentar coisas novas, não hesite. Você tem uma excelente oportunidade de introduzir técnicas Orientadas por Objetos em sua organização. Seus sistemas terão uma vida mais longa desta forma. 15 Exigências com Relação à Tecnologias Caso os seus clientes tenham perfil conservador (denota-se através de sua arquitetura de hardware e rede) você deve sintonizar-se com a linguagem deles e utilizar algo que use a mesma terminologia. Deixe claro o risco da obsolescência. Caso seus clientes exigem de você a “última palavra” em tecnologia, sorte sua. Mantenha o foco, invista em tecnologia OO e vá em frente. Mas, divida e responsabilidade pelo sucesso (ou fracasso) com o cliente. 16 Ambiente de Desenvolvimento • COBOL, FORTRAN, “C”, BASIC, • VB5, Java, PowerBuilder, C++, Pascal, PL/1, VB3, Natural, e outras linguagens procedurais: Fique com métodos estruturados e técnicas de Entidade/Relacionamento; • Use DeMarco, Yourdon, Martin, Constantine, Gane/Sarson, Peter Chen, etc…; SmallTalk, CORBA, Forté, Informix NewEra, Delphi e outras linguagens que suportam conceitos de classes, heranças e agregações: Aprenda OO imediatamente, ou não terá benefício em utilizá-las; • Use UML, OMT, Shlaer/Mellor, Martin/Odell, Coad/Yourdon, etc 17 Passado e Futuro(?) Alan M. Turing (1912-1954) z Computing Machinery and Intelligence. Mind, Vol. LIX. 433-460, 1950 Æ Os computadores terão inteligência. z Debate: Então, e agora ? Æ Será uma relação simbiótica ? (computador como uma ferramenta) Æ Os computadores terão “consciência”? 19 Teste de Turing z 1o Teste - Jogo de Imitação: Æ 3 pessoas: Juiz, homem e mulher; Æ Toda conversa por e-mail; Æ Homem finge ser a mulher; Æ Homem mente; Æ Mulher tenta ajudar o juiz; Æ Juiz tem que identificar o homem em 5 minutos. 20 Teste de Turing z 2o Teste - Jogo de Substituição: Æ Troque o homem ou a mulher por um computador; Æ O juiz é enganado 30% do tempo. 21 O que Turing disse? “I believe that in about fifty years' time it will be possible, to program computers, with a storage capacity of about 109 , to make them play the imitation game so well that an average interrogator will not have more than 70 per cent chance of making the right identification after five minutes of questioning. The original question, “Can machines think?” I believe to be too meaningless to deserve discussion. Nevertheless I believe that at the end of the century the use of words and general educated opinion will have altered so much that one will be able to speak of machines thinking without expecting to be contradicted.” Alan M.Turing, 1950 “Computing Machinery and Intelligence.” Mind, Vol. LIX. 433-460 22 49 anos depois z Previsão de tecnologia de Turing foi fantástica! Æ Armazenamento de Gb de memória são comuns. z Previsão de inteligência foi otimista. Æ Vários locais da Internet oferecem “chatterbots” do teste. Æ Ninguém passou (ainda) ` http://www.loebner.net/Prizef/loebner-prize.html z Mas acredita-se que não demorará Æ menos de 50 anos, mais de 10 anos. z Os testes de Turing ainda se apresentam como desafios de longo prazo. 23 Mas, houve progresso ... z Computadores solucionaram alguns problemas: “Mapa de 4 cores” Æ K. Appel and W. Haken, “The solution of the four-color-map problem,” Scientific American, Oct 1977, 108-121 e uma prova “manual” http://www.math.gatech.edu/~thomas/FC/fourcolor.html (1995) z Os computadores venceram o campeão mundial de xadrez Æ com alguma ajuda dos programadores, mas … venceu! z Os computadores estão presentes no dia-a-dia z Ajudam a projetar e idealizar novas coisas z Estas são relações simbióticas. z Aprendizado e formação de conhecimento ainda são ilusórios. 24 Armadilha dos números z Os seres humanos possuem 100 Tb de informação (1012) e podem processar 100 T ops. Æ ROBOT, Hans Moravec, Oxford, 1998, page 58 Æ Æ Æ Æ 90% lixo 90% em comum com os chimpanzés 90% comum entre os indivíduos Então, realmente só 106 bytes são relevantes (huh?!) Æ Æ Æ Um excelente algoritmo de compressão ? Uma melhor linguagem de programação ? Técnicas de aprendizado ? z Então, um supercomputador “tem” um poder comparável. z O Genoma humano tem 109 bits: z Estamos perdendo algo ... 25 26 Charles Babbage (1791-1871) z Os objetivo de Babbage foram alcançados Æ mas ainda precisamos de melhores algoritmos e máquinas mais rápidas. z O que acontecerá quando: Æ A capacidade de processamento for infinita ? Æ A capacidade de armazenamento for infinita ? z Limites remanescentes: Æ Conteúdo: A capacidade de informação do Cyberspace Æ Software: Bugs, >100$ por linha de código (!) Æ Processamento: > 1,000 $/cpu/ano 27 Mais 3 desafios z Implícitos nos teste de Turing: Æ Æ Ler e entender tão bem quanto um humano Escrever e pensar tão bem quanto um humano – Traduzir “fala” para “texto” z Ouvir tão bem quanto uma pessoa (locutor nativo) z Falar tão bem quanto uma pessoa (interlocutor nativo) – Traduzir “texto” para “fala” z Ver tão bem quanto uma pessoa (reconhecer objetos e comportamentos) z Ilustrar/Mostrar/Desenhar tão bem como uma pessoa (já feito) Æ Æ mas, Realidade Virtual ainda é um grande desafio criar cenas 3D “reais” em tempo real z E ainda: Lembrar o que foi (é) visto e ouvido e rapidamente responder quando solicitado. 28 Benefícios z Hoje os computadores podem: Æ Ler para os cegos (OCR & Texto → Fala) Æ Ouvir para os surdos (Fala → Texto) Æ Escrever para os deficientes (Fala → Texto) z Logo: Æ Substituir deficiências: ` melhor memória, melhor visão, … Æ Novas formas de comunicação ` Tradução automática de telefonemas Æ Revolucionar a interface homem-computador 29 Vannevar Bush (1890-1974) z “As We May Think” The Atlantic Monthly, 1945 http://www.theatlantic.com/unbound/flashbks/computer/bushf.htm z Memex Æ Todo conhecimento humano … “a billion books” hyper-linked together ... Æ Registrando tudo o que se vê ` filmes e fotos ` ... “a machine which types when talked to” ... Æ Navigate by ` … text search following links associations ... z Conexões diretas ao sistema nervoso ? 30 Memex Individual Memex: “Lembrar o que é visto e ouvido e rapidamente devolver qualquer informação solicitada” 31 Quanto de Informação Existe ? z Logo, tudo poderá ser gravado e catalogado. z A maioria da informação nunca será vista. z Fundamentos tecnológicos: Æ Atenção humana Æ “Sumarização” automática Æ Busca automática http://www.lesk.com/mlesk/ksg97/ksg.html 32 Resumo z Pense seriamente sobre Algoritmos z Qual o melhor algoritmo para um problema? → “aderência” z Oito paradigmas para projetar um bom algoritmo: 1. reduzir a um problema conhecido (ex: ordenação); 2. recursão; 3. criar ou expandir uma estrutura de dados; 4. dividir e conquistar; 5. guloso; 6. programação dinâmica; 7. probabilidade; 8. aproximação. 33 Usa Windows ?!? 34 Cuidado com os efeitos colaterais! 35 Modelos de Computação Problemas & Algoritmos suponha n=8 Problema: Como computar S ? Æ entrada: lista de salários S1, S2, … , Sn Æ saída: despesa total com salários: S = S1+S2+…+Sn Æ recursos: pessoa alfabetizada, papel e lápis solução 1: solução 2: solução 3: - estimar o salário típico T (por exemplo, o 1o da lista) - calcular S por S = n * T 37 Modelos Computacionais z Procuram abstrair e simplificar o comportamento dos computadores. Æ Máquina de Turing ` Utilizado para estabelecer resultados básicos em computabilidade e complexidade computacional. Æ Árvore de Decisões Algébricas ` Muito usado para obtenção de resultados teóricos em computação. 38 Problema Algorítmico z Problema E ⇒ conjunto das possíveis entradas S ⇒ conjunto das saídas desejadas R(E,S) ⇒ relação entre entradas e saídas desejadas O ⇒ operações válidas z Solução A ⇒ algoritmo correto e ∀e ∈ E A s (e,s) ∈ R(E,S) 39 Solução de Problemas modelo modelomatemático matemático algoritmo algoritmoinformal informal tipo tipoabstrato abstratode dedados dados pseudo pseudocódigo código estrutura estruturade dedados dados programa programa ... código códigode demáquina máquina 40 Algoritmos e Complexidade z z Problema, Instância e Algoritmo. Dado um problema: Æ Como encontrar um algoritmo eficiente para solucioná-lo ? Æ Uma vez encontrado, como compará-lo a outros algoritmos que também resolvem o problema ? Æ Como determinar se o algoritmo está correto ? Æ Como determinar se o algoritmo é eficiente ? 41 Algoritmo Conjunto finito de instruções, composta de uma ou mais operações válidas, com o objetivo de resolver um problema específico. z Operações válidas Æ definidas 5÷0 Æ efetivas √π z Término em tempo finito (procedimento computacional) z Entrada (opcional) z Saída (uma ou mais) 42 Alguns Exemplos Iniciais Para qualquer algoritmo, temos que provar que ele sempre retornará o resultado desejado para todas as instâncias possíveis do problema. ¼ Correção (Correctness) ¼ Eficiência 43 Critérios de Análise especificação z Eficácia Æ Correção problema algoritmo requisitos verificação NÃO erros z Eficiência Æ Æ Æ Æ Tempo Espaço Simplicidade / Clareza Otimalidade z Limitações Æ Computabilidade Æ Tratabilidade SIM solução código z Parcialmente Correto Æ Æ entrada válida → saída desejada pode ser tempo infinito Æ Æ tempo finito saída desejada z Totalmente Correto 44 Correção não é óbvio! ¼ Você recebeu a tarefa de programa um braço de robô de soldagem. ¼ O robô deve soldar (visitar) o primeiro ponto de solda, depois o segundo, terceiro e assim por diante. ¼ Determine um algoritmo para achar o melhor caminho. 45 Vizinho Mais Próximo ¼ Inicie em algum ponto p0 e então vá para o ponto mais próximo p1. Repita o processo a partir de p1, etc. até que todos os pontos sejam visitados. Escolha e visite um ponto inicial p0 p = p0; i = 0; enquanto existirem pontos não visitados i=i+1 escolha e visite o ponto pi, mais próximo de pi-1 retorne ao ponto inicial ¼ Este algoritmo é simples de entender, simples de entender e muito eficiente. Está correto ? 46 Vizinho Mais Próximo ¼ Algoritmo não é correto! ¼ Escolher sempre o ponto mais próximo é muito restritivo, pois pode nos levar a fazer movimentos desnecessários. 47 Par Mais Próximo ¼ Conectar ao par mais próximo de pontos cuja conexão não irá causar um ciclo ou bifurcações, até se formar uma única cadeia de pontos com todos os pontos. faça n ser o número de pontos do conjunto e d = ∞ para i = 1 até n - 1 faça para cada par de pontos (x,y) de caminhos parciais if (dist(x,y) <= d) então xm = x; ym = y; d = dist(x,y); conecte (xm, ym) por uma aresta conecte os dois pontos por uma aresta ¼ Este algoritmo está correto para o contra-exemplo anterior. Então agora estará correto ? 48 Par Mais Próximo ¼ Algoritmo não é correto! ¼ Existe algoritmo correto ?! 49 Um algoritmo correto z Podemos tentar todas as ordenações de pontos possíveis e então selecionar a ordenação que minimiza o comprimento total. z Uma vez que todas as possíveis ordenações são consideradas, podemos garantir que teremos o melhor caminho possível. z Mas, isso significa testar n! permutações, que é extremamente lento. Tão lento que é inviável quanto se tem mais de 10 ou 20 pontos. z Conclusão: Não existe um algoritmo correto eficiente! Traveling Salesman Problem 50 Eficiência “Porque (simplesmente) não usar um supercomputador?” z Supercomputadores são para pessoas muito ricas e muito estúpidas para escrever algoritmos eficientes! (S.Skiena) z Um algoritmo rápido rodando em um computador lento irá sempre ganhar de um supercomputador com um algoritmo ruim para instâncias suficientemente grandes. z Normalmente, os problemas não chegam a ficar tão grandes antes do algoritmo rápido ganhar. 51 Correção z Método de Solução Æ Fórmulas / Propriedades Æ Lemas / Teoremas z Conjunto de Instruções Æ Invariantes & Convergentes ` trecho de código faz exatamente o desejado ` não tem nenhum loop infinito Æ Prova de Teoremas ` seqüência de instruções usa corretamente as propriedades teóricas ` garante a integridade das fórmulas 52 M.D.C. Entrada: x, y ∈ Z* Saída: mdc(x,y) max{z ∈ Z | ∃ a,b ∈ Z, x=a*z, y=b*z} exemplo 1: exemplo 2: mdc(67,12) = 1 mdc(64,12) = 4 53 Algoritmo Ingênuo - mdc int mdc(int x, int y) { int t; if (x < y) t = x; else t = y; while ((x%t != 0) && (y%t != 0)) t--; return t; } 54 Correção Total Correção Parcial + Término = Correção Total z Correção Parcial Æ pontos de verificação e invariantes z Término Æ Æ Æ 0 < t <= min(x,y) t = 1 ⇒ não itera a cada iteração t decresce ⇒ t é o convergente Conclusão: O algoritmo ingênuo para o problema do M.D.C. é totalmente correto! 55 Algoritmo de Euclides - mdc Entrada: x, y ∈ Z* Saída: mdc(x,y) max{z ∈ Z | ∃ a,b ∈ Z, x=a*z, y=b*z} exemplo 1: 67 7 5 12 5 exemplo 2: 1 7 2 1 5 1 2 2 0 2 1 64 4 5 12 0 3 4 56 Algoritmo de Euclides - mdc mdc (54180,13125) = ? 4 54180 13125 7 5 Algoritmo Ingênuo: Algoritmo Euclides: 7 1680 2 1 1365 1 13020 5 4 315 0 3 105 iterações iterações (2604 x !!!) Correção: Æ mdc (0, x) = x, pois qualquer número é divisor de zero Æ mdc (x, y) = mdc (y, x mod y) é o resultado básico usado na solução 57 Algoritmo de Euclides - mdc Com recursividade: int mdc(int u, int v) { if (v == 0)return (u); else return (mdc(v,u%v)); } int int mdc(int mdc(int u, u, int int v){ v){ int int t; t; Convertendo de recursivo para não-recursivo: while while (v (v != != 0) 0) {{ t=u%v; t=u%v; u=v; u=v; v=t; v=t; }} return return u; u; }} 58 Problema: Ponto em Polígono Dado em polígono plano simples, ou seja, os lados não se cruzam, P e um ponto p do plano, decidir se p é interior ou não ao polígono P. P •p 59 Complexidade Assintótica z Existe algum algoritmo que resolve o problema? Æ Isso requer que o algoritmo pare após um número finito de passos para qualquer instância do problema. z Dado um certo algoritmo A, quão eficiente é este algoritmo? Dado dois algoritmos A e B, qual deles é superior? z Dentre todos os algoritmos que resolvem o problema, qual deles é melhor? z Medir a complexidade (ou eficiência) de um algoritmo pelo tempo necessário à sua execução em função do tamanho da instância. (Complexidade Assintótica O(f (n))) 60 Análise de Algoritmos z Recursos Computacionais Æ Tempo de execução e quantidade de memória z Implementação do Algoritmo Æ Linguagem e arquitetura z Tamanho da entrada (N) Æ Número de elementos ou número de nós da expressão z Complexidade (tempo) de Pior Caso Æ T(N): Maior tempo de execução do algoritmo com todos os problemas possíveis de tamanho N. Æ T(N) é proporcional ao número total de instruções t (N) executadas para o pior caso de tamanho N ⇒ T(N) = c t (N) 61 Definição 1 Um algoritmo A para resolver P tem complexidade O(f (n)) se existe uma constante k > 0 e um natural N tais que, para qualquer instância de P de tamanho n > N, o número de passos de A necessários para resolver esta instância é, no máximo, k f (n). ex. 1000 n2 “ambiente computacional” “natureza do método” 62 Ordens de Magnitude x←x+y for i ← 1 to n for i ← 1 to n begin begin x←x+y for j ← 1 to n begin end x←x+y end end 1 n n2 63 Complexidade z Se um algoritmo processa problemas de tamanho n em tempo cn2 para alguma constante c, então dizemos que a complexidade (time complexity) do algoritmo é O(n2), lendo-se “ordem n2”. algoritmo A1 A2 A3 A4 A5 complexidade n n log n n2 n3 2n 1s 1000 140 31 10 9 1m 6x104 4893 244 39 15 1h 3.6x106 2.0x105 1897 153 21 64 Complexidade 65 Tempo de Execução 20 50 100 200 500 1000 1000 n 0.02 s 0.05 s 0.1 s 0.2 s 0.5 s 1s 1000 n log n 0.09 s 0.3 s 0.6 s 1.5 s 4.5 s 10 s 100 n2 0.04 s 0.25 s 1s 4s 25 s 2m 10 n3 0.02 s 1s 10 s 1m 21 n 2.7 h nlog n 0.4 s 1.1 h 220 d 125 s 5E8 s 2n 1s 35 a 3E4 s Tamanho Complexidade - Obs.: Supondo que 1 operação leva 1 µs. 66 Tamanho Máximo do Problema Tempo Complexidade 1s 1.7 m 2.7 h 12 d 3a 3s 1000 n 1E3 1E5 1E7 1E9 1E11 1E13 1000 n log n 1.4E2 7.7E3 5.2E5 3.9E7 3.1E9 2.6E11 100 n2 1E2 1E3 1E4 1E5 1E6 1E7 10 n3 46 2.1E2 1E3 4.6E3 2.1E4 1E5 nlog n 22 36 54 79 112 156 2n 19 26 33 39 46 53 67 Curiosidade z Explosão Combinatorial Æ Æ Æ Æ 100! → número com 158 dígitos 120! → número com 200 dígitos número de prótons no universo → 126 dígitos número de µ segundos desde o Big-Bang → 24 dígitos z Impacto da Evolução Tecnológica algoritmo n n2 n3 2n atuais N1 N2 N3 N4 100 x 100 N1 10 N2 4.64 N3 N4 + 6.64 1000 x 1000 N1 31.6 N2 10 N3 N4 + 9.97 68 Outra Curiosidade (sic!) z Dada a função f abaixo, calcule o seu valor para x = 40545 e y = 70226. f (x,y) = 9 x4 - y4 + 2 y2 dígitos: 3 7 11 15 19 21 1010 -10-13 1.3 107 82152 2 Oops! O valor correto é 1 69 Outra Curiosidade (sic!) z Dada a função f abaixo, calcule o seu valor para: x = 77617 y = 33096. f (x,y) = 333.75 y6 + x2 (11 x2 y2 - y6 - 121 y4 - 2) + 5.5 y8 + x/2y Precisão simples: Precisão dupla: Precisão extendida: 1.172603… 1.1726039400531… 1.172603940053178… Oops! O valor correto é -0.8273960599… ( - 54767 / 66192 ) 70 Moral da História “Computers do not solve problems, People do!” E.R.Davidson 71 Algoritmos para Ordenação z Insertion Sort z Selection Sort z Bubble Sort z Shell Sort z etc. 72 Ordenação por Seleção SelectionSort(x,n) para i = 1 .. n-1 m=i para j = i+1 .. n se xj < xm então m = j troque xi com xm 73 Ordenação por Seleção 74 Ordenação por Seleção z Para analisar tal algoritmo, a primeira observação é que o tamanho de uma instância é dada pelo número n de reais a serem ordenados. z Na primeira execução do corpo do loop principal, são feitas n-1 comparações e 1 troca, num total de n operações. z Na segunda execução, n-2 comparações e 1 troca, e assim por diante. Logo, o número de passos para o algoritmo é: n(n + 1) n 2 n n + (n − 1) + (n − 2 ) + + 1 = = + ≈ n2 2 2 2 z Assim, o algoritmo tem complexidade O(n2) 75 Não entendeu ?! z Porque N (N + 1) i= ∑ 2 i =1 N ? … soma de seqüências! z Quanto é a soma de inteiros de 1 até 100 ? Æ Com papel e lápis pode demorar um pouco … Æ Podemos usar uma calculadora … Æ Escrever um programa … z Em 1786, um garoto de 9 anos respondeu em alguns 5 segundos! z Nome dele ? Gauss. 76 Demonstração de Gauss n S (n ) = ∑ i = 1 + 2 + 3 + + n i =1 S (n ) = 1 + 2 + 3 + + n + S (n ) = n + (n − 1) + (n − 2 ) + + 1 2 S (n ) = (n + 1) + (n + 1) + + (n + 1) n ⋅ (n + 1) S (n ) = 2 n vezes 77 Ordenação por Inserção Insertsort(x) para i = 2 .. N v = xi j=i enquanto xj-1 > v xj = xj-1 j=j-1 xj = v Este algoritmo descobre a posição correta para xi no segmento x1..xi-1 ao mesmo tempo que o coloca lá. Com isso, obtemos soluções parciais e algoritmo deste tipo são chamados de incrementais ou on-line. Usando árvores balanceadas, é possível implementar algoritmos incrementais ótimos para ordenação. 78 Ordenação por Inserção 79 Mergesort z Usa o paradigma “dividir-para-conquistar” que obtém a solução de um problema através da resolução de problemas de tamanho menor. z Ao invés de ordenar o conjunto de n números, dividimos este conjunto em dois conjuntos com n/2 elementos cada, ordenamos cada um destes conjuntos e reunimos esses conjuntos já ordenados. z Para ordenar cada um dos conjuntos com n/2 elementos, aplicamos recursivamente o mesmo algoritmo. 80 Mergesort Mergesort (x, l, r) se (r <= l) então retorne; /* caso básico da recursão */ m = (l + r) / 2; mergesort(x, l, m); mergesort(x, m+1, r); merge(x, l, m, r) /* separação */ /* recursão */ /* combinação */ 81 Mergesort 82 Mergesort z Para facilitar, n=2p e seja T(n) a complexidade do algoritmo, expressa pelo número de passos necessários à sua execução. z Duas chamadas recursiva do mesmo algoritmo para instâncias de tamanho n/2, seguidas por uma etapa em que, a partir de dois conjuntos já ordenados, deve-se obter sua união, também já ordenada. Esta união é obtida em um número de passos que é proporcional a n. T(n) = 2 T(n/2) + k n onde k é uma constante. 83 Mergesort T(n) = 2 T(n/2) + k n Por sua vez, T(n/2) = 2 T(n/4) + k n/2 o que fornece T(n) = 4 T(n/4) + 2 k n Continuando o mesmo processo, obtemos sucessivamente: T(n) = 8 T(n/8) + 3 k n ... T(n) = n T(n/n) + p k n T(n) = 2p T(n/2p) + p k n n = 2p T(n) = n T(1) + k (log2 n) n p = log2 n Daí, concluímos que T(n) = O(n log n) 84 Algoritmo Dividir-para-Conquistar Separação: decompor a instância do problema em duas instâncias de tamanhos menores; Recursão: aplicar recursivamente o mesmo algoritmo para cada uma destas instâncias; Combinação: combinar os resultados para obter a solução da instância original. 85 Teorema 1 Se um algoritmo recursivo do tipo dividir-paraconquistar para resolver um problema decompõe uma instância de tamanho n em duas instâncias de tamanho n/2 do mesmo problema e, se o processamento necessário à execução das etapas de separação e combinação tem, no total, complexidade O(n), então o algoritmo resultante tem complexidade O(n log n). 86 QuickSort z Também utiliza o paradigma de dividir-para-conquistar. z Toma-se um elemento do conjunto (x1) e a etapa de separação consiste em dividir o conjunto a ser ordenado em dois subconjuntos: o primeiro é composto por todos os elementos menores que x1 e o segundo por todos os maiores ou iguais a x1. Cada um destes conjuntos é ordenado utilizando recursivamente o mesmo algoritmo. z A etapa de combinação é trivial, já que a seqüência ordenada consiste em listar os elementos (já ordenados) que são menores que x1, seguidos pelos elementos (também já ordenados) que são maiores ou iguais a x1. 87 QuickSort quicksort(r,s) se (s <= r) então retorne v = xr ; i = r; j = s + 1; repita repita i = i + 1 até xi >= v repita j = j + 1 até xj <= v troque xi com xj até j <= i troque xi com xj troque xi com xj quicksort(r,i - 1) quicksort(i+1,s) /* caso básico */ /* separação */ Observações: Observações: ••não nãohá háuma umachamada chamadaexplícita explícita de decombinação combinação ••ooinício iníciodo doalgoritmo algoritmose sedá dá quicksort(1,n) chamando chamando quicksort(1,n) /* recursão */ 88 QuickSort 89 QuickSort z Como o processamento da separação requer O(n) passos, uma análise semelhante à desenvolvida para o Mergesort permite demonstrar que a complexidade média do algoritmo é O(n log n). z No entanto, a complexidade deste algoritmo no pior caso é O(n2). Para se constatar este fato, basta observar que, caso o conjunto esteja ordenado, o algoritmo descrito vai executar n-1 separações. A primeira exige n-1 comparações, a segunda n-2, e assim por diante, num total de O(n2) comparações. 90 ShellSort z Utiliza o algoritmo de inserção em sub-seqüências periódicas da entrada para produzir um algoritmo mais rápido. shellsort(a) h = 1; faça (h = 3 * h + 1) até (h > N) faça h = h div 3 para i = h+1 até N faça v = a i; j = i; enquanto aj-h > v faça j = j - h; aj = aj-h; se (j <=h) termine enquanto aj = v até (h = 1) 91 13 ShellSort 4 • Usa uma seqüência decremental de incrementos; • Cada passo torna o próximo mais fácil; • Como saber qual incremento usar ? 1 • Ex.: 1, 4, 13, 40, 121, 363, ... 92 BubbleSort n bubblesort(a) faça t = a1 para j = 2 até N faça se (aj-1 > aj) então t = aj-1; aj-1 = aj; aj = t; até (t = a1) o bubblesort(a) para i = 1 até n-1 para j = n até i+1 passo -1 if (aj < aj-1) troque aj com aj-1 93 BubbleSort 94 Comparação z Selection Sort Æ comparações: n-1 + n-2 + … + 2 + 1 = n2/2 Æ trocas: n z Insertion Sort Æ comparações: (n-1 + n-2 + … + 2 + 1) / 2 = n2/4 Æ trocas: n2/4 z Bubble Sort Æ comparações: n-1 + n-2 + … + 2 + 1 = n2/2 Æ trocas: n2/2 95 Árvore de Decisão A complexidade de uma árvore de decisão é dada pela sua profundidade p, isto é, pela profundidade máxima de uma de suas folhas. No caso do problema de ordenação, cada uma das folhas da árvore de decisão deverá estar associada a uma possível ordenação dos n elementos. Como há n! ordenações possíveis, a árvore possui no mínimo n! folhas. Mas o número máximo possível de folhas é obtido quando todas as folhas ocorrem a profundidade p e cada nó que não é uma folha tem exatamente 2 descendentes. Assim, o número de folhas é igual ao número de nós à profundidade p que é 2p. 96 Árvore de Decisão Logo, a profundidade p de uma árvore de decisão que possua pelo menos n! folhas satisfaz 2p ≥ n , isto é, p ≥ log2 (n!) Mas a aproximação de Stirling para n! é ( e) n!= 2 Π n n ou seja: log 2 (n!) = log 2 ( n ) 2Π n + n log 2 n − n log 2 e ≥ kn log n Logo, como existe um algoritmo de complexidade O(n log n), concluímos que a complexidade do problema de ordenação é Θ(n log n). 97 Definição 2 Dizemos que a complexidade de um problema P tem cota inferior dada por Ω(f (n)) se existe uma constante k tal que todo algoritmo que resolve P requer pelo menos k f (n) passos para resolver alguma instância de tamanho n. Dizemos que a complexidade de P é Θ(f (n)) se, além disso, existir um algoritmo de complexidade O(f (n)) para P. Neste caso, dizemos que o algoritmo é ótimo para P. 98 Análise de Algoritmos z Medidas de Consumo dos Recursos Computacionais Æ Θ (f) Cota assintótica superior Æ Ο (f) Ordem Æ Ω (f) Cota assintótica inferior z Contabilidade Æ por pontos de verificação ` em geral entrada de loops Æ por rateio (usado em grafos) ` centros de custo 99 Exemplo: Régua comum Entrada: número de marcas n Saída: régua com n marcas regua(n) para i = 1 até n faça marque(i,”|”) fim_para ... ⇒ Ο(n) 100 Exemplo: Régua binária Entrada: número de marcas n Saída: régua com n marcas n = 2h (h marcas diferentes) regua_binaria(l,r,k) m = (l + r) / 2 marque(l,m,k) se (k > 1) então regua_binaria(l,m,k-1) regua_binaria(m,r,k-1) 101 Recorrência z Vários algoritmos, particularmente os baseados no paradigma Dividir-para-Conquistar, tem complexidades que são naturalmente modeladas por relações de recorrência. z Uma relação de recorrência é uma equação que é definida em termos dela mesma. z Várias funções naturais são facilmente expressas como recorrências: Æ an = an-1 + 1, a1 = 1 → an = n (polinomial) Æ an = 2 * an-1, a1 = 1 → an = 2n-1 (exponencial) Æ an = n * an-1, a1 = 1 → an = n! (explosão combinatória) 102 Indução z Recursão é uma indução matemática Æ Temos condições gerais e de fronteira, com a condição geral dividindo em partes cada vez menores o problema. Æ A condição de fronteira (ou inicial) termina a recursão. z Nenhum procedimento (geral) é conhecido para se resolver relações de recorrência. z A indução provê uma ferramenta para resolver recorrências: Adivinhar a solução e prová-la por indução. 103 Prova por Indução n Tn Tn = 2 * Tn-1 + 1, T0 = 0 0 1 2 3 4 5 6 7 0 1 3 7 15 31 63 127 z Qual a solução ? Prove que é Tn = 2n -1 por indução. Æ Mostre a condição básica: T0 = 20 - 1 = 0 Æ Assuma que é verdade para Tn-1 Æ Partindo da afirmação anterior, mostre que Tn = 2 * Tn-1 + 1 = 2 (2n-1 - 1) + 1 = 2n - 1 104 Exemplo: Régua binária Entrada: número de marcas n Saída: régua com n marcas n = 2h (h marcas diferentes) regua_binaria(l,r,k) m = (l + r) / 2 marque(l,m,k) se (k > 1) então }⇒ c regua_binaria(l,m,k-1) ⇒ T(n/2) regua_binaria(m,r,k-1) ⇒ T(n/2) 105 Exemplo: Régua binária T(n) = 2 T(n/2) + c = 2 [ 2 T(n/4) + c] + c = c + 2c + 4 T(n/4) = c + 2c + 4c + 8c + … + 2i T(n/2i) mas, T(2) = c T(n) = c + 2c + 4c + 8c + … + 2i-1 T(2) = c (1 + 2 + 22 + 23 + … + 2h-1) = c (20 + 21 + 22 + 23 + … + 2h-1) = c (2h - 1) = c (n - 1) T(n) = c (n - 1) ⇒ T(n) = O(n) 106 Recorrências Usuais em DPC ck n= z T(n) = a T(n/c) + k n Esforço de combinação Æ a → fator de crescimento dos sub-problemas Æ c → fator de divisão (tamanha dos sub-problemas) T(n) = O(n) Æa<c T(n) = O(n log n) Æa=c T(n) = O(nlogc a) Æa>c z T(n) = T(n/c) + k Æ T(n) = O(logc n) p.ex.: busca binária 107 Exemplos T(n) = 9 T(n/3) + n ` T(n) = O(n2) T(n) = T(2n/3) + 1 ` T(n) = (log n) T(n) = 3 T(n/4) + n log n ` T(n) = O(nlog4 3) = O(n0.793) 108 HeapSort z Construindo a heap 109 HeapSort z “Ordenando” a heap 110 Radix Sort z Até agora, foi razoável definir métodos de ordenação em termos de operações básicas de comparação e troca de dois elementos quaisquer. z Entretanto, para algumas aplicações é possível tirar vantagem de que os elementos são números dentro de um intervalo. z Esse métodos são chamados de Radix Sorts. Æ Não somente comparam os elementos. Æ Processam e comparam pedaços dos elementos. 111 Radix Sort 329 457 657 839 436 720 355 720 355 436 457 657 329 839 720 329 436 839 355 457 657 329 355 436 457 657 720 839 Qual a complexidade deste algoritmo ? 112 Radix Sort 113 Radix Sort (exchange) radix_sort (l,r,b) if (r > l) and (b >= 0) then i = l; j = r; repeat while (bits(a[i],b,1)=0) and (i<j) do i=i+1; while (bits(a[j],b,1)=1) and (i<j) do j=j+1; t=a[i]; a[i]=a[j]; a[j]=t; until j=i; if (bits(a[r],b,1)=0) then j = j+1; radix_sort(l,j-1,b-1); radix_sort(j,r,b-1); 114 Radix Sort (straight) 115 Redução z z Os resultados obtidos a respeito do problema de ordenação são úteis para estabelecer cotas inferiores para vários problemas computacionais. Para tal, recorreremos a um mecanismo que consiste em reduzir um problema a outro. 116 Definição 3 Um problema P1 é redutível (em tempo linear) a um problema P2 se dada uma instância de tamanho n de P1 for possível, em tempo O(n), obter uma instância de I2 de P2 tal que a resposta de P1 para I1 possa ser obtida, em tempo O(n), a partir da resposta de P2 para I2. Neste caso, escrevemos P1∝ P2 . 117 118 Algoritmos de Busca z z z z z z Linear Search Binary Search Binary Search Tree B-Tree Hashing Quadtree 119 Busca Linear z Este método de procurar dados é direto e fácil entender. Æ Para achar um determinado dado, comece sua procura ao começo do conjunto de dados e continue ou olhando até você achar, ou acabar o espaço de procura. Æ A complexidade deste tipo de procura é O(n) porque, no pior caso serão examinados todos os dados no espaço de procura. z Como nós veremos adiante, existem muitos algoritmos que podem melhorar tempo de procura. Por exemplo, o algoritmo de busca binária opera muito mais eficazmente que uma busca linear mas requer que o conjunto de dados esteja ordenado. 120 Busca Binária z Para se determinar se um elemento a está no vetor A, comparamos a com o elemento b da posição mediana do vetor A. Se a=b então “sim”. Senão, repetimos o processo na primeira metade de A se a<b, ou na segunda metade de A se a<b. z Pela divisão sucessiva do espaço de busca, nunca faremos mais de log n+1 comparações para achar a, ou que a ∉ A. 121 Busca Binária busca_bin(a,f,l) se (f > l) então retorne “não” senão se (a = A[(f+l)/2]) então retorne “sim” senão se (a < A[(f+l)/2]) então busca_bin(a,f,(f+l)/2-1) senão busca_bin(a,(f+l)/2+1,l) 7? 32 ? não sim 2 3 6 8 12 20 24 29 32 38 46 55 122 Árvore de Busca Binária - BST Definição: Uma árvore de busca binária é uma árvore binária onde cada vértice v é identificado por um elemento l(v) ∈ S tal que: Æ para cada vértice u na sub-árvore esquerda de v, l(u) < l(v) Æ para cada vértice u na sub-árvore direita de v, l(u) > l(v) Æ para cada elemento a ∈ S, existe um único vértice v tal que l(v) = a. z A operação mais comum realizada em uma BST é a busca por um elemento armazenado na árvore. No entanto, também se pode realizar mínimo, máximo, sucessor e predecessor. z Todas essas operações são feitas em tempo O(h) em uma BST de altura h. 123 Árvore de Busca Binária search_BST(13) ⇒ 15 → 6 → 7 → 13. min_BST() ⇒ 15 → 6 → 3 → 2. max_BST() ⇒ 15 → 18 → 20. suc_BST(15) ⇒ min_BST(right[15]) → 17. pre_BST(15) ⇒ max_BST(left[15]) → 13. 15 6 3 2 18 7 17 20 13 4 9 124 BST: Busca, Min e Max search_BST(x,k) if x = nil or x = key[x] then return x if k < key[x] then return search_BST(left[x],k) else return search_BST(right[x],k) min_BST(x) while left[x] ≠ nil do x ← left[x] return x max_BST(x) while right[x] ≠ nil do x ← right[x] return x 125 BST: Sucessor e Predecessor suc_BST(x) if right[x] ≠ nil then return min_BST(right[x]) y ← parent[x] while y ≠ nil and x = right[y] do x ← y y ← parent[y] return y pre_BST(x) if left[x] ≠ nil then return max_BST(left[x]) y ← parent[x] while y ≠ nil and x = left[y] do x ← y y ← parent[y] return y 126 BST: Inserção insert_BST(T,z) y ← nil x ← root[T] while x ≠ nil do y ← x if key[z] < key[x] then x ← left[x] else x ← right[x] parent[z] ← y if y = nil then root[T] ← z else if key[z] < key[y] then left[y] ← z else right[y] ← z 127 BST: Inserção 128 BST: Remoção delete_BST(T,z) if left[z] = nil or right[z] = nil then y ← z else y ← suc_BST(z) if left[y] ≠ nil then x ← left[y] else x ← right[y] if x ≠ nil then parent[x] ← parent[y] if parent[y] = nil then root[x] ← x else if y = left[parent[y]] then left[parent[y]] ← x else right[parent[y]] ← x if y ≠ z then key[z] ← key[y] return y 129 BST: Remoção Nó não tem filhos. Nó tem 1 filho. Nó tem 2 filhos. 130 Balanced Trees z z 2-3-4 Tree Red-Black Tree 131 2-3-4 Tree z Para eliminar o pior caso da BST, precisamos de alguma flexibilidade na estrutura de dados. z Para obter esta flexibilidade, permitimos que os nós da árvore possam conter mais de um elemento. Æ Especificamente, permite-se 3-nodes ou 4-nodes, que podem conter dois ou três elementos respectivamente. Æ Os nós padrões (BST) 2-nodes possuem um elemento e dois links. 132 2-3-4 Tree E X A M P L E 133 Red-Black Trees z É uma BST com um bit extra por nó: sua cor, que pode ser “red” ou “black”. z Por restrição, a forma como os nós são coloridos, por qualquer caminho, da raiz para as folhas assegura que nenhum caminho é mais do que duas vezes maior que qualquer outro. Assim, é aproximadamente balanceada. z Propriedades: Æ Todo nó é red ou black sendo que toda folha (nil) é black. Æ Se um nó é red, então os filhos são black. Æ Todo caminho de um nó para um descendente, tem o mesmo número de nós black. 134 Red-Black Tree Uma red-black tree com n nós internos tem no máximo 2 log(n +1). 135 Heap e Heap Tree z Heap = garbage-collected storage z Heap Tree: É uma BSP (a) que possui um vetor associado (b). 136 Heap Tree z A Heap Tree tem as seguintes propriedades: Æ A[parent(i)] ≥ A[i] Æ parent(i) { return (i/2) } Æ left(i) { return (2*i) } Æ right(i) { return (2*i + 1) } A 137 Heapify: Corrigir a Heap A[2], i = 2 → violou a propriedade da heap heapify(A,2) → troca A[2] com A[4] A[4], i = 4 → violou a propriedade da heap heapify(A,4) → troca A[2] com A[4] A[9], i = 9 → propriedade da heap ok! Heapify(A,9) → não precisa fazer nada 138 Heapify T(n) heapify(a,i) T(n)==T(2n/3) T(2n/3)++cc T(n) T(n)==O(log O(logn) n) l ← left(i) r ← right(i) Obs.: Obs.:Alternativamente, Alternativamente,podemos podemos if A[l] > A[i] and l ≤ heap_size[A] caracterizar caracterizarootempo tempode deexecução execução then largest ← l do doheapify heapifyem emum umnó nóde dealtura alturahh com else largest ← i comO(h). O(h). if A[r] > A[largest] and r ≤ heap_size[A] then largest ← r if largest ≠ i then exchange(A[i],A[largest]) heapify(A,largest) 139 Construindo a Heap Tree z Podemos usar a heapify para converter um array A em uma heap. z Uma vez que os elementos do sub-array A[n/2+1..n] são todos folhas da árvore, cada um é um heap para se iniciar. build_heap(A) heap_size[A] ← length[A] for i = length[A] / 2 downto 1 do heapify(A,i) 140 Heap 141 Heap Sort z Construir uma Heap Tree (build_heap) Æ Maior elemento do array que é armazenado na raiz deve ser colocado no seu lugar correto A[n] e então basta chamar a heapify(A,1) Heapsort heap_sort(A) HeapsortééO(n O(nlog logn) n) pois: pois: build_heap(A) build_heap build_heapéé O(n) O(n) for i ← length[A] downto 2 heapify heapifyéé O(log O(logn) n)** n-1 n-1 do exchange(A[1],A[i]) heap_size[A] ← heap_size[A] - 1 heapify(A,1) 142 Heap Sort build_heap heapify 143 Inserindo elementos na Heap Tree Insere uma folha heap_insert(A,key) heap_size[A] ← heap_size[A]+1 i ← heap_size[A] while i > 1 and A[parent(i)] > key do A[i] ← A[parent(i)] i ← parent(i) A[i] ← key Desce os elementos um nível, desde a nova folha até o local correto Insere o 15 144 B-Tree z São balanced search trees projetadas para trabalhar em memória secundária, tais como discos, fitas ou outro dispositivo de armazenamento secundário de acesso direto. z Diferem das red-black trees e 2-3-4 trees pois podem ter vários filhos, de unidades a milhares. z A característica de “branching factor” de uma B-tree é determinada pelo dispositivo de armazenamento utilizado. 145 Propriedades da B-Tree z Todo nó x tem os seguintes dados: Æ Æ Æ n[x], o número de elementos armazenados no nó x; os n[x] elementos armazenados de forma ordenada; leaf[x], indica se é uma folha (true) ou um nó (false). z Cada folha tem a mesma profundidade, que é a altura h da árvore. z Existem limites, inferior e superior, que um nó pode conter. Esses limites podem ser expressos em termos de um inteiro fixo t ≥ 2 chamado grau mínimo da B-tree. Æ Æ Exceto o nó raiz, cada nó tem que ter ao menos t-1 elementos e tem pelo menos t filhos. Se a árvore não for vazia, o nó raiz tem que conter pelo menos um elemento. Cada nó pode conter no máximo 2t-1 filhos e no máximo 2t filhos. O nó estará cheio quando conter exatos 2t-1 elementos. 146 Busca na B-Tree z Alguns detalhes: Æ A raiz da B-tree esta sempre na memória principal. Æ Todos os nós utilizados tem que ser previamente lidos para a memória principal. z Searching a B-Tree Æ É parecida com a BST, exceto que ao invés de uma escolha binária a cada nó, teremos uma escolha múltipla dependente do número de filhos. Æ Mais precisamente, a cada nó teremos n[x]+1 escolhas a decidir. 147 Inserindo elementos na B-Tree Supondo t = 3, cada nó pode ter no máximo 5 elementos. 148 Retirando elementos da B-Tree 149 Hashing z Uma abordagem completamente diferente da baseada em comparações é conhecida como hashing: referencia registros em uma tabela através de operações aritméticas que convertem o elemento em um endereço da tabela. z Hash function: converte o elemento de busca em um endereço da tabela. z Collision-resolution: trata o problema de dois ou mais elementos serem convertidos para um mesmo endereço da tabela. 150 Hash Function z Como as funções serão aritméticas, o primeiro passo é converter o elemento em números. z O métodos mais comum é escolher um número primo M que, para qualquer elemento k, calcular hash(k) = k mod M. z Exemplos: Æ M = 101, elemento “AKEY” = 44217 ⇒ 44217 mod 101 = 80 Æ Mas, se o elemento for “BARH”, o resultado também é 80. 151 Tratamento de Colisões Tratamento da colisão por listas encadeadas. 152 Separate Chaining M = 11 153 Linear Probing z Se o número de elementos N é previamente conhecido e se M > N, então existirão espaços vazios na tabela. Os métodos que se aproveitam disso são chamados de open-addressing. z Destes, o método mais simples é conhecido por linear probing. Æ Quando existir uma colisão, simplesmente teste (probe) a(s) posição(ões) seguinte(s). 154 Linear Probing M = 19 155 Linear Probing 156 Double Hashing z Em linear probing, principalmente quando a tabela começa a encher, várias posições tem que ser examinadas para se poder inserir um elemento. z Ainda pior, geralmente ocorre em vários lugares da tabela um agrupamento, denominado clustering, fazendo com que o desempenho caia muito. z No entanto, existe um forma fácil de resolver este problema, denominada double hashing: em caso de colisão, utilizamos uma outra função de hashing. 157 Double Hashing M = 19 158 Double Hashing 159 Grafos z Vários problemas são naturalmente modelados por objetos e conexões entre eles. z Por exemplo: Æ Caminho mínimo: ` Qual o menor caminho entre a cidade A e a cidade B ? Æ Conectividade: ` O interruptor A está conectado a lâmpada B ? Æ Fluxos: ` Para fazer a tarefa A, precisamos antes fazer a B e C. z Um grafo (graph) é um objeto matemático que modela precisamente estes problemas. 160 Nomenclatura de Grafos Æ Um grafo é uma coleção de vértices (ou nós) e arestas. Æ Um caminho (path) entre os vértices a e b é uma lista sucessiva de vértices conectados por arestas. Æ Um grafo é dito conectado se existe um caminho de cada nó para qualquer outro. Æ Um ciclo é um caminho em que começa e termina no mesmo vértice. 161 Nomenclatura de Grafos Æ Um grafo sem ciclos é chamado de árvore. Æ Um grupo de árvores desconectadas é chamada de floresta. Æ Uma spanning tree de um grafo é um sub-grafo que contém todos os vértices mas apenas as arestas necessárias para formar uma árvore. 162 Nomenclatura de Grafos z Além dos tipos anteriores, denominados não dirigidos (undirected graphs), existem tipos de grafos mais complicados, onde algumas informações são atribuídas aos vértices e/ou as arestas. z Quando associamos a cada aresta uma informação, um custo ou uma distancia por exemplo, denomina-se weighted graphs. z Quando as arestas possuem uma única direção, ou seja, uma aresta conecta o vértice a ao vértice b mas não o inverso, é dito que temos um grafo dirigido (directed graphs). z Os grafos que possuem as duas características anteriores, são chamados directed weighted graph ou de networks. 163 Representação de Grafos Grafo Lista de adjacências Matriz 164 Busca em Grafos z Problema: Dado um vértice inicial, queremos percorrer o grafo visitando todos os vértices possíveis de serem alcançados a partir do vértice inicial. z Os dois algoritmos mais usados em árvores, ou seja, grafos sem ciclos, são a busca em largura e a busca em profundidade. Æ Breadth-First Search Æ Depth-First Search 165 Depth-First Search - DFS Também conhecido como backtracking, faz um caminho partindo do vértice inicial e vai até o mais longe possível no grafo. Æ Cada nova aresta percorrida tem que ser uma aresta ainda não usada pelo algoritmo. Æ O algoritmo continua até atingir um vértice que não possua arestas ou que conduzam a vértices ainda não visitados. A partir deste vértice, retornamos ao vértice anterior e escolhemos uma nova aresta. Este procedimento é feito até que todas as arestas sejam percorridas e todos os vértices visitados. 166 Depth-First Search ? 167 DFS (com matriz) visit(k) id = id + 1; val[k] = id para t = 1 até V faça se a[k,t] então se val[t]=0 então visit(t); dfs() id = 0; para k = 1 até V faça val[k] = 0; para k = 1 até V faça se val[k] = 0 então visit(k); 168 DFS (com listas) visit(k) id = id + 1; val[k] = id t = next[k]; enquanto t ≠ nil faça se val[t]=0 então visit(t); t = next[t]; dfs() id = 0; para k = 1 até V faça val[k] = 0; para k = 1 até V faça se val[k] = 0 então visit(k); 169 Breadth-First Search - BFS z DFS “explora” o grafo procurando novos vértices cada vez mais distante do vértice inicial e só utiliza vértices mais próximos quando não existe nada “mais distante” naquele caminho. z BFS “explora”, primeiro, todos os vértices mais próximos do vértice inicial, só utilizando vértices mais distantes depois que todos os vértices próximos forem visitados. z É também chamada de busca em amplitude. 170 Breadth-First Search 171 BFS (com listas) visit(k) queue(k); faça k = dequeue(); id = id + 1; val[k] = id; t = next[k] enquanto t ≠ nil faça se val[t] = 0 então queue(t); val[t] = -1; t = next[t]; até queue_empty(); 172 DFS x BFS DFS 1/3 BFS 2/3 1/3 2/3 173 Árvore Geradora Mínima z z Minimum Spanning Tree Algoritmo de Prim 174 MST = 16 175 Algoritmo de Prim z z Segue a estratégia do guloso (greedy) Existem três tipos de vértices: Æ os vértices que já estão na árvore mínima (S) Æ os adjacentes aos vértices da árvore (F de fringe) Æ os vértices ainda não examinados (U de unseen) V=S∪F∪U 176 Algoritmo de Prim 177 Algoritmo de Prim 1. Inicie com qualquer vértice v S = {V} F = {vértices adjacentes} U = {vértices restantes} 178 Algoritmo de Prim 2. Construa a MST Usa-se heappara Usa-seuma umaheap paraarmazenar armazenar os osvértices vérticesde deFF.. OOmenor heap. menorpeso pesofica ficana naraiz raizda daheap. repita ache aresta (v,w) de menor peso tal que v∈S e w∈F inclua (v,w) na MST inclua w a S atualize F até S = V. 179 Algoritmo de Prim: passo-a-passo 180 Algoritmo de Prim: passo-a-passo 181 Caminho Mínimo z z Shortest Paths Algoritmo de Dijkstra origem destino 182 Algoritmo de Dijkstra 1. Adicione um vértice de cada vez ao caminho mínimo, escolhendo o vértice mais próximo a um vértice da árvore. 2. Os vértice são divididos em unseen, fringe e tree. 3. Os vértices vão de unseen para fringe via da operação de insert. 4. Os vértices vão de fringe para tree via operação de remove_min. 5. Atualiza-se a fringe sempre que um novo vértice for inserido na tree. 183 Algoritmo de Dijkstra 184 Algoritmo de Dijkstra 185 Algoritmo de Dijkstra 186 Algoritmo de Dijkstra 187 Algoritmo de Dijkstra d(PVD, SFO) = 200+1000+1500+800 d(PVD, SFO) = 3500 188 Caminho Mínimo em uma Superfície 3D 189 Caminho Mínimo em Mapas 190 Caminho Mínimo em Imagens: Detecção de Contorno 191 Redes de Fluxos z z Maximum Flow The Tao of Flow: Æ “Let your body go with the flow.” - Madonna, Vogue Æ “Maximum flow … because you’re worth it.” - Lóreal Æ “Use the flow, Luke!” - Obi-wan Kenobi, Star Wars 192 Redes de Fluxos z Possui dois vértices distintos dos demais: Æ Fonte s (source) e Tanque t (sink) z Os pesos (weights) das arestas são chamados de “capacidades”. 193 Fluxo e Capacidades z Capacidades: Æ Similares aos pesos dos grafos, mas não podem ser negativos. z Fluxo: Æ É função da rede de arestas. Æ 0 ≤ fluxo ≤ capacidade Æ Em cada vértice: fluxo entrando = fluxo saindo Æ Valor: combinação dos fluxos no tanque. 194 Fluxo e Capacidades 195 Problema do Fluxo Máximo “Dada uma rede de fluxos N, ache o fluxo f de valor máximo.” z Aplicações: Æ Tráfego Æ Sistemas hidráulicos Æ Circuitos Elétricos 196 Aumentando o Fluxo Fluxo da rede = 3 Caminhos aumentados Fluxo da rede = 4 ? 197 Caminhos Aumentados z Arestas para frente Æ fluxo < capacidade Æ fluxo pode ser aumentado! z Arestas para trás Æ fluxo > 0 Æ fluxo pode ser diminuído! z Teorema do Fluxo Máximo “Um fluxo tem um valor máximo se e somente se não tiver um caminho aumentado.” 198 Algoritmo de Ford & Fulkerson z inicialize a rede com fluxo igual a zero z Find_Flow() se existir um caminho aumentado então ache o caminho aumentado aumente o fluxo Find_Flow() 199 Achando o Fluxo Máximo 200 Roberto Beauclair tron@visgraf.impa.br tron@tecgraf.puc-rio.br tron@lncc.br 201