Prévia do material em texto
<p>Algoritmos e Complexidade</p><p>Professor - Matheus Johann Araújo</p><p>Sobre o docente</p><p>Formação:</p><p>► Técnico em Redes de Computadores</p><p>► Bacharel em Ciência da Computação</p><p>► Pós-Graduado em Docência do Ensino Superior</p><p>► Pós-Graduado em Gestão da Tecnologia da Informação</p><p>► Pós-Graduando em Business Intelligence, Big Data e Inteligência Artificial</p><p>► Mestrando em Ciência da Computação</p><p>Matheus Johann Araújo</p><p>Programador de Sistemas de Informação</p><p>Natural de Recife, possui uma sólida expertise em</p><p>programação, desenvolvimento web, bancos de dados, IoT</p><p>e robótica. Tem mais de 6 anos de experiência atuando</p><p>como desenvolvedor fullstack, instrutor e professor.</p><p>Sobre a ementa disciplina</p><p>Em resumo a ementa da disciplina é seguinte:</p><p>► 1. ANÁLISE DE ALGORITMO</p><p>► 2. RECURSIVIDADE</p><p>► 3. ALGORITMOS DE ORDENAÇÃO AVANÇADOS</p><p>► 4. ALGORITMOS EM ÁRVORES BINÁRIA E ÁRVORE AVL</p><p>► 5. ALGORITMOS EM GRAFOS</p><p>Procedimentos de avaliação</p><p>Sobre os procedimentos de avaliação</p><p>Os procedimentos de avaliação contemplarão as</p><p>competências desenvolvidas durante a disciplina por</p><p>meio de provas presenciais, denominadas AV e AVS, sendo</p><p>a cada uma delas atribuído o grau de 0,0 (zero) a 10</p><p>(dez) no formato PNI Prova Nacional Integrada.</p><p>Caso o aluno não atinja o resultado desejado na prova</p><p>de AV, ele poderá recuperar sua nota na prova de AVS.</p><p>Sobre os procedimentos de avaliação</p><p>Será composta por uma prova no formato PNI Prova</p><p>Nacional Integrada, com total de 10 pontos, e substituirá</p><p>a nota da AV, caso seja maior.</p><p>Para aprovação na disciplina, o aluno deverá, ainda:</p><p>atingir nota igual ou superior a 6 (seis) na prova de AV ou</p><p>AVS; frequentar, no mínimo, 75% das aulas ministradas.</p><p>Objetivos</p><p>Objetivo geral da disciplina</p><p>Analisar a complexidade computacional dos algoritmos</p><p>utilizando o conceito de Análise Assintótica, desenvolver</p><p>habilidades na implementação e análise de eficiência e</p><p>eficácia dos algoritmos, criar e comparar algoritmos</p><p>recursivos e de ordenação, e aplicar algoritmos de Árvores</p><p>de Pesquisas Binárias, Árvores AVL e Grafos para resolver</p><p>problemas combinatórios em computação.</p><p>1º Objetivo da específico disciplina</p><p>Analisar a complexidade computacional dos algoritmos</p><p>aplicados, utilizando -se do conceito de Análise Assintótica,</p><p>com objetivo de desenvolver habilidades de análise da</p><p>eficiência e eficácia dos algoritmos.</p><p>2º Objetivo da específico disciplina</p><p>Construir algoritmos recursivos, utilizando técnicas de</p><p>programação, para desenvolver habilidades de implementação</p><p>de algoritmos em pilhas de memória e interativas, além do</p><p>desenvolvimento de algoritmos importantes, melhorando a</p><p>legibilidade do programa.</p><p>3º Objetivo da específico disciplina</p><p>Implementar algoritmos de ordenação, desenvolvidos</p><p>através de exemplos e modelos propostos, a fim de propiciar</p><p>uma análise comparativa da complexidade computacional</p><p>desses algoritmos, além de desenvolver habilidade de escolha</p><p>daquela que melhor se adequa ao projeto de algoritmos.</p><p>4º Objetivo da específico disciplina</p><p>Aplicar algoritmos de Árvores de Pesquisas Binárias e</p><p>Árvores AVL e suas principais propriedades, através dos</p><p>conceitos apresentados na literatura, com o objetivo de</p><p>propiciar uma análise comparativa dessas estruturas.</p><p>5º Objetivo da específico disciplina</p><p>Aplicar os principais conceitos em Algoritmos de Grafos,</p><p>investigando sobre as suas principais características estruturais,</p><p>para desenvolver habilidades de programação e resolução de</p><p>problemas combinatórios em computação.</p><p>Conteúdo das aulas</p><p>Conteúdos a serem abordados nas aulas</p><p>1. ANÁLISE DE ALGORITMO</p><p>1.1 ALGORITMOS: FUNÇÕES E PASSAGEM DE PARÂMETROS</p><p>1.2 ESTRUTURA DE DADOS: HOMOGÊNEAS, HETEROGÊNEAS</p><p>E PONTEIRO</p><p>1.3 ANÁLISE DE ALGORITMOS: CONCEITOS, NOTAÇÃO O E</p><p>FUNÇÃO O</p><p>1.4 PRÁTICA DE ANÁLISE DE ALGORITMOS</p><p>Conteúdos a serem abordados nas aulas</p><p>2. RECURSIVIDADE</p><p>2.1 DEFINIÇÕES RECURSIVAS</p><p>2.2 COMO IMPLEMENTAR RECURSIVIDADE</p><p>2.3 DESENVOLVENDO ALGORITMOS COM RECURSIVIDADE</p><p>2.4 QUANDO NÃO USAR RECURSIVIDADE</p><p>Conteúdos a serem abordados nas aulas</p><p>3. ALGORITMOS DE ORDENAÇÃO AVANÇADOS</p><p>3.1 ANÁLISE DOS ALGORITMOS DE ORDENAÇÃO ELEMENTARES</p><p>3.1 ORDENAÇÃO POR INTERCALAÇÃO (MERGESORT)</p><p>3.2 ORDENAÇÃO RÁPIDA (QUICKSORT)</p><p>3.4 ORDENAÇÃO SHELLSORT</p><p>Conteúdos a serem abordados nas aulas</p><p>4. ALGORITMOS EM ÁRVORES BINÁRIA E ÁRVORE AVL</p><p>4.1 ÁRVORE BINÁRIA DE BUSCA: BUSCA, INSERÇÃO E</p><p>REMOÇÃO COM ANÁLISE DE COMPLEXIDADE</p><p>4.2 PERCURSO EM ÁRVORES BINÁRIA: ALGORITMOS DOS</p><p>PERCURSOS EM ORDEM, PÓS-ORDEM E PRÉ- ORDEM COM</p><p>RECURSIVIDADE E ANÁLISE DE COMPLEXIDADE</p><p>4.3 BALANCEAMENTO DE ÁRVORE: CONCEITOS E ALGORITMO</p><p>DSW E ANÁLISE DE COMPLEXIDADE</p><p>4.4 ÁRVORE AVL: CONCEITOS, PROPRIEDADES E ANÁLISE DE</p><p>COMPLEXIDADE</p><p>Conteúdos a serem abordados nas aulas</p><p>5. ALGORITMOS EM GRAFOS</p><p>5.1 CONCEITOS DE GRAFOS</p><p>5.2 REPRESENTAÇÃO DE GRAFO</p><p>5.3 ALGORITMOS DE BUSCA</p><p>5.4 ALGORITMO DO CAMINHO MÍNIMO</p><p>Algoritmos e Complexidade</p><p>O que são Algoritmos?</p><p>Algoritmos são sequências de instruções bem definidas que</p><p>visam resolver problemas ou realizar tarefas específicas.</p><p>Eles constituem a base para desenvolver soluções de</p><p>problemas computacionais.</p><p>A modularização de algoritmos é essencial para reduzir a</p><p>complexidade desses problemas, dividindo-os em partes</p><p>menores e mais manejáveis.</p><p>O que é Otimização?</p><p>Otimização é o processo de melhorar a eficiência de</p><p>um algoritmo ou sistema. Após a definição de um</p><p>algoritmo, a otimização é essencial para garantir um</p><p>desempenho mais eficiente.</p><p>Mesmo com a poderosa capacidade computacional dos</p><p>computadores modernos, a otimização continua sendo</p><p>vital, pois resulta em uma melhor experiência para o</p><p>usuário e maximiza o uso dos recursos disponíveis.</p><p>O que é Complexidade?</p><p>A complexidade refere-se à medida de dificuldade de um</p><p>problema ou sistema.</p><p>A complexidade dos problemas cresceu tão rápido quanto</p><p>a capacidade computacional, portanto, é fundamental a</p><p>capacidade de analisar diversos algoritmos para um</p><p>problema complexo para se chegar ao algoritmo mais</p><p>otimizado para o problema.</p><p>Sobre otimização e complexidade</p><p>Um algoritmo otimizado deverá executar em um menor</p><p>espaço de tempo possível, ocupando o menor espaço possível</p><p>de memória.</p><p>Dessa forma, a escolha adequada do algoritmo pode</p><p>significar a diferença entre uma solução viável e uma</p><p>inviável.</p><p>Além disso, a análise de complexidade ajuda a prever o</p><p>comportamento do algoritmo em diferentes cenários. Por</p><p>isso, entender e aplicar conceitos de complexidade é crucial</p><p>no desenvolvimento de soluções eficientes.</p><p>Uma visão sobre complexidade</p><p>A complexidade de um problema matemático</p><p>aumenta conforme o número de variáveis envolvidas,</p><p>enquanto a complexidade de um problema algorítmico</p><p>cresce com a quantidade de situações diferentes que</p><p>precisam ser abordadas.</p><p>A base de tudo que é programado para um</p><p>computador é o algoritmo, que pode ser definido como</p><p>uma sequência finita de etapas, bem definidas,</p><p>utilizadas para solucionar um problema específico.</p><p>Complexidade de um algoritmo</p><p>Cada algoritmo possui uma complexidade que está</p><p>diretamente ligada à complexidade do problema a ser</p><p>resolvido.</p><p>Quanto maior a variedade de situações a serem tratadas</p><p>pelo algoritmo, maior será sua complexidade.</p><p>Para reduzir a complexidade, é possível diminuir a</p><p>variedade de situações, dividindo problemas maiores em</p><p>problemas menores, que são mais fáceis de tratar e</p><p>implementar através de sub-rotinas.</p><p>Complexidade de um algoritmo</p><p>A técnica chamada top-down é utilizada para a</p><p>decomposição de problemas, ajudando a definir os</p><p>subprogramas necessários para resolvê-los.</p><p>Essa abordagem divide um problema grande em partes</p><p>menores e mais manejáveis, reduzindo a complexidade geral e</p><p>facilitando a implementação de soluções mais eficazes.</p><p>Módulos/Subprogramas</p><p>O que são Módulos/Subprogramas?</p><p>Os módulos ou subprogramas são componentes de um</p><p>programa que tratam partes menores e específicas da</p><p>complexidade do problema.</p><p>Eles facilitam a compreensão e a manutenção do</p><p>software ao longo</p><p>de seu ciclo de vida.</p><p>A modularização também reduz o retrabalho, pois</p><p>permite que trechos de código sejam reutilizados em</p><p>diferentes partes do mesmo sistema.</p><p>Descrição de Módulo</p><p>Módulos são unidades de código independentes e coesas que</p><p>realizam funções específicas dentro de um programa maior.</p><p>Eles ajudam a dividir a complexidade do sistema em partes</p><p>menores e mais gerenciáveis, tornando o desenvolvimento e a</p><p>manutenção do software mais eficientes.</p><p>Descrição de Subprograma</p><p>Subprogramas, por outro lado, são funções ou</p><p>procedimentos definidos dentro de um módulo que</p><p>executam tarefas específicas.</p><p>Eles são chamados por outros subprogramas ou pelo</p><p>programa principal para realizar operações específicas,</p><p>promovendo a reutilização de código e a organização lógica</p><p>do software.</p><p>Sobre as sub-rotinas</p><p>Sub-rotinas, também chamadas de subprogramas, são blocos</p><p>de instruções que realizam tarefas específicas.</p><p>Esses trechos de código têm atribuições definidas,</p><p>simplificando o entendimento do programa principal, reduzindo</p><p>as chances de erro e diminuindo a complexidade do software.</p><p>Elas são utilizadas para lidar com problemas complexos de</p><p>maneira mais manejável.</p><p>Sobre as sub-rotinas</p><p>A utilização de sub-rotinas torna os programas menores e</p><p>mais organizados, pois permite que um problema seja</p><p>subdividido em tarefas menores e mais simples.</p><p>Em resumo, sub-rotinas são pequenos programas</p><p>projetados para resolver problemas específicos. Uma</p><p>sub-rotina não deve ser escrita para resolver múltiplos</p><p>problemas, pois isso comprometeria sua eficácia e propósito.</p><p>Objetivos das sub-rotinas</p><p>► Dividir e estruturar um algoritmo em partes</p><p>logicamente coerentes.</p><p>► Facilidade em testar os trechos em separado.</p><p>► Aumentar a legibilidade de um programa.</p><p>► Evitar que uma certa sequência de comandos</p><p>necessária em vários locais de um programa tenha</p><p>que ser escrita repetidamente nestes locais,</p><p>diminuindo também, o código fonte.</p><p>Vantagens no uso de sub-rotinas</p><p>► Clareza e legibilidade no algoritmo.</p><p>► Construção independente.</p><p>► Testes individualizados.</p><p>► Simplificação da manutenção.</p><p>► Reaproveitamento de algoritmos.</p><p>Sobre o uso das sub-rotinas</p><p>Com as sub-rotinas o programador terá a capacidade de</p><p>desenvolver sua própria biblioteca de funções, o que</p><p>contribuirá para uma maior eficiência em sua programação.</p><p>Dessa forma, ele poderá utilizar funções previamente</p><p>criadas em diversos programas, beneficiando-se da vantagem</p><p>de já terem sido testadas.</p><p>Decomposição de Problemas</p><p>Decomposição de Problemas</p><p>Um método eficaz para decompor problemas é a aplicação</p><p>do conceito de programação estruturada.</p><p>A maioria das linguagens de programação modernas é</p><p>compatível com esse paradigma, o que facilita sua</p><p>implementação.</p><p>De acordo com Manzano e Oliveira (2016), a abordagem</p><p>mais recomendada para aplicar a técnica de decomposição de</p><p>problemas é o método top-down.</p><p>Decomposição de problemas usando</p><p>estrutura top-down (“organograma”)</p><p>Decomposição de problemas por top-down</p><p>A utilização do método top-down</p><p>permite que seja realizada uma</p><p>divisão de problemas em refinamentos</p><p>sucessivos.</p><p>Cada divisão obtida com a técnica</p><p>de refinamentos sucessivos pode ser</p><p>convertida uma parte do algoritmo.</p><p>Essas partes são conhecidas como</p><p>módulos ou sub-algoritmos.</p><p>Sobre sub-rotina</p><p>Uma sub-rotina é um bloco contendo início e fim, sendo</p><p>identificada por um nome, pelo qual será referenciada em</p><p>qualquer parte e em qualquer momento do programa.</p><p>Como uma sub-rotina é um programa, ela poderá efetuar</p><p>diversas operações computacionais, como entrada,</p><p>processamento e saída, da mesma forma que são executadas</p><p>em um programa. De modo geral, uma sub-rotina serve para</p><p>executar tarefas menores, como ler, calcular, determinar o</p><p>maior/menor valor entre uma lista de valores, ordenar,</p><p>converter para maiúsculas, entre outras.</p><p>Sintaxe genérica de uma sub-rotina</p><p>Descrição dos elementos da sub-rotina</p><p>Tipo de retorno: Tipo de dado que a sub-rotina dará retorno.</p><p>Sequência de declarações de parâmetros: Declarações de</p><p>variáveis da sub-rotina (tipo e nome).</p><p>Corpo da sub-rotina: Sequência de comandos.</p><p>Nome da sub-rotina: Segue as mesmas regras de declaração</p><p>de variáveis da linguagem utilizada.</p><p>Início: Início da sub-rotina.</p><p>Descrição dos elementos da sub-rotina</p><p>Retorne: O que será retornado ou não para o algoritmo.</p><p>parâmetros</p><p>Nomes das variáveis: Seguem as mesmas regras de</p><p>declaração de variáveis da linguagem utilizada.</p><p>Variáveis locais: Declarações de variáveis que serão utilizadas</p><p>dentro da sub-rotina (tipo e nome).</p><p>Fim sub-rotina: Fim da sub-rotina.</p><p>Declaração de sub-rotina</p><p>Aspectos a respeito da declaração</p><p>da sub-rotina.</p><p>Ela deve estar entre o final da</p><p>declaração de variáveis e a linha de</p><p>início do programa principal.</p><p>Chamada sub-rotina</p><p>Uma sub-rotina pode ser acionada de qualquer ponto do</p><p>algoritmo principal ou de outra sub-rotina. O acionamento de</p><p>uma sub-rotina é conhecido por chamada ou ativação.</p><p>Quando ocorre uma chamada, o fluxo de controle é</p><p>desviado para a sub-rotina, quando ela é ativada no algoritmo</p><p>principal.</p><p>Ao terminar a execução dos comandos da sub-rotina, o</p><p>fluxo de controle retorna ao comando seguinte àquele onde</p><p>ela foi ativada.</p><p>Chamada de sub-rotina</p><p>Múltiplas sub-rotinas</p><p>Um algoritmo pode incluir múltiplas sub-rotinas,</p><p>resultando em várias chamadas a partir do programa</p><p>principal. Cada sub-rotina é executada de forma</p><p>independente, e o controle retorna ao programa principal</p><p>após a conclusão da execução de cada uma.</p><p>Por exemplo, em um algoritmo com duas sub-rotinas, a</p><p>execução segue o fluxo das chamadas: o controle é</p><p>transferido para a primeira sub-rotina e retorna ao programa</p><p>principal ao finalizar. O mesmo processo acontece para a</p><p>segunda sub-rotina, com o controle retornando ao programa</p><p>principal que continua sua execução normal.</p><p>Ilustração da execução de algoritmo com</p><p>ativação de múltiplas sub-rotinas</p><p>Parametrização de sub-rotinas</p><p>A parametrização de sub-rotinas permite torná-las mais</p><p>genéricas e reutilizáveis, utilizando parâmetros para</p><p>receber valores antes da execução.</p><p>Parâmetros são os dados que a sub-rotina pode aceitar e</p><p>processar, facilitando a adaptação da função para</p><p>diferentes situações.</p><p>Parametrização de sub-rotinas</p><p>Para ativar uma sub-rotina parametrizada, é necessário</p><p>fornecer os argumentos correspondentes, que podem ser</p><p>valores constantes ou variáveis.</p><p>Por exemplo, uma sub-rotina para exibir a tabuada de um</p><p>número específico pode ser generalizada para calcular a</p><p>tabuada de qualquer número, ao passar o valor desejado</p><p>como parâmetro.</p><p>Exemplo de sub-rotina que realiza a troca</p><p>de valores recebidos em seus parâmetros</p><p>Sobre o exemplo de sub-rotina</p><p>No algoritmo descrito, a sub-rotina é definida entre as</p><p>linhas 05 e 13, e sua chamada ocorre na linha 17.</p><p>Nessa sub-rotina, os valores das variáveis a e b são</p><p>passados para as variáveis x e y, respectivamente.</p><p>Isso significa que a é copiado para x e b é copiado para y,</p><p>e essas cópias são usadas dentro da sub-rotina.</p><p>Sobre passagem de parâmetros por valor</p><p>Na passagem de parâmetros por valor, como é o caso do</p><p>exemplo, os valores das variáveis são copiados para a</p><p>sub-rotina, e qualquer modificação feita dentro da</p><p>sub-rotina não afeta as variáveis originais.</p><p>Portanto, no exemplo dado, mesmo que x e y sejam</p><p>alterados dentro da sub-rotina, os valores originais de a e b</p><p>permanecem inalterados.</p><p>Sobre passagem de parâmetros por referência</p><p>Por outro lado, a passagem por referência permite que a</p><p>sub-rotina acesse diretamente os endereços de memória das</p><p>variáveis, possibilitando a modificação dos valores originais.</p><p>Se a passagem de parâmetros na sub-rotina troca</p><p>(inteiro: x, y) fosse feita por referência, então as variáveis a</p><p>e b teriam seus valores trocados, refletindo as alterações</p><p>realizadas dentro da sub-rotina.</p><p>Categorias de sub-rotinas</p><p>Sub-rotinas são blocos de código que podem ser</p><p>chamados a partir de diferentes partes de um programa,</p><p>permitindo a modularização e a reutilização do código.</p><p>Existem duas principais categorias de sub-rotinas:</p><p>funções e procedimentos.</p><p>O que são Funções?</p><p>Funções são sub-rotinas que recebem parâmetros e</p><p>retornam um valor ao programa principal, realizando cálculos</p><p>ou processamentos que produzem um resultado específico.</p><p>Por exemplo, uma função pode somar números e devolver</p><p>o resultado dessa soma ao programa principal.</p><p>O que são Procedimentos?</p><p>Procedimentos são sub-rotinas que também podem</p><p>receber parâmetros, mas não retornam um valor diretamente</p><p>ao programa principal.</p><p>Eles executam uma série de operações ou comandos, mas</p><p>o resultado é geralmente exibido ou modificado diretamente</p><p>dentro do escopo do procedimento.</p><p>Em algumas linguagens de programação, tanto funções</p><p>quanto procedimentos são usados, mas a diferença principal</p><p>está na presença ou ausência de um valor de retorno.</p><p>Função versus Procedimento</p><p>Bibliografia</p><p>Bibliografia básica</p><p>► CORMEN, Thomas H.; LEISERSON, Charles E.; RIVEST, Ronald L. et al.</p><p>Algoritmos. Rio de Janeiro: GEN LTC, 2024. Disponível em:</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595159914</p><p>► SERPA, Matheus da Silva; RODRIGUES, Thiago Nascimento; ALVES, Ítalo</p><p>Colins et al. Análise de Algoritmos. Porto Alegre: SAGAH, 2021. Disponível</p><p>em: https://integrada.minhabiblioteca.com.br/#/books/9786556901862</p><p>► Thomas H. Cormen; Charles E. Leiserson; Ronald L. Rivest; Stein, Clifford.</p><p>Algoritmos: Teoria e Prátic. Rio de Janeiro: Elsevier Editora Ltda, 2012.</p><p>Disponível em:</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595158092/cfi/6</p><p>/4!/4/2/2@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595159914</p><p>https://integrada.minhabiblioteca.com.br/#/books/9786556901862</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595158092/cfi/6/4!/4/2/2@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595158092/cfi/6/4!/4/2/2@0:0</p><p>Bibliografia complementar</p><p>► Drozdek, Adam. Estrutura de dados e algoritmos em C++. São Paulo:</p><p>4a Edição. Disponível em:</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788522126651/</p><p>cfi/0!/4/4@0.00:0.00</p><p>► Jayme Luiz Szwarcfiter, Lilian markezon. Estruturas de Dados e Seus</p><p>Algoritmos. 3a Edição. Rio de Janeiro: LTC, 2010. Disponível em:</p><p>https://integrada.minhabiblioteca.com.br/#/books/978 85 216 2995</p><p>5/cfi/6/8!/4/2/4@0:0</p><p>► NICOLETTI, Maria do Carmo; HRUSCHKA, Estevan. Fundamentos da</p><p>Teoria dos Grafos para Computação [BV:MB]. Rio de Janeiro: Grupo</p><p>GEN, 2018. Disponível em:</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788521634775/</p><p>cfi/6/10!/4/2@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788522126651/cfi/0!/4/4@0.00:0.00</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788522126651/cfi/0!/4/4@0.00:0.00</p><p>https://integrada.minhabiblioteca.com.br/#/books/978%C2%AD85%C2%AD216%C2%AD2995%C2%AD5/cfi/6/8!/4/2/4@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/978%C2%AD85%C2%AD216%C2%AD2995%C2%AD5/cfi/6/8!/4/2/4@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788521634775/cfi/6/10!/4/2@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788521634775/cfi/6/10!/4/2@0:0</p><p>Bibliografia complementar</p><p>► Nivio Ziviane. Projeto de algoritmos: com implementações em Java e C++..</p><p>São Paulo: Cengage Learning, 2012. Disponível em:</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788522108213/cfi/2!/4</p><p>/4@0.00:49.1</p><p>► Thomas H. Cormen. Desmistificando Algoritmos. [BV:MB]. Rio de Janeiro:</p><p>Elsevier Editora Ltda. Disponível em:</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595153929/cfi/6/10</p><p>!/4/2/2@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788522108213/cfi/2!/4/4@0.00:49.1</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788522108213/cfi/2!/4/4@0.00:49.1</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595153929/cfi/6/10!/4/2/2@0:0</p><p>https://integrada.minhabiblioteca.com.br/#/books/9788595153929/cfi/6/10!/4/2/2@0:0</p>