




























































































Estude fácil! Tem muito documento disponível na Docsity
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
Prepare-se para as provas
Estude fácil! Tem muito documento disponível na Docsity
Prepare-se para as provas com trabalhos de outros alunos como você, aqui na Docsity
Encontra documentos específicos para os exames da tua universidade
Prepare-se com as videoaulas e exercícios resolvidos criados a partir da grade da sua Universidade
Responda perguntas de provas passadas e avalie sua preparação.
Ganhe pontos para baixar
Ganhe pontos ajudando outros esrudantes ou compre um plano Premium
- - - - - - -
Tipologia: Notas de estudo
1 / 136
Esta página não é visível na pré-visualização
Não perca as partes importantes!





























































































Este material foi escrito por Paulo Eduardo Azevedo Silveira e Rafael Antonio Cosentino para ser utilizado no curso de verão Introdução a Estrutura de dados e Algoritmos em Java , do Instituto de Matemática e Estatística da Universidade de São Paulo. Paulo Silveira é bacharel e mestre em ciência da computação pelo Instituto de Matemática e Estatística
Rafael Cosentino é bacharel em ciência da computação pelo Instituto de Matemática e Estatística da Uni- versidade de São Paulo (IME-USP), é mestrando em Ciência da Computação também pelo IME-USP e trabalha atualmente na Caelum. As experiências como alunos e professores mostrou aos autores desta apostila os principais pontos de dificuldades no aprendizado. Isso motivou uma abordagem um pouco diferente para esta apostila em relação ao que é comum na maioria dos livros sobre o assunto A cada capítulo, apresentaremos diversos problemas que servirão de motivação para os principais conceitos de estrutura de dados. Os exercícios complementarão o apredizado pois ajudam a fixar os conceitos vistos na apostila e estimulam o aluno para conceitos avançados que fogem do escopo deste material. Além disso, no fim de cada capítulo, apresentaremos as bibliotecas do Java que modelam as estruturas de dados apresentadas nesta apostila.
“As três coisas mais difíceis no mundo: guardar segredo, perdoar uma injúria e aproveitar o tempo”
Considere o problema de descobrir a altura da pessoa mais alta de um grupo de pessoas. Suponha que estas pessoas estão em seqüência, como em uma fila de banco, e que esta fila não está vazia. Vamos elaborar uma estratégia para resolver este problema. Uma solução bem simples seria fazer o se- guinte:
Fig.: Fila de pessoas
2
Material do Treinamento Algoritmos e Estruturas de Dados em Java
A única coisa que precisa ser mostrada para o usuário são as operações que ele pode fazer na agenda (inserir, recuperar, atualizar, remover contato, saber quantos contatos estão na agenda, etc). Este conjunto de operações é a interface que o usuário tem com a agenda. Cada celular pode implementar a sua agenda de contatos de uma forma totalmente diferente um do outro, na tentativa de obter mais performance, ser mais confiável ou gastar menos memória. Porém o conjunto básico de operações oferecidas pelas agendas é sempre o mesmo. Isso facilita a vida do usuário pois se ele tiver que trocar de celular não vai ter que aprender novamente como usar uma agenda de contatos. Essa é a grande vantagem em se pensar em interface. Mantida a interface, podemos trocar uma agenda que não é tão eficiente ou que já não atende mais as nossas necessidades por outra mais eficiente ou adequada, sem problemas em ter de aprender a usar a nova agenda: troca-se a implementação, mas não mudamos a interface. Uma agenda de celular pode ser vista como uma estrutura de dados. Uma estrutura de dados mantém os dados organizados seguindo alguma lógica e disponibiliza operações para o usuário manipular os dados. É importante, quando programar, não misturar dado e estrutura de dados em uma coisa só. Um dado é uma informação armazenada e estrutura de dados é quem administra os dados. O ideal é que a estrutura de dados seja o mais independente possível dos dados que ela vai armazenar. Desta forma pode-se aproveitar a mesma estrutura de dados para diversos tipos de dados. Por exemplo, é melhor ter uma agenda genérica do que uma agenda de telefones. Uma agenda genérica pod ser utilizada para guardar telefones, ou emails, ou até mesmo guardar uma outra estrutura dentro dela: contatos, que seriam compostos por nome, telefone e email. Algumas estruturas de dados são apenas agrupamentos de dados sem um objetivo de aplicar algum algo- ritmo ou tirar proveito de sua estrutura. Um exemplo seria a estrutura Contato. Algumas outras estruturas são mais espertas e trabalhosas, como a Agenda , assim como Listas Ligadas, Vetores, Tabelas de Espalhamento e outras que veremos no decorrer do texto. Estas estruturas, por sua característica mais complexa e de poder ser reutilizada em outros contextos, devem ser criadas da forma mais independente possível dos dados que estarão dentro dela. Em outras palavras, não devemos misturar a Agenda e o Contato de maneira rígida, para que com isso possamos criar outras Agendas, como por exemplo uma Agenda de Fornecedor.
2.4 - Sobre este texto Este texto vai mostrar a você diversas estruturas de dados, suas vantagens e desavantagens, assim como suas implementações básicas e classes já existentes na bibilioteca padrão do Java. Vamos usar recursos do Java como interfaces, generics, exceptions, pacotes e outros. É bom já ter um conhecimento razoável da linguagem e um pouco de orientação a objetos.
Capítulo 2 - Introdução - Sobre este texto - Página 4
“A morte do homem começa no instante em que ele desiste de aprender”
Todo mundo já experimentou sopa de letrinhas quando criança. Aliás, quando as crianças tomam sopa de letrinhas, elas ficam muito mais interessadas em formar as palavras do que em tomar a sopa. O que chama mais a atenção é que nesta brincadeira de criança aparece um conceito bem interessante de estrutura de dados. Quando a sopa é servida, as letras estão todas espalhadas sem ordem alguma e sem nenhum significado. Quando você escolhe um grupo de letras e as coloca em seqüência formando uma palavra, este grupo de letras ganha um valor semântico, ou seja, ganha um significado. O grupo de letrinhas que você escolhe para formar uma palavra pode conter letras repetidas sem problema nenhum. A única regra é que as letras postas em seqüência devem formar uma palavra existente em alguma língua.
Fig.: Sopa de Letrinhas As músicas também são exemplos em que a definição de uma seqüência dos elementos agrega valor semântico. Uma música é composta de notas musicais. Quando estas notas estão “espalhadas”, elas não sigi- nificam muita coisa. Já quando colocadas em uma seqüência adequada, formam uma música que as pessoas podem apreciar. Além disso, uma mesma nota musical pode aparecer mais de uma vez em uma única música.
Material do Treinamento Algoritmos e Estruturas de Dados em Java
Por exemplo, suponha que entregaram relatórios os alunos Rafael, Paulo e Ana. Rafael entregou apenas um relatório; Paulo entregou dois relatórios; e Ana entregou três relatórios. Uma possível listagem neste caso seria assim:
A listagem também deve manter a ordem de pontuação obtidas pelos relatórios dos alunos. Por exemplo, suponha que o Rafael teve pontuação máxima(100) no seu relatório; O Paulo teve pontuação 70 em um relatório e 50 no outro; Ana teve pontuação 60, 40 e 40 nos seus relatórios. Então, a listagem ficaria assim:
Conforme os alunos forem entregando os relatórios, novas entradas serão adicionadas na listagem. Uma nova entrada pode ser inserida em qualquer posição. A posição é definida de acordo com a pontuação do relatório do aluno. Por exemplo, suponha que o Rafael entregou mais um relatório com pontuação 65. A listagem deveria ser atualizada para:
Capítulo 3 - Armazenamento Sequencial - O problema da listagem de alunos - Página 7
Material do Treinamento Algoritmos e Estruturas de Dados em Java
Para gastar os créditos obtidos com os relatórios, o aluno deve pedir para retirar uma das suas entradas na listagem. Os créditos são proporcionais a colocação da entrada do aluno na listagem. Por exemplo, se o Paulo quiser gastar uma das suas duas entradas na lista ele deve escolher entre a de 70 pontos a 50 pontos. A de 70 é a segunda da lista e a de 50 é a quinta. Suponha que ele escolha a de 50 pontos então a nova listagem ficaria assim:
Quando o aluno quiser usar seus créditos ele deve verificar antes se ele tem entradas na listagem. Para isso, ele deve ir na secretária da instituição. A instituição pode querer saber qual é o aluno que está na primeira posição da listagem ou o que está na última. Na verdade, seria interessante para a instituição poder facilmente saber qual é o aluno que está em qualquer posição que ela queira.
3.3 - Listas Nesta seção, vamos definir uma estrutura de dados para resolver o problema da listagem de alunos. Cha- maremos esta estrutura de Lista. Vimos que uma estrutura de dados deve definir duas coisas:
Nos dois próximos capítulos, veremos as principais implementações de Listas. Cada implementação tem uma maneira particular de armazenar os dados, que trará vantagens e desvantagens em determinados casos, em termos de uso de memória e tempo consumido para cada operação. Cabe a você conhecer esses casos e saber fazer a melhor escolha conforme o problema enfrentado. Neste capítulo, definiremos apenas a interface de uso que a Lista deve fornecer ao usuário. Com certeza, vamos querer adicionar elementos então precisamos de algumas operações de adição. Talvez duas operações já sejam suficientes, uma que permita adicionar um elemento no fim da Lista e outra que deixe o usuário escolher a posição onde ele quer adicionar um elemento. Também, precisaremos recuperar elementos então vamos definir uma operação que dado uma posição da Lista ela devolve o elemento que está lá. Outro tipo de operação necessária e o de remover elementos. Esta operação deve receber a posição do elemento que deve ser removido.
Capítulo 3 - Armazenamento Sequencial - Listas - Página 8
Material do Treinamento Algoritmos e Estruturas de Dados em Java
public boolean equals(Object o) { Aluno outro = (Aluno)o; return this.nome.equals(outro.nome); } }
Com a classe Aluno , o sistema é capaz de criar objetos para representar os alunos da instituição. Teremos apenas alguns poucos atributos nessa classe, e alguns pares de getters e setters. Vale lembrar que não é boa prática ter classes que apenas carregam dados: seria mais interessante que Aluno também tivesse métodos de negócio. Perceba que reescrevemos os métodos toString() e equals(Object). O primeiro será útil para imprimir os alunos na tela. O segundo servirá para comparar dois objetos do tipo Aluno, o critério de comparação será os nomes dos alunos. Devemos tomar cuidado no método equals(Object) pois estamos correndo o risco de dois tipos de erro. O primeiro acontece quando a referência recebida no parâmetro não está apontando para um objeto do tipo Aluno. O segundo ocorre quando ou a referência do parâmetro é null ou o atributo nome está null.
3.5 - Exercícios: Armazenamento
Capítulo 3 - Armazenamento Sequencial - Exercícios: Armazenamento - Página 10
“A melhor maneira de fugir do seu problema é resolvê-lo”
Ainda falta definir como os alunos serão armazenados. Como queremos manter muitos alunos vamos alocar um grande espaço de memória sequencial com capacidade para guardar uma certa quantidade de alunos, talvez 100 alunos por enquanto seja razoável. Para facilitar o acesso aos alunos, dividiremos o espaço de memória alocado em pequenos pedaços idênti- cos. Cada pedaço armazenará um aluno. Além disso, vamos indexar (numerar) os pequenos pedaços para ser fácil recuperar um aluno.
Fig.: Array Praticamente todas as linguagens de programação têm um recurso similar ao que descrevemos acima. Em Java, este recurso é chamado de Array. Um array é uma porção de memória fixa e sequencial dividida em pedaços idênticos indexados a partir do 0. Em cada posição do array, podemos guardar um aluno. Na verdade, cada posição pode guardar uma referência para um objeto do tipo Aluno. A capacidade de um array é fixa e deve ser informada no momento da criação do array. Não é possível redimensionar um array em Java, teremos de contornar isso mais adiante.
11
Material do Treinamento Algoritmos e Estruturas de Dados em Java
4.1 - Os testes primeiro Como temos a interface do Vetor já bem definida, podemos criar alguns testes antes mesmo de começar a implementar o código. Criaremos testes para cada uma das operações.
Teste: public class TesteAdicionaNoFim { public static void main(String[] args) { Aluno a1 = new Aluno(); Aluno a2 = new Aluno(); a1.setNome("Rafael"); a2.setNome("Paulo"); Vetor lista = new Vetor(); lista.adiciona(a1); lista.adiciona(a2); System.out.println(lista); } }
Saída: [Rafael, Paulo]
Teste: public class TesteAdicionaPorPosicao { public static void main(String[] args) { Aluno a1 = new Aluno(); Aluno a2 = new Aluno(); Aluno a3 = new Aluno(); a1.setNome("Rafael"); a2.setNome("Paulo"); a3.setNome("Ana"); Vetor lista = new Vetor(); lista.adiciona(a1); lista.adiciona(0, a2); lista.adiciona(1, a3); System.out.println(lista);
Capítulo 4 - Vetores - Os testes primeiro - Página 13
Material do Treinamento Algoritmos e Estruturas de Dados em Java
Saída: [Paulo, Ana, Rafael]
Teste: public class TestePegaPorPosicao { public static void main(String[] args) { Aluno a1 = new Aluno(); Aluno a2 = new Aluno(); a1.setNome("Rafael"); a2.setNome("Paulo"); Vetor lista = new Vetor(); lista.adiciona(a1); lista.adiciona(a2); Aluno aluno1 = lista.pega(0); Aluno aluno2 = lista.pega(1); System.out.println(aluno1); System.out.println(aluno2); } }
Saída: Rafael Paulo
Teste: public class TesteRemovePorPosicao { public static void main(String[] args) { Aluno a1 = new Aluno(); Aluno a2 = new Aluno(); a1.setNome("Rafael"); a2.setNome("Paulo"); Vetor lista = new Vetor();
Capítulo 4 - Vetores - Os testes primeiro - Página 14