Você está na página 1de 126

MANUAL DO CURSO DE LICENCIATURA EM

Gestão de Sistemas de
Informação

ENSINO ONLINE. ENSINO COM FUTURO 2022


2º ANO : Programação II

CÓDIGO ISCED1-GSI08
GSITOTAL
HORAS/ 1
SEMESTRE
CRÉDITOS (SNATCA) 6
NÚMERO DE TEMAS 4
CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Direitos de autor (copyright)

Este manual é propriedade do Instituto Superior de Ciências e Educação a Distância (ISCED), e


contém reservados todos os direitos. É proibida a duplicação ou reprodução parcial ou total
deste manual, sob quaisquer formas ou por quaisquer meios (electrónicos, mecânico, gravação,
fotocópia ou outros), sem permissão expressa de entidade editora (Universidade Aberta
Isced(UNISCED).

A não observância do acima estipulado o infractor é passível a aplicação de processos judiciais


em vigor no País.

Universidade Aberta Isced (UNISCED)


Vice -Reitoria Académica

Rua Dr. Almeida Lacerda, No 212 Ponta - Gêa


Beira - Moçambique
Telefone: +258 23 323501
Cel: +258 82 3055839

Fax: 23323501
Email:d i r e c ç ã o @ u n i s c e d . e d u . m z

Website:www.unisced.edu.mz

i
CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Agradecimentos

A Universidade Aberta Isced (UNISCED) agradece a colaboração dosseguintes indivíduos


e instituições na elaboração deste manual:

Autor Adjello Garfo

Vice -Reitoria Académica do ISCED


Coordenação
Universidade Aberta Isced (UNISCED)
Design

Financiamento e Logística Instituto Africano de Promoção da Educação a Distância (IAPED)

Solomone Rumhungwe
Revisão Científica e
Linguística

Ano de Publicação 2018

Local de Publicação UNISCED – BEIRA

ii
CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Índice

Visão geral 1
Benvindo à Disciplina/Módulo de Programação II ...............................................1
Objectivos do Módulo ..........................................................................................1
Quem deveria estudar este módulo.....................................................................1
Como está estruturado este módulo ....................................................................2
Ícones de actividade............................................................................................3
Habilidades de estudo .........................................................................................3
Precisa de apoio?................................................................................................5
Tarefas (avaliação e auto-avaliação) ..................................................................6
Avaliação.............................................................................................................6

TEMA – I: FUNDAMENTOS DE ALGORITMOS DE COMPUTAÇÃO. 9


UNIDADE Temática 1.1. Introdução a Algoritmos ...............................................9
UNIDADE Temática 1.3. Algoritmos de Pesquisas – Sequencial e Binária. ................... 22
UNIDADE Temática 1.4. Algoritmos de Ordenação. ..........................................30
Exercícios de AUTO-AVALIAÇÃO .....................................................................34

TEMA – II: ESTRUTURAS DE DADOS FUNDAMENTAIS. 37


UNIDADE Temática 2.1. Introdução às estruturas de dados fundamentais.................... 37
UNIDADE Temática 2.2. Pilhas, Filas e Gráfos. ................................................47
UNIDADE Temática 2.3. Árvores e Tabelas de Hash. .......................................64
Exercícios de AUTO-AVALIAÇÃO .....................................................................78

TEMA – III: EXERCÍCIOS E RESOLUÇÃO DE PROBLEMAS REAIS. 84


UNIDADE Temática 3.1. Introdução de processos para resolução de problemas reais. 84
UNIDADE Temática 3.2. Problema 1: “Pegar e Plantar”. ....................................... 91
UNIDADE Temática 3.3. Problema 2: “Como Substituir a Rede por uma Flor”. ................95
Exercícios de AUTO-AVALIAÇÃO .....................................................................98

TEMA – IV: INTERFACE DE PROGRAMAÇÃO DE APLICAÇÕES JAVA. 100


UNIDADE Temática 2.1. Introdução à API Collections do JAVA ............................ 100
UNIDADE Temática 2.2. Listas: java.util.List. ......................................................... 103
UNIDADE Temática 2.3. Ordenação: Collections.sort. .......................................... 106
UNIDADE Temática 2.4. Conjunto: java.util.Set ..............................................110
Exercícios de AUTO-AVALIAÇÃO ...................................................................117

iii
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Visão geral

Benvindo à Disciplina/Módulo de Programação II

Objectivos do Módulo

Ao terminar o estudo deste módulo de Programação II o leitor deverá


estar familiarizado com os princípios fundamentais de algoritmos e
estruturas de dados bem como reconhecer a sua importância na
resolução de diferentes tipos de problemas reais. É ainda objetivo
deste módulo que o leitor adquira competências de análise e
desenho de algoritmos e conhecer as diferentes abordagens usadas
na implementação de estruturas de dados.

▪ Conhecer os princípios fundamentais de algoritmos e estruturas de


dados.

▪ Ser capaz de escolher, comparar, conceber e utilizar estruturas


Objectivos de dados adequadas ao problema a resolver.
Específicos ▪ Saber distinguir as estruturas de dados como árvores de busca
binária, tabelas (hash tables) e grafos;
▪ Demonstrar competências no uso de API’s JAVA para criação de
algoritmos na resolução de problemas reais.

Quem deveria estudar este módulo


Este Módulo foi concebido para estudantes do 2º ano do curso de
licenciatura em Gestão de Sistemas de Informação do ISCED. Poderá
ocorrer, contudo, que haja leitores que queiram se actualizar e
consolidar seus conhecimentos nessa disciplina, esses serão bem-
vindos, não sendo necessário para tal se inscrever. Mas poderá
adquirir o manual.

1
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Como está estruturado este módulo

Este módulo de Programação II, para estudantes do 2º ano do curso


de licenciatura em Gestão de Sistemas de Informação, à semelhança
dos restantes do ISCED, está estruturado como se segue:
Páginas introdutórias

▪ Um índice completo.
▪ Uma visão geral detalhada dos conteúdos do módulo, resumindoos
aspectos-chave que você precisa conhecer para melhor estudar.
Recomendamos vivamente que leia esta secção com atenção
antes de começar o seu estudo, como componente de
habilidades de estudos.
Conteúdo desta Disciplina/módulo

Este módulo está estruturado em Temas. Cada tema, por sua vez
comporta certo número de unidades temáticas ou simplesmente
unidades. Cada unidade temática se caracteriza por conter uma
introdução, objectivos, conteúdos.
No final de cada unidade temática ou do próprio tema, são
incorporados antes o sumário, exercícios de auto-avaliação, só
depois é que aparecem os exercícios de avaliação.
Os exercícios de avaliação têm as seguintes características: Puros
exercícios teóricos/Práticos, Problemas não resolvidos e actividades
práticas, incluído estudo de caso.

Outros recursos

A equipa dos académicos e pedagogos do ISCED, pensando em si,


num cantinho, recôndito deste nosso vasto Moçambique e cheio de
dúvidas e limitações no seu processo de aprendizagem, apresenta
uma lista de recursos didácticos adicionais ao seu módulo para você
explorar. Para tal o ISCED disponibiliza na biblioteca do seu centro
de recursos mais material de estudos relacionado com o seu curso
como: Livros e/ou módulos, CD, CD-ROOM, DVD. Para além deste
material físico ou electrónico disponível na biblioteca, pode ter
acesso a Plataforma digital moodle para alargar mais ainda as
possibilidades dos seus estudos.

2
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Auto-avaliação e Tarefas de avaliação

Tarefas de auto-avaliação para este módulo encontram-se no final


de cada unidade temática e de cada tema. As tarefas dos exercícios
de auto-avaliação apresentam duas características: primeiro
apresentam exercícios resolvidos com detalhes. Segundo, exercícios
que mostram apenas respostas.
Tarefas de avaliação devem ser semelhantes às de auto-avaliação
mas sem mostrar os passos e devem obedecer o grau crescente de
dificuldades do processo de aprendizagem, umas a seguir a outras.
Parte das terefas de avaliação será objecto dos trabalhos de campo
a serem entregues aos tutores/docentes para efeitos de correcção e
subsequentemente nota. Também constará do exame do fim do
módulo. Pelo que, caro estudante, fazer todos os exercícios de
avaliação é uma grande vantagem.
Comentários e sugestões

Use este espaço para dar sugestões valiosas, sobre determinados


aspectos, quer de natureza científica, quer de natureza didáctico-
Pedagógica, etc, sobre como deveriam ser ou estar apresentadas.
Pode ser que graças as suas observações que, em gozo de confiança,
classificamo-las de úteis, o próximo módulo venha a ser melhorado.

Ícones de actividade

Ao longo deste manual irá encontrar uma série de ícones nas margens
das folhas. Estes ícones servem para identificar diferentes partes do
processo de aprendizagem. Podem indicar uma parcela específica
de texto, uma nova actividade ou tarefa, uma mudança de
actividade, etc.

Habilidades de estudo

O principal objectivo deste campo é o de ensinar aprender a


aprender. Aprender aprende-se.

Durante a formação e desenvolvimento de competências, para


facilitar a aprendizagem e alcançar melhores resultados, implicará
empenho, dedicação e disciplina no estudo. Isto é, os bons resultados
apenas se conseguem com estratégias eficientes e eficazes. Por isso é
importante saber como, onde e quando estudar. Apresentamos
algumas sugestões com as quais esperamos que caro estudante possa
rentabilizar o tempo dedicado aos estudos, procedendo como se
segue:

1º Praticar a leitura. Aprender a Distância exige alto domínio de


leitura.

3
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

2º Fazer leitura diagonal aos conteúdos (leitura corrida).

3º Voltar a fazer leitura, desta vez para a compreensão e


assimilação crítica dos conteúdos (ESTUDAR).

4º Fazer seminário (debate em grupos), para comprovar se a sua


aprendizagem confere ou não com a dos colegas e com o padrão.

5º Fazer TC (Trabalho de Campo), algumas actividades práticas ou


as de estudo de caso se existirem.

IMPORTANTE: Em observância ao triângulo modo-espaço-tempo,


respectivamente como, onde e quando...estudar, como foi referido
no início deste item, antes de organizar os seus momentos de estudo
reflicta sobre o ambiente de estudo que seria ideal para si: Estudo
melhor em casa/biblioteca/café/outro lugar? Estudo melhor à
noite/de manhã/de tarde/fins-de-semana/ao longo da semana?
Estude melhor com música/num sítio sossegado/num sítio barulhento!?
Preciso de intervalo em cada 30 minutos, em cada hora, etc.

É impossível estudar numa noite tudo o que devia ter sido estudado
durante um determinado período de tempo; Deve estudar cada ponto
da matéria em profundidade e passar só ao seguinte quando achar
que já domina bem o anterior.

Privilegia-se saber bem (com profundidade) o pouco que puder ler e


estudar, que saber tudo superficialmente! Mas a melhor opção é
juntar o útil ao agradável: Saber com profundidade todos conteúdos
de cada tema, no módulo.

Dica importante: não recomendamos estudar seguidamente por


tempo superior a uma hora. Estudar por tempo de uma hora
intercalado por 10 (dez) a 15 (quinze) minutos de descanso (chama-
se descanso à mudança de actividades). Ou seja que durante o
intervalo não se continuar a tratar dos mesmos assuntos das
actividades obrigatórias.

Uma longa exposição aos estudos ou ao trabalho intelectual


obrigatório pode conduzir ao efeito contrário: baixar o rendimento
da aprendizagem. Por que o estudante acumula um elevado volume
de trabalho, em termos de estudos, em pouco tempo, criando
interferência entre os conhecimentos, perde sequência lógica, por fim
ao perceber que estuda tanto mas não aprende, cai em insegurança,
depressão e desespero, por se achar injustamente incapaz!

Não estude na última da hora; quando se trate de fazer alguma


avaliação. Aprenda a ser estudante de facto (aquele que estuda
sistematicamente), não estudar apenas para responder a questões de

4
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

alguma avaliação, mas sim estude para a vida, sobre tudo, estude
pensando na sua utilidade como futuro profissional, na área em que
está a se formar.

Organize na sua agenda um horário onde define a que horas e que


matérias deve estudar durante a semana; Face ao tempo livre que
resta, deve decidir como o utilizar produtivamente, decidindo quanto
tempo será dedicado ao estudo e a outras actividades.

É importante identificar as ideias principais de um texto, pois será


uma necessidade para o estudo das diversas matérias que compõem
o curso: A colocação de notas nas margens pode ajudar a estruturar
a matéria de modo que seja mais fácil identificar as partes que está
a estudar e Pode escrever conclusões, exemplos, vantagens,
definições, datas, nomes, pode também utilizar a margem para
colocar comentários seus relacionados com o que está a ler; a melhor
altura para sublinhar é imediatamente a seguir à compreensão do
texto e não depois de uma primeira leitura; Utilizar o dicionário
sempre que surja um conceito cujo significado não conhece ou não lhe é
familiar;

Precisa de apoio?

Caro estudante, temos a certeza que por uma ou por outra razão, o
material de estudos impresso, lhe pode suscitar algumas dúvidas como
falta de clareza, alguns erros de concordância, prováveis erros
ortográficos, falta de clareza, fraca visibilidade, página trocada ou
invertidas, etc). Nestes casos, contacte os serviços de atendimento e
apoio ao estudante do seu Centro de Recursos (CR), via telefone, sms,
E-mail, se tiver tempo, escreva mesmo uma carta participando a
preocupação.
Uma das atribuições dos Gestores dos CR e seus assistentes
(Pedagógico e Administrativo), é a de monitorar e garantir a sua
aprendizagem com qualidade e sucesso. Dai a relevância da
comunicação no Ensino a Distância (EAD), onde o recurso as TIC se torna
incontornável: entre estudantes, estudante – Tutor, estudante –CR,
etc.
As sessões presenciais são um momento em que você caro estudante,
tem a oportunidade de interagir fisicamente com staff do seu CR, com
tutores ou com parte da equipa central do ISCED indigitada para
acompanhar as suas sessões presenciais. Neste período pode
apresentar dúvidas, tratar assuntos de natureza pedagógica e/ou
administrativa.
O estudo em grupo, que está estimado para ocupar cerca de 30%
do tempo de estudos a distância, é muita importância, na medida em
que lhe permite situar, em termos do grau de aprendizagem com
relação aos outros colegas. Desta maneira ficará a saber se precisa
de apoio ou precisa de apoiar aos colegas. Desenvolver hábito de

5
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

debater assuntos relacionados com os conteúdos programáticos,


constantes nos diferentes temas e unidade temática, no módulo.

Tarefas (avaliação e auto-avaliação)


O estudante deve realizar todas as tarefas (exercícios, actividades e
auto−avaliação), contudo nem todas deverão ser entregues, mas é
importante que sejam realizadas. As tarefas devem ser entregues
duas semanas antes das sessões presenciais seguintes.
Para cada tarefa serão estabelecidos prazos de entrega, e o não
cumprimento dos prazos de entrega, implica a não classificação do
estudante. Tenha sempre presente que a nota dos trabalhos de campo
conta e é decisiva para ser admitido ao exame final da
disciplina/módulo.
Os trabalhos devem ser entregues ao Centro de Recursos (CR) e os
mesmos devem ser dirigidos ao tutor/docente.
Podem ser utilizadas diferentes fontes e materiais de pesquisa,
contudo os mesmos devem ser devidamente referenciados,
respeitando os direitos do autor.
O plágio1 é uma violação do direito intelectual do(s) autor(es). Uma
transcrição à letra de mais de 8 (oito) palavras do testo de um autor,
sem o citar é considerado plágio. A honestidade, humildade científica
e o respeito pelos direitos autorais devem caracterizar a realização
dos trabalhos e seu autor (estudante do ISCED).

Avaliação

Muitos perguntam: Com é possível avaliar estudantes à distância,


estando eles fisicamente separados e muito distantes do
docente/tutor! Nós dissemos: Sim é muito possível, talvez seja uma
avaliação mais fiável e consistente.
Você será avaliado durante os estudos à distância que contam com
um mínimo de 90% do total de tempo que precisa de estudar os
conteúdos do seu módulo. Quando o tempo de contacto presencial
conta com um máximo de 10%) do total de tempo do módulo. A
avaliação do estudante consta detalhada do regulamentado de
avaliação.
Os trabalhos de campo por si realizados, durante estudos e
aprendizagem no campo, pesam 25% e servem para a nota de
frequência para ir aos exames.
Os exames são realizados no final da cadeira disciplina ou modulo e
decorrem durante as sessões presenciais. Os exames pesam no mínimo

1
Plágio - copiar ou assinar parcial ou totalmente uma obra literária, propriedade
intelectual de outras pessoas, sem prévia autorização.

6
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

75%, o que adicionado aos 25% da média de frequência,


determinam a nota final com a qual o estudante conclui a cadeira.
A nota de 10 (dez) valores é a nota mínima de conclusão da cadeira.
Nesta cadeira o estudante deverá realizar pelo menos 2 (dois)
trabalhos e 1 (um) (exame).
Algumas actividades práticas, relatórios e reflexões serão utilizados
como ferramentas de avaliação formativa.
Durante a realização das avaliações, os estudantes devem ter em
consideração a apresentação, a coerência textual, o grau de
cientificidade, a forma de conclusão dos assuntos, as recomendações,
a identificação das referências bibliográficas utilizadas, o respeito
pelos direitos do autor, entre outros.
Os objectivos e critérios de avaliação constam do Regulamento de
Avaliação.

7
ISCED CURSO: Gestão de Sistemas de Informação; 3° Ano Disciplina/Módulo: Programação II

TEMA – I: FUNDAMENTOS DE ALGORITMOS DE COMPUTAÇÃO.

UNIDADE Temática 1.1. Introdução a Algoritmos.


UNIDADE Temática 1.2. Algoritmos Numéricos Simples.
UNIDADE Temática 1.3. Algoritmos de Pesquisas - Sequencial e
Binária.
UNIDADE Temática 1.4. Algoritmos de Ordenação.
UNIDADE Temática 1.5. EXERCÍCIOS deste tema.

• Introduzir o conceito de algoritmos; descrever a sua


importância.
• Apresentar algumas formas de escrever um algoritmo e
Objectivos suas aplicações.
específicos • Apresentar as principais técnicas usadas na construção
de algoritmos.

UNIDADE Temática 1.1. Introdução a Algoritmos

Geralmente espera-se que um gestor de sistemas de informação


resolva qualquer problema da maneira mais eficiente possível. Essa
eficiência pode ser em termos de memória, tempo ou ambos. No
entanto, a eficiência torna-se importante apenas se a solução,
proposta pela pessoa, resolver esse problema. Os passos seguidos
para o fazer constituem assim, um algoritmo. Esta unidade introduz
o conceito de algoritmo, discute as formas de escrever um algoritmo
e explora os fundamentos do design algorítmico. Começaremos com
a definição de um algoritmo.
Bhasin (2005) define algoritmo como todos os passos a serem
executados para realizar uma tarefa particular.
O escopo de uso de algoritmos é incrivelmente amplo; estes podem
ser usados em qualquer área, desde um simples problema
matemático à resolução de problemas mais complexos de outros
ramos da ciênciia, medicina, finanças, produção, fornecimento
industrial e comunicação.
Os algoritmos fornecem suporte para todas as partes da nossa vida
quotidiana. Sempre que tivermos uma sequência finita, bem definida

9
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

e efetiva de ações que alcançarem alguma coisa, podemos vê-las (a


sequência de ações) como um algoritmo. Por exemplo, pode-se
transformar até mesmo algo tão simples quanto fazer um bolo em
um algoritmo: todos os passos seguidos desde o início da confeição
do bolo ao término (obtenção do produto final, o bolo) são o
algoritmo para a criação deste.
Todas as tarefas que executamos em um computador envolvem
algoritmos. Alguns algoritmos aparecem como parte do hardware do
computador. O próprio ato de inicializar um computador envolve o
uso de um algoritmo. Podemos também encontrar algoritmos em
sistemas operativos, aplicativos e qualquer outra peça de software.
Até as nossas rotinas diárias muitas vezes se transformam em
algoritmos.
A maioria das pessoas, realiza essencialmente as mesmas tarefas
todos os dias e na mesma ordem, tornando o seu dia um algoritmo
que resolve o problema de como viver com sucesso, gastando a
menor quantidade de energia possível.
Os procedimentos de emergência geralmente dependem de
algoritmos. Ao tirarmos o cartão de emergência do pacote à nossa
frente no avião; nele estão uma série de pictogramas mostrando
como abrir a porta de emergência e estender o slide. Em alguns
casos, podemos até mesmo nem ver palavras, mas as imagens
transmitem o procedimento necessário para executar a tarefa e
resolver o problema de sair do avião com pressa. Essas sequências de
procedimentos podem ser consideradas algoritmos.
1.1.1. Importância de Algoritmos
Para entender a importância dos algoritmos, vamos começar com um
exemplo. Alguns (ou a maioria) de nós deve ter encontrado soluções
para muitos dos nossos problemas usando o Google. Quando
digitamos uma consulta no Google, nos é apresentado um conjunto
ordenado de resultados que são mais ou menos relevantes. Contudo,
esta ordenação é feita através de um algoritmo, que classifica as
páginas de acordo com a consulta que fazemos (o texto introduzido).
Esse algoritmo de ordenação não apenas verifica a similaridade
textual da consulta com a página web apresentada, mas também
calcula os inlinks (número de páginas que apontam para essa página)
e os outlinks (número de páginas para as quais a página está
apontanda) dessa página. Este algoritmo ajudou o Google a atingir o
status que tem atualmente.

10
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

A maioria de nós provavelmente deve concordar que o Google tem


uma grande influência positiva na nossa vida, principalmente
académica e profissional. Portanto, o crédito vai para o algoritmo de
classificação de páginas que o Google usa.
Outro exemplo que pode ser citado aqui é o de “Google Maps”,
também da Google. Alguns de nós deve ter usado esta ferramenta
para encontrar a rota de um local para outro ou sua posição, ou até
mesmo para procurar por locais específicos de interesse como
restaurantes, bombas de abastecimento, entre outros. O “Google
Maps” nos ajuda a obter instruções de direção usando os algoritmos
que conseguem identificar qual é o caminho mais curto para um
determinado local. Então, até O Google Maps é baseado em
algoritmos.
Hoje em dia, os algoritmos se tornaram importantes até mesmo para
área biológica. Governos de todo o mundo pensam em criar um
banco de dados global de DNAs para combater o ameaça do
terrorismo. Isso só seria possível se algoritmos de ordenação e
pesquisa fossem desenvolvidos, que podessem extrair informações
de bilhões de DNAs. Para realizar esta tarefa, os algoritmos baseados
nessa natureza estão a ser desenvolvidos. Esse tipo de algoritmos são
os chamados de algoritmos genéticos, que infelizmente não serão
aprofundados aqui neste módulo; entretendo recomenda-se a leitura
após familiarização com o conteúdo deste módulo.
1.1.2. Formas de Representar um Algoritmo
Existem várias maneiras de se escrever um algoritmo. Aqui, três
maneiras foram explicadas e exemplificadas tomando exemplos
necessários, de forma simplificada:
• A descrição narrativa.
• O fluxograma.
• O Pseudocódigo.
1.1.2.1. Descrição narrativa
Um algoritmo pode ser escrito de várias maneiras. Pode ser escrito a
partir de uma descrição narrativa, mas essa metodologia pode conter
alguns inconvenientes. A linguagem natural pode ser ambígua e,
portanto, esse tipo de algoritmos não possuem a característica de
serem fortemente bem definidos. Uma vez que cada etapa de um
algoritmo deve ser clara e não deve ter mais de um significado, os

11
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

algoritmos escritos a partir de uma descrição narrativa não são


considerados bons para a maioria das tarefas. No entanto, um
exemplo de pesquisa linear, em que um elemento é pesquisado em
todas as posições da matriz e a posição é impressa se um elemento é
encontrado, é dado abaixo.
Nesse algoritmo, “A” é o array no qual os elementos são
armazenados e “item” é o valor que deve ser pesquisado. O algoritmo
assume que todos os elementos em “A” são distintos. O algoritmo
descreve o processo acima.
Algoritmo: algoritmo de descrição narrativa de pesquisa linear.
Etapa 1. Compare “item” com o primeiro elemento da matriz, A.
Etapa 2. Se os dois forem iguais, imprima a posição do elemento e
saia.
Passo 3. Senão repita o processo acima com o resto dos elementos.
Etapa 4. Se o item não for encontrado em nenhuma posição, imprima
“não encontrado” e saia.
No entanto, o algoritmo apesar de ser simples, não é comumente
usado. O fluxograma ou um pseudocódigo é mais comum em
comparação com algoritmos de descrição narrativa.
1.1.2.2. O fluxograma
Aqui, os algoritmos são representados graficamente por formas
geométricas diferentes que indicam ações distintas. O mesmo
algoritmo de pesquisa linear pode ser escrito a partir de um
fluxograma, abaixo. Note que o NULL é usado aqui para indicar uma
posição inexistente no array, precisamente para verificar se
chagamos numa posição fora dos limites da matriz.

12
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Fluxograma de pesquisa linear.

A seguir, as convenções usadas para o fluxograma:

Representação
Nome Significado
gráfica

A oval é usada
para indicar o
Início/Fim começo e fim
de um
algoritmo.

A seta indica a
direção do
Setas
fluxo do
algoritmo.

13
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

O
paralelogramo
Entrada/Saída indica a
entrada ou
saída.

O retângulo
Processo indica uma
computação.

O losango
indica um
Decisão ponto em que
uma decisão é
feita.

Tabela: Convenções básicas usadas para construção de fluxogramas.

1.1.2.3. O Pseudocódigo

Em relação às formas anteriores, o pseudocódigo tem a vantagem de


ser facilmente convertido em qualquer linguagem de programação.
Esta forma de escrever um algoritmo é mais aceitável e mais usado.
O algoritmo abaixo descreve o processo de pesquisa linear. O nome
do algoritmo é “Pesquisa linear”. O elemento “item” deve ser
pesquisado na matriz “A”.

14
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Pseudocódigo do algoritmo de pesquisa linear.

Os algoritmos apresentados nesta forma exigem menos esforço para


ser implemento por um programador. Entretanto, às vezes, quando
os detalhes da implementação não devem ser inclusos no algoritmo,
os algoritmos descritos narrativamente são mais simples de se
perceber. O algoritmo descreve amplamente o que deve ser feito,
não exatamente como deve ser feito.

O Pseudocódigo fornece uma descrição de alto nível de um algoritmo


sem a ambiguidade associada à descrição narrativa de um texto
simples, mas também sem a necessidade de conhecer a sintaxe de
uma linguagem de programação específica.

Sumário

Nesta Unidade 1.1 introduzimos os principais


conceitos de algoritmos, descrevemos suas formas de
representação e importância.

15
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press.

UNIDADE Temática 1.2. Algoritmos Numéricos Simples.

Algoritmos numéricos são aqueles capazes de solucionar problemas


matemáticos, fornecendo resultados numéricos aproximados. Os
algoritmos numéricos são voltados ao processamento numérico e
geralmente têm o objetivo de obter um ou mais resultados
numéricos para seus problemas. Um algoritmo numérico
considerado “bom” tem as seguintes características:
Inexistência de erro lógico
Deve-se ter uma visão completa de todas as tendências do processo
de resolução do problema, levando em conta as possibilidades e
caraterísticas das operações aritméticas e dos modelos matemáticos
em questão. O algoritmo numérico deve identificar todas as etapas
do modelo.
Exemplo: Um algoritmo para calcular o valor de x na equação ax=b
deve levar em consideração a possibilidade de a ser zero, e daí de b
ser zero (não basta dividir b por a, deve-se considerar a possibilidade
de em algum momento o valor de a=0, que levaria a x=b/0,
matematicamente “impossível”).
Inexistência de erro operacional

16
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Mesmo que não haja erro lógico, o algoritmo pode falhar por violar
restrições físicas da máquina e teremos erros que são detetados em
tempo de execução.
Exemplo: Situações de overflow e underflow.
Quantidade finita de cálculos
Como muitos problemas numéricos são resolvidos por métodos
iterativos (repetitivos), faz-se necessário estabelecer um critério de
parada para que o algoritmo possa terminar após um número finito
de passos.
Existência de um critério de exatidão
Em virtude das limitações de precisão da máquina e da exatidão desta
e do método, todo resultado obtido do computador deverá
enquadrar-se num critério de exatidão fornecido de antemão de
modo a possibilitar que um resultado aceitável seja escrito na forma:
Resultado  Valor Aproximado Limite de Erro.
Na Matemática Intervalar todos os métodos apresentam essa
característica, uma vez que os resultados são sempre um intervalo
que contém a solução exata e a partir daí temos implicitamente o
limite para o erro.
Independência de máquina
Em algoritmos numéricos não deve haver dados que dependem de
máquina. Devem ser evitadas as cotas que, em geral, são usadas para
terminar ciclos de iterações, pois essas grandezas são dependentes
da máquina em uso e não provêm do problema em si. Em outras
palavras, o programa gerado pelo algoritmo deve ser executado em
diferentes máquinas, visando à máxima portabilidade.
Exemplo: Quantos dígitos devem ser usados na representação da
constante de Euler, e=2.718281828...?
Com precisão infinita, os limites de erro devem convergir a zero
Essa exigência estabelece a dependência entre a solução ideal em R
e a solução de máquina. Sem essa condição de convergência a
solução de máquina não precisará necessariamente estar relacionada
com a solução verdadeira.
Exemplo: Dado 𝑎 ∈ 𝑅 , determinar x = sen(a). Um algoritmo que satisfaz
os cinco critérios anteriores, mas não este por não prever um

17
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

critério de truncamento apropriado, isto é, não há uma convergência


numérica, é dado por:
• entrada {a}
• x: = 0 ± 1
• saída {a, x}
Eficiência
Quando se deseja encontrar a solução para um problema, sempre
visamos economizar os recursos envolvidos. Então prevemos certo
conjunto de condições com respeito a fatores envolvidos no processo
de solução e, conforme o resultado que queremos obter,
estabelecemos um compromisso entre estas condições, de modo a
fornecer aquelas que nos forem mais vantajosas. Em geral, tais
fatores são: tempo, exatidão, volume de dados de referência,
dificuldades de representação e outros.
Sobre estes fatores formulamos condições de rapidez, alta exatidão,
trabalhar com poucos dados de referência, ocupar menor espaço de
memória, ser facilmente representável, etc. Podemos estabelecer
um conceito de custo operacional por quantidade de informação, ou
seja, ponderar com certo custo relativo cada um dos fatores e depois
computá-los em busca da mínima soma que nos possibilite a máxima
quantidade de informação.
Exemplo: Cálculo do determinante de uma matriz n x n através de
diferentes métodos, supondo o tempo de 40µs para adições e
subtrações e de 400 µs para multiplicações:

n=5 n=10 n=20


Cramer 2,5s 3,4dias 20 bilhões de
Determinantes pela anos
definição
Cramer 0,4s 6 min 5 meses
Determinantes por Laplace
Gauss 36ms 0,22s 1,5s
Método de Eliminação

1.2.1. Passos para a resolução de um problema


Dado um problema técnico, para chegarmos a uma soluçãonumérica,
faz-se necessário percorrer uma sequência

18
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

preestabelecida de passos isolados que perfazem o algoritmo


numérico. Em cada um desses passos pode existir uma parcela de
erro que se acumula ao montante final do processo. Eis, os passos a
seguir:
Modelamento
O problema técnico precisa ser associado a um modelo matemático
para ser possível a interpretação e a consequente solução.
Simplificação
É possível que o modelo usado para certa solução numérica necessite
de simplificações.
Resultados de Ciências Vizinhas e Medição
Nas equações ocorrem coeficientes, que foram obtidos de ciências
vizinhas, como por exemplo, Termodinâmica, Ecologia, Física, ou de
medidas e, por isso, já providos de erros. Neste ponto, já dispomos
das equações a serem resolvidas pelas máquinas digitais.
Escolha de Métodos
É preciso escolher o método numérico para obter a solução, sempre
levando em conta em que recurso vamos procurar maior eficiência.
Escolha de Parâmetros
No método de solução devem ser escolhidos certos parâmetros de
cálculo, como, por exemplo, a escolha de um “passo” num método
de diferenças, ou a escolha do tamanho do sub-intervalo para um
método para integração.
Truncamento das Iterações
A maioria dos problemas numéricos não tem solução direta e precisa,
por isso, são resolvidos iterativamente; porém é necessário que se
escolha um critério de parada.
Podemos simplificar os passos referidos acima a partir de um
fluxograma, abaixo:

19
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Fluxograma-resumo do processo de resolução de problemas.


No fluxograma anterior:
• Problema real: determinar tensões nos nós dos circuitos.
• Levantamento de dados: os valores das resistências e tensões
nos pontos A e B, por exemplo.
• Construir modelo matemático: montar equações e criar as
matrizes a partir delas.
• Escolher um método numérico: Decomposição LU,
Decomposição de Cholesky, Fatoração LDLT, Método de
Jacobi, etc.
• Implementar o método computacionalmente: criar e
processar programa.
• Analisar resultados e verificar se o modelo matemático ou o
método numérico precisam ser alterados.
Todos esses passos podem causar erros no resultado final.
Intuitivamente temos: se a passagem da teoria para a aproximação
induz a certo erro na solução, então uma iteração com certa precisão
pode não melhorar o erro e o tempo de cálculo é mero desperdício.
Portanto, se quisermos melhorar o tempo de cálculo de modo
efetivo, devemos fazer uma análise cuidadosa da sequência de erros.

20
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

É difícil dizer algo sobre os erros que ocorrem no Modelamento e


Simplificação. No caso de Simplificação pode-se fazer uma análise a
posteriori, isto é, substituir o resultado aproximado nas equações
iniciais e assim obter-se uma ideia sobre a grandeza do erro.

Sumário

Nesta apresentamos os algoritmos numéricos, que são aqueles


capazes de solucionar problemas matemáticos, fornecendo
resultados numéricos aproximados e mostramos os passos a serem
seguidos no processo de resolução de problemas.

21
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Deadman, E., Dongarra, J., Güttel, S., Hammarling, S., Higham,
N., Lucas, C., . . . Tisseur, F. (s.d.). Numerical Algorithms and
Software Development | The University of Manchester | School
of Mathematics. Obtido de The University of Manchester |
School of Mathematics:
http://www.maths.manchester.ac.uk/our-research/research-
groups/numerical-analysis-and-scientific-
computing/numerical-analysis/our-research/numerical-
algorithms-and-software-development/;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc.

UNIDADE Temática 1.3. Algoritmos de Pesquisas – Sequencial e Binária.

Os algoritmos de pesquisa são projetados para procurar ou recuperar


um elemento em qualquer estrutura de dados onde este está
armazenado. Este tipo de algoritmos resolve o problema de
recuperar informações armazenadas em alguma estrutura de dados
ou calculadas no espaço de pesquisa de um domínio de problema,
com valores discretos ou contínuos.
Os algoritmos de pesquisa formam uma parte importante de muitos
sistemas de informação. Algumas pesquisas envolvem a procura de
uma entrada em um banco de dados, como procurar pelo seu registro
no banco de dados do governo. Outros algoritmos de busca

22
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

procuram dentro de um espaço virtual, como aqueles que procuram


os melhores movimentos num jogo de xadrez (com jogador
automático ativo). Embora os programadores possam escolher entre
vários tipos de pesquisa, estes selecionam o algoritmo que melhor
corresponde ao tamanho e estrutura do banco de dados para
fornecer melhor experiência para o usuário.
Um problema geral de pesquisa pode ser descrito da seguinte
maneira: Localize um elemento x qualquer numa lista de elementos
distintos a1, a2, ... an ou determine se ele não está na lista. A solução
para esse problema de pesquisa é a localização de um termo na lista
que é igual a x e é 0 se x não estiver nessa lista.
Com base no tipo de operação de pesquisa, este módulo apresenta
dois tipos de algoritmos de pesquisa, a seguir:
• De pesquisa sequencial (ou linear).
• De pesquisa binária.
1.3.1. Algoritmos de pesquisa sequencial (ou de pesquisa linear)
A pesquisa sequencial é um tipo de algoritmo de pesquisa muito
básico e simples. Na pesquisa sequencial, procuramos um elemento
ou valor em uma determinada lista percorrendo-a desde o início, até
que o elemento ou valor desejado seja encontrado. Este tipo de
algoritmo verifica sequencialmente cada elemento da lista até
encontrar um elemento que corresponda ao valor desejado. Se o
algoritmo chegar ao final da lista, a pesquisa terminará sem sucesso.
A pesquisa sequencial (também chamada de linear) é um algoritmo
de escolha para listas curtas, porque é simples e requer um código
mínimo para ser implementado. Estes algoritmos analisam oprimeiro
item da lista para ver se é o item procurado e, em caso afirmativo, o
algoritmo termina. Se não, ele olha para o próximo item da lista, e
assim sucessivamente.
Modo de funcionamento
A pesquisa linear é um algoritmo básico de pesquisa usado em
estruturas de dados. É também chamado de pesquisa sequencial,
como dito anteriormente. É usada para encontrar um elemento
específico numa matriz ou lista. Não é obrigatório organizar essa lista
em qualquer ordem (ascendente ou descendente) como no caso da
pesquisa binária, da qual falaremos ainda nesta unidade temática.

23
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

A imagem abaixo mostra como essa pesquisa funciona. A partir do


primeiro item da lista, simplesmente passamos de item para item,
seguindo o pedido sequencial subjacente até encontrar o que se
procura ou ficar sem itens. Se chegamos ao final da lista, descobrimos
que o item que procuramos não estava presente.

Figura: Pesquisa linear para encontrar o elemento “J” numa


determinada lista ordenada de A-X.
Para a implementação desse algoritmo numa linguagem de
programação, escolheu-se como exemplo o JavaScript, por ser muito
simples de compreender. A função precisa da lista de todos os
elementos e do item que procuramos e retorna um valor booleano
(true ou false) para saber se a letra “J” está ou não presente. A
variável booleana encontrada é inicializada para falso (false) e é
atribuída o valor verdadeiro (true) se descobrimos o item “J” na lista,
neste caso.

Figura: Exemplo de código em JavaScript de uma pesquisa


sequencial.
Sabemos que à primeira vista é mais fácil de se gostar desse tipo de
algoritmos porque é muito simples de implementar, masinfelizmente
não são usados praticamente porque a pesquisa bináriaé muito mais
rápida que a pesquisa linear. Vamos então a seguir, introduzir a
pesquisa binária.

24
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

1.3.2. Algoritmos de pesquisa binária


Os algoritmos de pesquisa binária são geralmente aplicados numa
matriz ordenada ou listas de tamanho grande.
Este tipo algoritmo de pesquisa trabalha com o princípio de dividir e
conquistar. Para que a pesquisa binária funcione de forma correta, a
coleção ou lista de dados deve estar num formato ordenado.
A pesquisa binária procura um item específico comparando o item
mais central da coleção. Se houver uma correspondência, o índice do
item será retornado. Se o item do meio for maior que o item, o item
será pesquisado na sublista à esquerda do item do meio. Caso
contrário, o item é procurado na sublista à direita do item do meio.
Esse processo continua na sublista também até que o tamanho desta
reduza para zero.
A pesquisa binária é geralmente composta de 3 seções principais:
• Pré-processamento: ordena se a coleção de dados não
estiver ordenada.
• Pesquisa Binária: usando um loop ou recursão para dividir o
espaço de busca pela metade após cada comparação.
• Pós-processamento: determina candidatos viáveis no espaço
restante.
Modo de funcionamento
Na sua forma mais simples, a pesquisa binária opera numa sequência
contígua com um índice especificado à esquerda e à direita, chamado
de espaço de pesquisa. A pesquisa binária mantém os índices
esquerdo, direito e médio do espaço de pesquisa e compara o destino
da pesquisa ou aplica a condição de pesquisa ao valor médio da
coleção; se a condição for insatisfeita ou valores desiguais, a metade
na qual o alvo não se encontra é eliminada e a busca continua na
metade restante até que seja bem sucedida. Se a pesquisa terminar
com uma metade vazia, a condição não poderá ser atendida e a
condição não será satisfeita.
A ideia é comparar o elemento a pesquisar com o elemento que está
ao meio da lista e analisar 3 situações diferentes:
• se o elemento é igual ao que está ao meio,
• se o elemento está antes do meio,

25
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• se o elemento está depois do meio.


Se ocorrer a 1ª situação, então foi encontrado o elemento naquela
posição.
Se ocorrer a 2ª situação, então basta pesquisar o elemento na
sublista até ao meio.
Se ocorrer a 3ª situação, então basta pesquisar o elemento na
sublista do meio para a frente.

Figura: Pesquisa linear para encontrar o elemento “J” numa


determinada lista ordenada de A-X.
Caso tenhamos uma lista com os valores ordenados de forma
numérica ou alfabética, é possível fazer uma busca muito mais
rápida. Ao invés de pesquisar a lista em sequência como no método
de pesquisa anterior, uma pesquisa binária começa examinando o
item central. Se esse item for o que se procura, a pesquisa termina.
Se não for o item buscado, pode-se usar a natureza ordenada da lista
para eliminar a metade dos itens restantes. Se o item que se procura
for maior do que o item central, sabe-se que toda a metade inferior
da lista, bem como o item central, podem ser eliminados de uma
consideração mais aprofundada. O item, se estiver na lista, deve
então estar na metade superior. Pode-se então repetir o mesmo
processo com a metade superior.
A Figura abaixo mostra como esse algoritmo pode encontrar
rapidamente, a letra “J”, usando também a linguagem JavaScript,
para questões de teste.

26
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Exemplo de código em JavaScript de uma pesquisa binária.


Ajudaremos a perceber melhor o processo de busca binária com um
exemplo pictórico, a seguir.
Temos a seguir um array (que pode ser considerado como uma lista
simples, neste exemplo) ordenado e vamos supor que precisamos
procurar a localização do valor 31 usando a pesquisa binária.

Primeiro, vamos determinar metade da matriz usando essa fórmula:


meio = primeiro + (ultimo - meio) / 2

Assim, teremos 0 + (9 - 0) / 2 = 4 (valor inteiro de 4.5). Então, 4 é o


meio do array.

Nós mudamos o nosso primeiro para meio + 1 e encontramos o novo


valor médio novamente.
primeiro = meio + 1

27
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

meio = primeiro + (ultimo - primeiro) / 2

Nosso novo meio é 7 agora. Agora devemos comparar o valor


armazenado na localização 7 com o nosso valor alvo 31.

Após verificar concluímos de seguida que o valor armazenado na


localização 7 não é o que se procura, e sim maior. Portanto, o valor
deve estar na parte inferior dessa posição.

Assim, calculamos o meio novamente usando as mesmas fórmulas.


Desta vez é 5.

Agora deve-se comparar o valor armazenado na localização 5 com o


nosso valor alvo. Parece que coincide, pode-se verificar na imagem
abaixo:

Aqui, concluímos então que o valor alvo 31 é armazenado na posição


5.
A pesquisa binária divide os itens pesquisáveis em metades e, assim,
reduz a contagem de comparações a serem feitas em números muito
menores.

28
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

1.3.3. Pesquisa Linear vs. Pesquisa Binária


• Uma pesquisa linear procura um item de cada vez, sem saltar
para nenhum item.
• O tempo gasto para pesquisar elementos continua
aumentando conforme o número de elementos é
aumentado. Uma pesquisa binária, no entanto, reduz a sua
pesquisa para metade assim que se encontra o item central
de uma lista ordenada.
• O elemento central é verificado para ver se é maior ou menor
que o valor a ser pesquisado. Assim, a pesquisa é feita para
metade da lista fornecida.
Diferenças mais notáveis
Os dados de entrada precisam ser ordenados obrigatoriamente na
pesquisa binária enquanto que na pesquisa linear, não.
A pesquisa linear faz o acesso sequencial, enquanto os dados de
acesso da pesquisa binária aleatoriamente.
A pesquisa linear executa comparações de igualdade e a pesquisa
binária executa comparações de pedidos.

Sumário

Nesta Unidade temática apresentamos os algoritmos de Pesquisas –


Sequencial e Binária, usados geralmente para resolver o problema de
recuperar informações armazenadas em alguma estrutura de dados
e apresentamos os exemplos praticos de implementacao desses
algoritmos na vida real.

29
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Deadman, E., Dongarra, J., Güttel, S., Hammarling, S., Higham,
N., Lucas, C., . . . Tisseur, F. (s.d.). Numerical Algorithms and
Software Development | The University of Manchester | School
of Mathematics. Obtido de The University of Manchester |
School of Mathematics:
http://www.maths.manchester.ac.uk/our-research/research-
groups/numerical-analysis-and-scientific-
computing/numerical-analysis/our-research/numerical-
algorithms-and-software-development/;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Data Structures Tutorial | Studytonight. (218). Obtido de
Studytonight: https://www.studytonight.com/data-structures.

UNIDADE Temática 1.4. Algoritmos de Ordenação.

Ordenar não é nada mais do que organizar os dados em ordem


crescente ou decrescente. O termo ordenação entrou em cena,
quando os seres humanos perceberam a importância de pesquisar
rapidamente.
Ordenar elementos de uma lista é um problema que ocorre em
muitos contextos. Por exemplo, para produzir uma lista telefônica, é
necessário alfabetizar os nomes dos contatos. Da mesma forma,
produzir um diretório de músicas disponíveis para download requer
que os títulos sejam colocados em ordem alfabética.

30
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Colocar endereços em ordem numa lista de e-mail pode determinar


se há endereços duplicados. Criar um dicionário útil requer que as
palavras sejam colocadas em ordem alfabética. Enfim, há tantas
coisas na nossa vida real que precisamos pesquisar e que teria sido
muito trabalhoso se os dados fossem mantidos desordenados e não
selecionados. Felizmente, o conceito de ordenação passou a existir,
facilitando a organização de dados numa ordem específica, que
facilita a pesquisa.
1.4.1. Ordenação Estável e Não Estável
Se um algoritmo de ordenação, depois de ordenar o conteúdo, não
altera a sequência de conteúdos semelhantes em que aparecem, é
chamado de ordenação estável.

Se um algoritmo de ordenação, depois de ordenar o conteúdo,


alterar a sequência de conteúdo semelhante em que aparecem, ele é
chamado de ordenação não estável ou instável.

A estabilidade de um algoritmo é importante quando desejamos


manter a sequência de elementos originais, como em uma tupla de
banco de dados, por exemplo.

31
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

1.4.2. Convenções usadas nos algoritmos de ordenação


Quando se fala de ordenação alguns termos são geralmente usados,
eis abaixo uma breve descrição destes.
Ordem Crescente
Diz-se que uma sequência de valores está em ordem crescente, se o
elemento sucessivo for maior que o anterior. Por exemplo, 1, 3, 4, 6,
8, 9 estão em ordem crescente, pois cada elemento seguinte é maior
que o elemento anterior.
Ordem decrescente
Diz-se que uma sequência de valores está em ordem decrescente, se
o elemento sucessivo for menor que o atual. Por exemplo, 9, 8, 6, 4,
3, 1 estão em ordem decrescente, pois cada elemento seguinte é
menor que o elemento anterior.
Ordem não crescente
Diz-se que uma sequência de valores está em ordem não crescente,
se o elemento sucessivo for menor ou igual ao seu elemento anterior
na sequência. Essa ordem ocorre quando a sequência contém valores
duplicados. Por exemplo, 9, 8, 6, 3, 3, 1 estão em ordem não
crescente, pois cada próximo elemento é menor ou igual a (no caso
de 3), mas não maior que qualquer elemento anterior.
Ordem não decrescente
Diz-se que uma sequência de valores está em ordem não
decrescente, se o elemento sucessivo for maior ou igual ao seu
elemento anterior na sequência. Essa ordem ocorre quando a
sequência contém valores duplicados. Por exemplo, 1, 3, 3, 6, 8, 9
estão em ordem não decrescente, pois cada próximo elemento é
maior ou igual a (no caso de 3), mas não menos que o anterior.
No que tange aos tipos, existem muitas técnicas diferentes
disponíveis para ordenação, diferenciadas por seus requisitos de
eficiência e espaço de memória necessária para completar o
algoritmo. A seguir são apresentadas algumas técnicas ou métodos
de ordenação que serão abordadas neste módulo:
• Método “bolha” (Bubble Sort).
• Método de ordenação por inserção (Insertion sort).
• Método de ordenação por seleção (Selection Sort).

32
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• Método de ordenação rápida (Quick Sort).


1.4.3. Método “bolha” (Bubble Sort)
O Bubble Sort é um algoritmo simples que é usado para ordenar um
dado conjunto de n elementos fornecidos na forma de um array com
um número n de elementos. O Bubble Sort compara todos os
elementos, um por um, e ordena-os com base nos seus valores.
Se a determinada lista tiver que ser ordenada em ordem crescente, a
ordenação em bolha começará comparando o primeiro elemento
dessa lista com o segundo, se o primeiro elemento for maior que o
segundo, ele trocará os elementos e, em seguida, segue em frente
para comparar o segundo e o terceiro elemento, e assim por diante.
Se tivermos n elementos totais, precisamos repetir esse processo por
n-1 vezes.
A classificação ocorre percorrendo todos os elementos um por um e
comparando-o com o elemento adjacente e trocando-os, se
necessário.
Modo de funcionamento
Tomaremos uma matriz não ordenada para o nosso exemplo, a
seguir.

A ordenação de bolhas começa com os primeiros dois elementos,


comparando-os para verificar qual deles é maior.

Nesse caso, o valor 33 é maior que 14, portanto, ele já está numa
posição ordenada. Em seguida, comparamos 33 com 27.

33
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta Unidade temática vimos os algoritmos de ordenação, que


consistem basicamente em organizar os dados de uma lista numa
certa ordem, geralmente em ordem crescente ou decrescente.

Exercícios de AUTO-AVALIAÇÃO

Perguntas

1. O que é um algoritmo?
2. O que é um programa?
3. Um algoritmo quando programado num computador é
constituído pelo menos das 3 partes. Mencione as.
4. Quais são os passos para a resolução de um problema através
de um algoritmo numérico simples?
5. Considere o seguinte algoritmo (v: vetor de entrada, e: índice
da esquerda, d: índice da direita do vetor).

a) Escreva o código para função aux de modo que o algoritmo


mostrado ordene os elementos no vetor v.

34
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Respostas:

1. R% Um algoritmo é uma sequência lógica de ações a serem


executadas para se executar uma determinada tarefa.

2. R% Um Programa é a formalização de um algoritmo em uma


determinada linguagem de programação, segundo suas regras de
sintaxe e semântica, de forma a permitir que o computador possa
entender a sequência de ações.

3. R% - Entrada de dados, Processamento de dados, Saída de dados.

4. R% Dado um problema técnico, para chegarmos a um resultado


numérico, faz-se necessário percorrer uma sequência de passos que
são: Modelamento, simplificação, escolha de métodos, escolha de
parâmetros;
5. a) R%

35
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc.

36
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

TEMA – II: ESTRUTURAS DE DADOS FUNDAMENTAIS.

UNIDADE Temática 2.1. Introdução às estruturas de dados


fundamentais.
UNIDADE Temática 2.2. Pilhas, Filas e Gráficos.
UNIDADE Temática 2.3. Árvores e Tabelas de Hash.
UNIDADE Temática 2.4. EXERCÍCIOS deste tema.

• Introduzir as estruturas de dados fundamentais.


• Apresentar exercícios com resolução para consolidação.

Objectivos
específicos

UNIDADE Temática 2.1. Introdução às estruturas de dados fundamentais.

Pilhas
Para iniciar, um exemplo: um determinado produto é composto por
diversas peças (digamos p1, p2, ..., pn). O processo de montagem
deste produto é automático (executado por uma máquina) e exige
que as peças sejam colocadas em uma ordem específica (primeiro a
p1, depois a p2, depois a p3 e assim por diante). As peças são
empilhadas na ordem adequada e a máquina de montagem vai
retirando peça por peça do topo desta pilha para poder montar o
produto.
A mesma máquina que faz a montagem é capaz de trocar uma peça
quebrada de um produto já montado. O que a máquina faz é
desmontar o produto até chegar na peça defeituosa, trocá-la e então
depois recolocar as peças que foram retiradas. Isso também é feito
com o uso da pilha de peças. Veja a seguir o algoritmo que a máquina
montadora implementa para fazer a manutenção de um produto
defeituoso.
1. Retirar e empilhar peça por peça do produto até chegar na
peça defeituosa.
2. Retirar a peça defeituosa.

37
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

3. Colocar uma peça nova sem defeitos


4. Desempilhar e montar peça por peça do topo da pilha até a
pilha ficar vazia.

Figura: Algoritmo para reparação do ventilador.


De alguma forma uma peça precisa ser representada no nosso
programa. Como estaremos usando orientação a objetos as peças
serão representadas por objetos.
Uma classe Java será criada somente para modelar as peças, algo
idêntico ao código a seguir:

38
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Com a classe “Peca”, já é possível criar objetos para representar as


peças que a máquina montadora utiliza. Porém, o sistema deve
definir como guardar estes objetos, ou seja, ele precisa escolher uma
estrutura de dados.
Esta estrutura de dados deve manter os dados seguindo alguma
lógica e deve fornecer algumas operações para a manipulação destes
e outras operações para informar sobre seu próprio estado.
Solução de problemas das Peças
Para implementar o algoritmo de manutenção do carro, é necessário
criar uma estrutura de dados que se comporte como a pilha de peças.
Vamos chamar esta estrutura de dados de Pilha.
Primeiro, definimos a interface da Pilha (conjunto de operações que
queremos utilizar em uma Pilha).
1. insere uma peça (coloca uma peça no topo da Pilha).
2. Remove uma peça (retira a peça que está no topo da Pilha).
3. Informa se a Pilha está vazia.
Podemos criar uma classe Pilha para implementar esta estrutura de
dados. Os métodos públicos desta classe serão a implementação das
operações.

39
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

O primeiro fato importante que devemos observar é que uma vez que
a interface da Pilha foi definida, já saberíamos usar a classe Pilha.
Vamos criar uma classe de teste bem simples para exemplificar o uso
de uma Pilha.

O segundo fato importante é que a estrutura que queremos aqui é


muito similar as Listas que vimos anteriormente. A semelhança
fundamental entre as Listas e as Pilhas é que ambas devem
armazenar os elementos de maneira sequencial. Este fato é o ponto-
chave deste capítulo.
Qual é a diferença entre uma Lista e uma Pilha? A diferença está nas
operações destas duas estruturas de dados. As operações de uma
Pilha são mais restritas do que as de uma Lista. Por exemplo, você
pode adicionar ou remover um elemento em qualquer posição de
uma Lista mas em uma Pilha você só pode adicionar ou remover do
topo.

40
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Então, uma Lista é uma estrutura mais poderosa e mais genérica do


que uma Pilha. A Pilha possui apenas um subconjunto de operações
da Lista. Então o interessante é que para implementar uma Pilha
podemos usar uma Lista. Isso mesmo! Vamos criar restrições sobre
as operações da Lista e obteremos uma Pilha.
Nós implementamos dois tipos de Listas: Vetores e Listas Ligadas.
Vimos, também que, na biblioteca do Java, há implementações
prontas para estes dois tipos de Listas. Neste capítulo, vamos utilizar
a classe LinkedList para armazenar as peças que serão guardadas na
Pilha.

Dentro da Pilha teremos uma LinkedList encapsulada, que vai


simplificar bastante o nosso trabalho: delegaremos uma série de
operações para essa Lista Ligada, porém sempre pensando nas
diferenças essenciais entre uma Pilha e uma Lista.
Devemos ter um getPecas() que devolve uma referência para essa
nossa LinkedList? Nesse caso a resposta é não, pois estaríamos
expondo detalhes de nossa implementação, e o usuário dessa classe
poderia mexer no funcionamento interno da nossa pilha,
desrespeitando as regras de sua interface. É sempre uma boa prática
expor o mínimo possível do funcionamento interno de uma classe,
gera um menor acoplamento entre as classes.
Operações em pilhas: Inserir uma peça
As peças são sempre inseridas no topo da Pilha. Ainda não definimos
onde peca o topo da Pilha. Como estamos utilizando uma Lista para
guardar os elementos então o topo da Pilha poderia ser tanto o
começo ou o •m da Lista. Aqui escolheremos o fim da Lista.
Então, inserir na Pilha é simplesmente adicionar no fm da Lista.

Recordando que o método add(Object) adiciona no fim da Lista.

41
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Operações em pilhas: Remover uma peça


A remoção também é bem simples, basta retirar o último elemento
da Lista.

É interessante observar que se o método remove() for usado com a


Pilha vazia então uma exceção será lançada pois o método
remove(int) da List lança IndexOutOfBoundsException quando não
existir elemento para remover.
Operações em pilhas: Informar se a pilha está vazia
Para implementar esta operação basta verificar se o tamanho da Lista
é zero.

Na classe LinkedList existe também o método isEmpty() que poderia


ter sido usado aqui mais convenientemente.
Generalização
NossaPilha só funciona para guardar objetos da classe Peca. Vamos
generalizar a Pilha para poder armazenar qualquer tipo de objeto.
Isso será feito utilizando a classe Object da qual todas as classes
derivam direta ou indiretamente. Criaremos uma LinkedList de
Object em vez de uma LinkedList de Peca.

42
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Agora, podemos guardar qualquer tipo de objeto na Pilha. Isso é uma


grande vantagem pois a classe Pilha poderá ser reaproveitada em
diversas ocasiões. Mas, há uma desvantagem, quando removemos
um elemento da Pilha não podemos garantir qual é o tipo de objeto
que virá.
No Java 5, poderíamos usar Generics para solucionar este problema.
A nossa classe Pilha poderia ser uma classe parametrizada. Na criação
de um objeto de uma classe parametrizada é possível dizer com qual
tipo de objeto que queremos trabalhar.
Algo deste tipo:
Pilha de Peças pilha = new Pilha de Peças();
Traduzindo este código para Java 5 de verdade, ficaria assim:

Só que para utilizar o recurso do Generics devemos parametrizar a


classe Pilha.

43
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Poderíamos também adicionar outros métodos provavelmente úteis


a manipulação de uma pilha, como saber o tamanho da pilha, espiar
um elemento em determinada posição, entre outros.
Testemos a classe Pilha que usa Generics.

Neste exemplo, criou-se duas Pilhas. A primeira vai armazenar


somente objetos do tipo Peca e a segunda só String.
Se você tentar adicionar um tipo de objeto que não corresponde ao
que as Pilhas estão guardando então um erro de compilação será
gerado para evitar que o programador cometa um erro lógico.
Usando a API do Java
Na biblioteca do Java existe uma classe que implementa a estrutura
de dados que foi vista neste capítulo, esta classe chama-se Stack e
será testada pelo código abaixo.

44
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Para evitar fazer casting de objetos, podemos utilizar o recurso de


Generics aqui também.

Escapando do Labirinto
Ao percorrer um labirinto para fugir do Minotauro, existe um
algoritmo bastante simples: você sempre escolhe o caminho mais a
direita em toda oportunidade que aparecer a separação do caminho
atual em dois ou mais.
Caso caia em um beco sem saída, deve voltar até o último ponto em
que optou pelo caminho mais a direita e mudar sua decisão: agora
você deve tentar o caminho mais a direita, porém excluindo o que foi
anteriormente selecionado (e que causou a chegada a um beco sem
saída). Se você não tiver mais nenhuma opção, deve voltar mais ainda
pelo caminho já percorrido até encontrar outro ponto em que você
teve a opção de escolha. Esse processo de guardar o caminho e
escolhas já feitos para tomar outra decisão é conhecido como
backtracking.
Para implementar esse algoritmo você deve se lembrar do caminho
percorrido e, além disso, em cada posição (x, y) em que houve opção
de escolha deve também lembrar qual foi a última escolha feita, para
poder mudá-la quando você voltar o caminho (backtrack).

45
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Uma solução é utilizar uma Pilha que armazene cada (x,y) onde uma
decisão foi tomada, e também guardar um inteiro opção que
represente qual das opções foi escolhida no atual caminho: se
escolhemos o mais da direita, guardamos 1, se já precisamos voltar
uma vez e escolhemos o segundo mais da direita, guardamos 2, etc...
Assim quando voltarmos a este ponto e precisarmos mudar de
decisão, basta incrementar esse número.
Caso não haja mais caminhos a percorrer por esse lado (isso é, se
opção == totalDeOpcoes daquele ponto), devemos regredir mais
ainda o nosso caminho.
A maneira que percorremos esse labirinto é conhecida como busca
em profundidade: vamos nos aprofundando no caminho atual até
não poder mais, e só quando não dermais voltamos a profundidade
do caminho para tentar outra alternativa.
Busca em Profundidade está muito relacionada ao uso de uma Pilha,
e também pode ser realizada com o uso de recursão. O algoritmo
sempre funciona, desde que haja saída e que você seja mais rápido
que o fatal Minotauro!

Sumário

Na unidade corrente introduzimos algumas estruturas de dados


consideradas fundamentais e apresentamos igualmente alguns
exemplos relacionados, como forma de consolidação. Na unidade
seguinte daremos mais ênfase às estruturas de dados mencionadas
nesta unidade.

46
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press.

UNIDADE Temática 2.2. Pilhas, Filas e Gráfos.

Filas
Estamos acostumados diariamente com as filas em vários lugares:
nos mercados, bancos, hospitais, nos terminais de carro, entre
outros. Filas são importantes pois elas determinam a ordem de
atendimento das pessoas.
As pessoas são atendidas conforme a posição delas na fila. O próximo
a ser atendido é o primeiro da fila.
Quando o primeiro da fila é chamado para ser atendido a fila “anda”,
ou seja, o segundo passa a ser o primeiro, o terceiro passa a ser o
segundo e assim sucessivamente até a última pessoa.
Normalmente, para entrar em uma fila, uma pessoa deve se colocar
na última posição, ou seja, no fim da fila. Desta forma, quem chega
primeiro tem prioridade. Neste capítulo, estamos interessados em
desenvolver estrutura de dados com o comportamento das filas.

47
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Assim como Listas e Pilhas, as Filas são estruturas de dados que


armazenam os elementos de maneira sequencial.
Assim como as Pilhas, as Filas têm operações mais restritas do que as
operações das Listas. Nas Filas, os elementos são adicionados na
última posição e removidos da primeira posição. Nas Listas, os
elementos são adicionados e removidos de qualquer posição. Então,
podemos implementar uma Fila simplesmente colocando as
restrições adequadas nas operações de adicionar e remover
elementos de uma Lista. Isso é bem parecido ao que fazemos com as
Pilhas.
Vamos implementar na sequência uma Fila de Aluno. Iremos
aproveitar a classe Aluno feita no capítulo de armazenamento
sequencial.

Figura: Fila de pessoas.


Interface de uso
As operações que formam a interface de uso da Fila de alunos são:
1. Insere um Aluno (coloca um aluno no fim da Fila).
2. Remove um Aluno (retira o aluno que está no começo da Fila).
3. Informa se a Fila está vazia.
O esboço da classe Fila seria mais ou menos assim:

48
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Agora que já temos a interface de uso da Fila definida vamos escrever


algum teste sobre como ela deveria se comportar.

Como já foi dito aqui vamos implementar Fila utilizando algum tipo
de Lista. Neste capítulo, vamos utilizar a classe LinkedList para
armazenar os alunos da Fila.

Operações em fila
Em seguida, implementaremos as operações da Fila de aluno.
1. Inserir um aluno
Os alunos que entram na Fila devem sempre se colocar no fim da
mesma. Vamos definir que o fim da Fila é o fim da Lista que estamos
utilizando para implementar.
Então, entrar na Fila e adicionar no fim da Lista.

49
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

2. Remover um aluno
O próximo aluno a ser atendido é sempre o que está no início da fila.
No nosso caso, quem está no início da fila é o aluno que está no início
da Lista.
Então, basta remover o primeiro aluno.

É bom observar que se o método remove() for usado com a Fila vazia
então uma exceção será lançada pois o método removeFirst() lança
IndexOutOfBoundsException quando não existir elemento para
remover.
3. Informar se a fila esta vazia
Para implementar esta operação basta verificar se o tamanho da Lista
é zero.

Generalização
A Fila só funciona para guardar objetos da classe Aluno. Vamos
generalizá-la para poder armazenar qualquer tipo de objeto. Isso será
feito utilizando a classe Object da qual todas as classes derivam direta
ou indiretamente. Criaremos uma LinkedList de Object em vez de
uma LinkedList de Aluno.

50
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Agora, podemos guardar qualquer tipo de objeto na Fila. Isso é uma


grande vantagem pois a classe Fila poderá ser reaproveitada em
diversas ocasiões. Mas, há uma desvantagem, quando removemos
um elemento da Fila não podemos garantir qual é o tipo de objeto
que virá.
A solução para este problema é utilizar o recurso do Generics. A nossa
classe Fila vai ser uma classe parametrizada. Assim, quando criarmos
uma Fila poderemos definir com qual tipo de objetos ela deve
trabalhar.
Algo deste tipo:
Fila de alunos fila = new Fila de alunos();
Traduzindo este código para Java, ficaria assim:
Fila<Aluno> fila = new Fila<Aluno>();
Agora, precisamos parametrizar a classe Fila.

Criemos duas Filas, uma para Aluno e outra para String.

51
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Em tempo de compilação, é verificado o tipo de objetos que estão


sendo adicionados na Fila. Portanto, se você tentar inserir um objeto
do tipo Aluno em uma Fila de String um erro de compilação será
gerado.

Utilizando a Api do Java


Na biblioteca do Java, existe uma interface que define a estrutura de
dados Fila. Essa interface chama-se Queue (Fila), umas das classes
que implementam Queue é a LinkedList. O funcionamento fica
extremamente parecido com a implementação que fizemos nesta
unidade.

52
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Grafos
Os grafos são estruturas matemáticas usadas para representar ideias
ou modelos, por intermédio de uma ilustração, gráfico ou esquema.
Estritamente, em matemática, a teoria dos grafos e utilizada para
representar o relacionamento entre dois ou mais conjuntos,
grandezas ou valores. A representação de um mapa de rotas, redes e
outros modelos semelhantes pode ser feita por meio do que se
denomina grafos.
Vamos tomar, por exemplo, um mapa de rotas áereas. Na figura
abaixo, nota-se que existem várias rotas de um ponto a outro, por
exemplo, de Florianopolis a Brasília existem as possibilidades via
Curitiba, via São Paulo ou via Rio de Janeiro. Algumas rotas podem
ter mais escalas, por exemplo, pode-se ir a Brasília por São Paulo,
passando por Curitiba, Rio e Belo Horizonte. Neste exemplo, temos a
linha que liga cada dois pontos. Note, entretanto, que existe uma rota
de Florianopolis a Florianópolis que, digamos, pode representar um
vôo panorâmico pela ilha que decola e retorna ao mesmo ponto.
O mapa de rotas contém pontos, que representam as cidades, e estão
ligados por linhas, que representam as rotas aéreas.
Cada um dos pontos de um grafo é denominado no e cada uma das
ligações são denominadas arcos. A representação de dados como
estrutura de dados, pode ser aplicada em:

53
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• Mapas de distâncias
• Mapas Metabólicos
• Diagramas e Fluxogramas
• Redes de computadores
• Redes Neurais
• Estruturas químicas

Figura: Mapa a representar rotas aéreas.


Definições
Grafos são definidos, matematicamente, como triplas ordenadas
(n,a,g), onde n é um conjunto não-vazio de nós ou vértices, a é um
conjunto de arcos ou arestas e g é uma função que associa cada arco
a a um par não ordenado x–y de n, denominados extremidades de a.

Figura: Exemplo de um grafo, seus arcos e nós.


g(a1) = 1−2
g(a2) = 1–2
g(a3) = 2−2
g(a4) = 2−3
g(a5) = 1−3

54
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

g(a6) = 3−4
Como o nó 5 não está ligado por nenhum arco, não temos uma
função que o utilize.
Os arcos de um grafo podem ser simples ou direcionados, o que
significa que a relação entre os nós têm um sentido. Neste caso, o
grafo recebe o nome de dígrafo.
Dígrafos (ou grafos direccionados) são triplas ordenadas (n,a,g), onde
n é um conjunto não-vazio de nós, a é um conjunto de arcos ou
vértices e g é uma função que associa cada arco a a um par ordenado
(x,y) de n, onde x é o ponto inicial e y é o ponto final de a.

Figura: Representação de grafo direcionado.


A figura representa um grafo direcionado (dígrafo) com 5 nós e 6
arcos, que pode ser descrito pelas funções:
g(a1) = 1,2
g(a2) = 2,1
g(a3) = 2,2
g(a4) = 2,3
g(a5) = 1,3
g(a6) = 3,4
Terminologia
A terminologia utilizada na teoria dos grafos compreende as
definições dos elementos, características e propriedades dos grafos.
Os elementos de um grafo compreendem:
• Laços: São arcos que conectam apenas um nó.
• Nós adjacentes: São dois nós ligados por um arco.
• Arcos Paralelos: Dois arcos com as mesmas extremidades, ou
seja, conectam os mesmos nós.

55
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• Nó isolado: Um nó que não é adjacente a nenhum outro nó.


• Grau de um Nó: Número de arcos que conectam um nó.
Por exemplo, na figura abaixo, o nó 2 tem um laço; o nó 5 é adjacente
aos nós 2,3 e 4, e quanto o nó 2 é adjacente ao 1, 5 e ele mesmo; os
arcos e e f são paralelos; o nó 6 é um nó isolado; e o n´o 6 tem grau
zero, o nó quatro tem grau 2, os nós 1, 2 e 5 têm grau 3 e o nó 3 tem
grau 4.

Figura: Elementos de um grafo.


As características de um grafo podem ser descritas como:
• Grafos Simples: São grafos sem laços ou arcos paralelos.
• Grafos Completos: São grafos onde quaisquer dois nós
distintos são adjacentes.
• Grafos Conexos: São grafos onde sempre existe um caminho
de um nó a outro, por meio de um ou mais arcos.

Figura: Características dos grafos: (a) Simples, (b) completo e (c)


Conexo.
A figura a cima exemplifica as características de um grafo.

56
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Quanto às propriedades, os grafos podem ser isomórficos e/ou


planares.
Um grafo é dito isomorfos quando pode ser representado de duas ou
mais maneiras, sendo que têm os mesmos nós, os mesmos arcos e a
mesma função que associa cada extremidade dos arcos, ou seja,
Dizemos que dois grafos (N1,A1,G1) e (N2,A2,G2) são isomorfos se, e
somente se ∃f1 : N1 → N2 e f2 : A1 → A2 (veja figura 4.6).

Figura: Grafos isomorfos.


Na figura a cima, as funções de nós e arcos podem ser escritas como:
f1 : 1 → a; 2 → b; 3 → c; 4 → d f2 : a1 → e1; a2 → e2
A planaridade é a propriedade de um grafo poder ser representado
em um plano, de modo que seus arcos não se intersectam entre si. A
figura a baixo exemplifica grafos planares.
Euler observou que a o número de nós n, arcos a e regiões r
delimitadas pelos arcos de um grafo planar ´e dado pela equação (n
− a) + r = 2, que é conhecida como fórmula de Euler.

Figura: Grafos planares.


Grafos e Estrutura de dados
Para a representação de dados de um conjunto que pode ser
modelado como um grafo, pode-se usar uma representação matricial
(array) ou uma lista ligada. Estas representações levam em conta as
relações entre nós adjacentes e, por isso, são denominadas de matriz
adjacência ou lista de adjacência de um grafo.

57
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Exemplo.
Grafos direccionados e matriz adjacência
A representação de grafos direccionados (dígrafos) em uma matriz
adjacência, quase nunca gera uma matriz simétrica. Na maioria das
vezes, a matriz é uma matriz boolena esparsa. Por exemplo, o grafo
da figura a baixo pode ser representado pela matriz:

Neste caso, podemos observar que a matriz não é simétrica, e os


arcos (6,7) e (7,6) não são paralelos, apesar de suas posições
simétricas na matriz adjacência.
Grafos como este podem ser representados, ainda, por relações
binárias, ou seja, se N é um conjunto de nós de um grafo
direccionado, então (ni,nj) é um par ordenado, tal que:

58
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Exemplo de grafo direcionado.


∃(ni,nj) ⇐⇒ ∃g(ai,j) = ni ∼ nj.

No caso do grafo acima, podemos representá-lo como um conjunto


de pares ordenados:
N = (2,1),(2,3),(2,5),(3,4),(4,2),(5,6),(6,1),(6,7),(7,6)
Note que somente existe um conjunto de pares ordenados N para um
grafo G se este não tiver arcos paralelos. E, como uma relação binária
em um conjunto pode ter as propriedades de reflexibilidade,
simetria, antisimetria e transitividade, qualquer destas
propriedades que o conjunto N apresentar, reflectirá em G e na
matriz booleana.
Acessibilidade dos nós de um grafo
Dizemos que um nó nj de um grafo pode ser acessado a partir de um
nó ni se, e somente se, existir um caminho de ni para nj. O conceito
de acessibilidade de um nó é de grande importância no estudo e
análise de redes, principalmente de redes de computadores, de
telefonia, de energia, água etc...
Considere o grafo da figura “Acessibilidade dos nós”.

Figura: Acessibilidade dos nós.

59
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sua matriz adjacência,

não dá muita informacão, pelo menos de maneira clara, sobre a


acessibilidade de cada nó, uma vez que ela explicita um arco (o
caminho de um nó para o adjacente).
Entretanto, se tomarmos a matriz adjacência e calcularmos o produto
booleano dela com ela mesmo, teremos o nó seguinte (o caminho
após dois arcos). Esta é uma matriz de acesso de um nó a outro, por
meio de dois arcos:

Note que A · A, aqui representada por A(2), é um produto booleano e


não o quadrado da matriz A (A2). A matriz A(2) é, portanto:

Os p caminhos seguintes, onde p é o máximo de caminhos possíveis,


podem ser encontrados a partir de:

A multiplicação lógica das matrizes obtidas gera uma matriz que


indica o alcance de um nó por 1,2,···, p arcos:

60
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

M = A ∨ A(2) ∨ ··· ∨ A(p)

Finalmente, a matriz acessibilidade B é obtida pela transposição de


M, ou seja:

Caminho mínimo
Os grafos podem representar ligação entre dados, onde os arcos
apresentam “pesos” ou valores que especificam alguma
característica da conexão. Em muitos casos, a solução de um
problema depende de se encontrar o caminho de menor “custo” ou
de menor valor ou, ainda, de maior eficiência. Este caminho recebe o
nome de caminho mínimo entre dois nós de um grafo.
Algoritmos para grafos
Quando os grafos têm poucos nós, todas as operações e cálculos que
envolvam matrizes (adjacência ou acessibilidade) podem, facilmente,
ser efetuados manualmente. No entanto em situações onde o
número de nós ´e maior, a utilização de um computador pode auxiliar
no cálculo destas estruturas. Assim, vamos verificar como se pode
implementar tais algoritmos. Para isso, vamos considerar a descrição
do algoritmo que pode ser implementado em qualquer linguagem.
1. Algoritmo de Warshall
O primeiro algoritmo nos permite achar a matriz acessibilidade de um
grafo. Para isso, vamos considerar um grafo G com n nós, para o qual
se necessita de n+1 matrizes para cada nível de acessibilidade. Tal
algoritmo é conhecido como algoritmo de Warshall.
Exemplo: Algoritmo de Warshall

61
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

O algoritmo de Warshall começa com a matriz adjacência (M0) e


calcula as outras matrizes M1, M2, ... , Mn. Note que é suficiente
calcular até o número de nós, pois qualquer nó pode ser acessível
pelo número de passos igual ao número de nós, não interessando as
outras repetições.
2. Caminho de Euler
O problema do caminho de Euler que levou o nome do matemático
suíço Leonard Euler, também é conhecido como “problema das sete
pontes”, ele é baseado em uma cidade dividida por um rio e com uma
porção insular, ligadas por sete pontes, em sua época denominada
de Konigsberg, actualmente Kaliningrad.
O problema consistia em determinar se era possível fazer um tour
pela cidade passando em cada uma das pontes apenas uma vez. Euler
solucionou o problema, matematicamente, representando as pontes
de Kaliningrado como arcos de um grafo.
O algoritmo do caminho de Euler serve para determinar se existe um
caminho de Euler em um grafo conexo qualquer. O algoritmo conta o
número de nós adjacentes a cada nó para determinar se este número
é par ou ímpar.
Exemplo: Algoritmo para o caminho de Euler

62
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

3. Algoritmo do Caminho Mínimo


Vamos supor que exista um mapa de cidades que sejam todas
interligadas e que possa ser representado por um grafo simples
conexo. Neste caso existe um caminho entre quaisquer cidades x e y
e, considerando as distâncias entre elas, percorrida por vários
caminhos, existirá um ou mais deles que será o mais curto. O
problema de identificar o caminho mais curto ´e denominado
“caminho mínimo” de um grafo.
A solução de tal problema é bastante importante para redes de
computadores ou de comunicação. O algoritmo para resolver este
problema foi estabelecido por Dijkstra e, por isso, ficou conhecido
como algoritmo de Dijkstra e é valido para qualquer grafo simples
conexo com pesos positivos em seus arcos.
4. Problema do Caixeiro Viajante
Existem várias versões deste problema, mas a forma mais conhecida
é a cada passo escolher a cidade vizinha mais próxima. Com as
seguintes regras:
1. Começar numa cidade qualquer;
2. Dessa cidade, ir para cidade mais próxima que ainda não foi
visitada;
3. Continuar dessa forma, até todas as cidades terem sido
visitadas; da última, regressar à cidade de onde se saiu.
Suponha que representemos soluções deste problema como uma
lista L em que Lk é a cidade a visitar em i-ésimo lugar, a função deve
devolver a cidade que ainda não foi visitada mais próxima do último
elemento da lista.
Uma outra estratégia para a solução deste problema consiste em, a
cada passo, adicionar o arco de menor custo de forma a que não se
formem ciclos nem nodos com grau maior que 2. O último arco a ser
incluıdo fecha o ciclo.

63
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta Unidade temática falamos das estruturas de dados Pilhas, Filas


e Gráfos introduzidas na unidade anterior, mas de uma forma mais
pormenorizada e apresentamos igualmente algumas operações
necessárias.

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press.

UNIDADE Temática 2.3. Árvores e Tabelas de Hash.

Árvores
Pode-se definir uma árvore como um grafo conexo e não cíclico, com
um nó denominado “raiz”, em um nível zero, de onde partem os arcos
(caminhos) para outros nós, denominados “folhas”. Cada folha pode
ter os seus descendentes, sendo que os nós do nível imediatamente
abaixo são denominados “filhos” e os de nível imediatamente acima
são denominados “pais”.

64
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Exemplo de uma árvore.


De particular interesse para estrutura de dados, são as árvores
binárias, em que cada nó tem, no máximo, dois filhos no nível
seguinte. O nó esquerdo inferior (NEI) e o nó direito inferior (NDI) são
denominados “filho esquerdo” e “filho direito”, respectivamente.

As árvores binárias podem ser completas, quando todos os nós do


nível d − 1 de uma árvore binária com d níveis tiverem filhos
esquerdos e direitos, ou quase completa quando não existirem nós
com apenas um dos filhos.

Figura: Exemplo de árvores completa e quase completa.


Existem ainda árvores estritamente binárias, que são árvores cujos
nós, quando não-terminais (folhas), têm ambos os filhos.

Figura: Exemplo de árvores (a) binária, (b) e (c) estritamente binárias.


Uma árvore binária com m nós no nível d, terá, no nível d +1, no
máximo 2m nós, ou seja, o dobro de nós do nível anterior. Assim, o

65
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

máximo número de nós de um nível d em uma árvore binária será de


2d e o total (T) de nós de uma árvore binária pode ser expresso por:
T = X)k = 0d2k, onde d é o número de níveis.
Percurso
Existem 3 maneiras diferentes de se percorrer uma árvore binária.
Estes percursos são fundamentais para que se possa utilizar a
estrutura de árvores na computação de dados. Assim, é necessário
que se estabeleça algoritmos de percurso para escrita e recuperação
de elementos em posições representadas pelos nós de uma árvore.
Para isso, são usados 3 algoritmos:
• Percurso em Pré-ordem;
• Percurso em Ordem Simétrica; e
• Percurso em Pós-ordem.
Esta nomenclatura se refere à ordem em que a raiz da árvore e das
sub-árvores são percorridas.
O percurso em pré-ordem começa pela raiz da árvore, descendo
primeiro pelas raízes das subárvores mais à esquerda e depois as da
direita. A figura representa uma árvore binária e o percurso em pré-
ordem.
O percurso em Pré-ordem visita primeiro a raiz a e depois vai para a
raiz da sub-árvore à esquerda (b), seguindo sempre à esquerda para
o nó d. Como d não é raiz de sub-árvore, visita a próxima raiz à direita
(e), seguindo sempre nesta ordem. Resultando em:
a→b→d→e→h→i→c→f→g→j→k
O percurso em Ordem simétrica visita a raiz de cada subárvore à
esquerda, antes da direita, separando os nós e sub-árvores de forma
simétrica em relação às suas raízes.
Assim, o percurso para a árvore começa em d passando por b e depois
a sub-arvore com raiz em e, e assim por diante, resultando em:

66
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Exemplo do percurso, em pré-ordem, de uma árvore binária.

Figura: Exemplo do percurso, em ordem simétrica, de uma árvore


binária.
d→b→h→e→i→a→f→c→k→j→g

Finalmente, o percurso em Pós-ordem visita a subárvore à esquerda


das folhas para a raiz, deixando a raiz da árvore por último resultando
no percurso:
d→h→i→e→b→f→k→j→g→c→a
Um exemplo
As árvores podem ser utilizadas para representar operações
algébricas. Por exemplo, a expressão (3+x)−(5/2) pode ser
representada por uma árvore binária.

67
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Exemplo do percurso, em pós-ordem, de uma árvore binária.

Figura: Exemplo de representação da equação algébrica (3 + x) − (5/2)


por uma árvore binária.
E evidente que a notação infixa deriva do percurso de ordem
simétrica da árvore. No caso do percurso por pré-ordem, o resultado
seria a notação prefixa (notação polonesa) da expressão (ex.
−+3x/52); e o percurso em pós-ordem, resultaria na notação posfixa
(polonesa reversa) da expressão (ex. 3x+52/−).
Como as expressões polonesas podem representar expressões de
forma mais eficiente (pois dispensa o uso de parênteses), os
compiladores mudam a notação infixa dos programas para a notação
polonesa reversa.
Árvore Geradora Mínima
Seja G = [V,N] um grafo conexo não direccionado e com pesos em
seus arcos, onde V representa o conjunto de vértices, que possuem
um peso positivo, e N representa o conjunto de nós, existe um
subconjunto T de tal que:
Árvore geradora mínima
T∈N
e T conecta todos os vértices de V , tal que a soma de seus pesos seja
mínimo. O grafo G′ = [V,T] é denominado Árvore Geradora Mínima
(AGM) de G.

68
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

O conceito de AGM é utilizado em uma série de tipos de redes, tais


como rotas aéreas, metros, redes de comunicação etc.. Uma AGM
representa, portanto, o menor custo de uma conexão de vários
pontos.
Basicamente, existem dois algoritmos para a implementação de uma
AGM: o algoritmo de Kruskal e o algoritmo de Prim.
Algoritmo de Kruskal
Inventado em 1956, o algoritmo de Kruskal determina a AGM de um
grafo da seguinte maneira:
1. Cria um conjunto vazio T;
2. Cria um conjunto de caminhos C que contém, cada um dos V
vértices;
3. Examina os nós N em ordem crescente de peso;
4. Se um nó tem liga dois componentes em C adiciona a T e os
adiciona a C. Caso contrário rejeita;
5. Repete os dois passos anteriores até que C contenha apenas
um componente.
Algoritmo de Prim
O algoritmo de Prim apareceu em 1957, apesar de já ter sido
proposto e em 1930 por Jarnik (o que Prim desconhecia), ficou
conhecido como algoritmo de Prim e ´e implementado da seguinte
maneira:
1. Cria um conjunto vazio de arcos T;
2. Cria um conjunto vazio de nós C;
3. Selecciona um nó arbitrário V e acrescenta a C;
4. Escolhe o arco a(m,n) de menor peso, tal que m esteja em C e
n não;
5. Acrescenta n a C e a T;
6. Repete os dois passos anteriores até que C seja igual a N, ou
seja, contém todos os nós.

69
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Tabelas de Hash
1. Tabelas de Espalhamento
Poderíamos simplesmente criar uma implementação desta estrutura
que internamente encapsule uma LinkedList ou ArrayList como já
fizemos anteriormente no caso da Fila e da Pilha.
Essa implementação é muito ineficiente computacionalmente: a cada
inserção de palavra teremos que buscar dentro da Lista pela queestá
sendo adicionada, para evitar vocábulos repetidos. Também teremos
de buscar dentro da Lista quando formos verificar se determinada
palavra se encontra naquele vocabulário.
O problema de buscar em uma Lista é que fatalmente temos que
percorrer ela por inteira e isso pode demorar muito: o consumo de
tempo é linear em relação ao número de elementos que ela possui.
O espaço de busca pode ser muito grande, a Lista pode ter milhões
de elementos. Imagine uma Lista com as digitais de todos os
brasileiros: são muitas digitais!
Em vez de buscar em todos os elementos do grupo, seria mais
interessante conseguir restringir o espaço de busca, eliminando o
maior número possível de elementos sem precisar “olhar” para eles.
Diferentemente das Listas, Pilhas e Filas, os Conjuntos não precisam
manter os elementos em sequência.
Então tentaremos uma abordagem bem diferente aqui. Vamos
armazenar os elementos do Conjunto espalhados! Isso mesmo,
espalhados, mas não aleatoriamente e sim com uma certa lógica que
facilitará buscá-los.
A idéia é separar os elementos em categorias de acordo com certas
características chaves do próprio elemento. Desta forma, para buscar
um elemento, basta verificar qual é a categoria dele e assim eliminar
todos os outros que estão nas outras categorias. Essa idéia é
fantástica e todo mundo já utilizou algo parecido no dia-a-dia. Um
exemplo clássico em que essa técnica aparece é a agenda de
telefones.
Nas agendas de telefones, os contatos são separados por categorias,
normalmente, o que define a categoria do contato é a primeira letra
do nome dele. Há uma página para cada letra do alfabeto. Desta
forma, quando é preciso buscar um contato, vamos direto para a

70
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

página referente a primeira letra do nome dele e assim eliminamos


todos os contatos das outras páginas.
A técnica que estamos falando aqui é a técnica de Espalhamento. Ela
consiste basicamente de duas partes: a Função de Espalhamento
(“Função de Hash”) e a Tabela de Espalhamento (“Tabela de Hash”).
A Função de Espalhamento deve descobrir qual é a categoria de um
determinado elemento. Para isso, ela deve analisar as características
chaves do próprio elemento. Por exemplo, na agenda de telefone, a
Função deveria ver qual é a primeira letra do nome do contato e
devolver o número da página referente àquela letra.
A Tabela de Espalhamento deve armazenar as categorias e cada
categoria deve ter um índice. Este índice, gerado com a Função de
Espalhamento, é usado para recuperar a categoria rapidamente.
A Função deve ser determinística, ou seja, toda vez que aplicada a um
mesmo elemento ela deve gerar o mesmo índice, caso contrário
procuraríamos um nome na página errada da agenda.

Figura: Técnica de espelhamento.


Idealmente, a Função deveria gerar índices diferentes para
elementos diferentes. Mas, na prática, ela pode, eventualmente,
gerar o mesmo índice para elementos distintos. Quando isto ocorre,
dizemos que houve uma colisão. No exemplo da agenda de contatos,
uma colisão acontece quando o nome de dois contactos distintos
inicia com mesma letra.

71
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Para resolver o problema da colisão, muitas vezes, a Tabela é


combinada com outra estrutura de dados. Isso ocorre da seguinte
forma: cada posição da Tabela pode armazenar uma Lista, uma
Árvore ou outra estrutura de dados em vez de apenas um elemento.
Desta forma conseguimos armazenar mais de um elemento na
mesma posição da Tabela.
Cuidados devem ser tomados para não permitir a repetição de
elementos nas estruturas que forem combinadas com a Tabela.
Vamos criar uma classe para implementar um Conjunto de palavras
para uma língua utilizando a técnica de Espalhamento.

A Tabela de Espalhamento pode ser implementada através de uma


Lista de Strings. Neste caso, cada posição da Tabela poderá guardar
somente uma palavra da língua. No mundo ideal, isto seria ótimo.
Mas, na prática, haverá colisões causadas pela Função de
Espalhamento. Devemos combinar a Tabela com outra estrutura de
dados para contornar as colisões.
Para combinar a Tabela com Listas, poderíamos defnir um atributo
do tipo Lista de Listas de Strings na classe ConjuntoEspalhamento.
Seria interessante que a Lista principal, aquela que armazena Listas,
fosse um Vetor pois a princípio ela não sofrerá adição nem remoção
de elementos. As Listas secundárias, aquelas armazenadas na Lista
principal, guardarão as palavras e elas sim sofrerão adição e remoção

72
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

de elementos então seria interessante que essas fossem Listas


Ligadas.
Lembrando que as classes do Java que implementam Vetor e Lista
Ligada são ArrayList e LinkedList res-pectivamente.

Essa declaração java pode parecer complicada, mas você pode


imaginar que aí criamos algo similar a uma matriz bidimensional, só
que como são Collections do java, temos grandes vantagens e
facilidades através de seus métodos.
Precisamos definir quantas posições a Tabela terá, ou seja, quantas
Listas secundárias devemos ter, e inicializar cada uma delas. Isso
pode ser feito no construtor da nossa classe. Inicialmente, teremos
26 posições na Tabela, uma para cada letra do alfabeto. Aqui vamos
separar as palavras de acordo com a primeira letra delas: essa será
nossa Função de Espalhamento. Assim como nas agendas de
contatos de antigamente.

Definimos o tipo do atributo tabela como ArrayList de LinkedList.


Desta forma, estamos “a amarrar” nossa implementação a tipos
específicos de Listas. Se depois quisermos trocar os tipos das Listas
teremos problemas. Podemos declarar e inicializar o atributo de
forma mais genérica e elegante, a seguir:

73
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

2. Função de Espalhamento
A Função deve observar a primeira letra das palavras e calcular o
índice correto na Tabela. Por exemplo, palavras começadas com “a”
devem ir para uma posição, palavras começadas com “b” devem ir
para outra, e assim por diante até a letra “z”.
Vamos fazer um método para implementar a Função de
Espalhamento. Estemétododeve receber uma String (palavra) e
devolver um int (índice associado a palavra).

Observe que foram utilizados os métodos toLowerCase() e


chatAt(int) da classe String. O primeiro de-volve a palavra em letras
minúsculas. O segundo devolve o caractere na posição passada como
parâmetro.
Além disso, foi feito uma operação de Resto da Divisão. Isso parece
estranho, mas faz todo o sentido visto que cada caractere tem um
valor inteiro positivo. Em vez de pegar o resto da divisão, poderíamos
simplesmente subtrair o valor 65 desse caractere, que é o caractere
‘A’. Mas o que aconteceria se o primeiro caractere da String fosse um
número ou um caractere especial? Esta operação de resto ajusta o
resultado da função de hash para não sair do intervalo fechado de 0
até 25.
Operações necessárias
Na sequência, vamos implementar as operações que um Conjunto de
palavras deve ter.
1. Adicionar uma palavra
Para adicionar uma palavra no Conjunto, devemos aplicar a Função
de Espalhamento para descobrir em qual posição da Tabela devemos
adicionar. Depois, recuperamos a Lista que está nesta posição para
guardar a palavra.

74
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Este método ficou simples, mas contém um erro. O requisito


fundamental de um Conjunto é não ter elementos repetidos. Como
as Listas permitem elementos repetidos se adicionarmos duas vezes
a mesma palavra ela será inserida duas vezes.
Podemos evitar a repetição de palavras fazendo uma pequena
verificação antes de adicionar uma palavra.

Utilizamos o método contem(String) para saber se o Conjunto já


contém a palavra. Se contém o adiciona(String) não faz nada.
2. Remover uma palavra
Analogamente ao adiciona(String), o método remove(String) deve
achar a posição da Tabela onde está a Lista na qual a palavra a ser
removida estaria. Depois, basta remover a palavra da Lista. Antes de
tentar remover poderíamos verificar se a palavra está no Conjunto.
Nas Listas da API do Java, existe uma sobrecarga do método de
remover que recebe o próprio elemento, além do qual recebe um
índice. O código a seguir auxilia no método:

3. Verificar se uma palavra está ou não no Conjunto


Esta operação é simples, basta achar o índice da Tabela aplicando a
Função de Espalhamento da palavra desejada e verificar se ela está
na Lista correspondente.

75
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Aqui está o grande truque para deixar nosso Conjuntomais rápido


que uma simples lista: buscamos apenas nos elementos que se
encontram naquela “página da agenda”. Se o elemento não estiver
lá, com certeza ele não se encontra em nenhuma outra página da
agenda. O nosso espalhamento tem uma certa organização que
facilita as buscas!
4. Recuperar todas as palavras do Conjunto
As palavras estão armazenadas na Tabela. Então, para recuperar
todas as palavras, precisamos percorrer todas as posições da Tabela.
Em cada posição, há uma Lista, pegaremos todos os elementos de
cada Lista e armazenaremos em uma única Lista e a devolveremos.

Este método cria uma Lista do tipo ArrayList. Porém, observe que a
referência é do tipo List. Isso é possível por causa do Polimorsmo
(capacidade de referenciar de várias maneiras um mesmo objeto).
Todo objecto do tipo ArrayList também é do tipo List.
Todas as Listas do Java disponibilizam uma operação que permite
adicionar diversos elementos de uma vez só. Esta funcionalidade é
implementada pelo método addAll(Collection). Este método foi
utilizado dentro do for para inserir na Lista de todas as palavras do
Conjunto todas as palavras da Lista da posição i da Tabela.
5. Informar o tamanho do Conjunto de palavras
Para esta operação, temos duas alternativas ou em cada vez que a
operação for executada nós percorremos todas as Listas contanto os
elementos ou fazemos de uma forma mais eficiente que é guardar
em um atributo a quantidade de palavras presentes no Conjunto.

76
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Este atributo deve ser incrementado toda vez que uma palavra for
adicionada e decrementada toda vez que uma palavra for removida.

77
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta Unidade temática falamos das árvores e tabelas de hash.


Relacionamos uma árvore ao gráfo ao defini-la como um grafo
conexo e não cíclico, com um nó denominado “raiz”, em um nível
zero, de onde partem os arcos para outros nós, denominados
“folhas”. No que tange às tabelas de hash apresentamos as principais
diferenças entre os Conjuntos das Listas, Pilhas e Filas, vistas nas
unidades anteriores.

Exercícios de AUTO-AVALIAÇÃO

Perguntas

1. Implemente a classe Peca no pacote mz.ac.isced para poder criar


objetos.
2. Implemente a classe Pilha para peças vista nesta unidade.
Coloque no pacote mz.ac.isced.pilhas.
3. Implemente a classe PilhaGenerica para objetos (genérica) vista
nesta unidade. Coloque a classe no pacote mz.ac.isced.pilhas.
4. Implemente a classe Fila para alunos vista neste capítulo.
Coloque a classe no pacote mz.ac.isced.filas.
5. Implemente a classe FilaParametrizada utilizando o recurso do
Generics. Coloque a classe no pacote mz.ac.isced.filas.
6. Crie a classe ConjuntoEspalhamento para implementar Conjunto
utilizando a técnica de Espalhamento. Faça esta classe no pacote
mz.ac.isced.conjuntos. Coloque o atributo que implementa a
tabela e o construtor que inicializa cada Lista da Tabela.
7. Faça o método que calcula qual é o índice da Tabela onde uma
palavra deve ser armazenada. Este método deve classificar as
palavras de acordo com a primeira letra.
8. Vamos implementar o método de adicionar palavras no Conjunto
assim como foi discutido neste capítulo.
9. Para visualizar melhor o que está acontecendo como o Conjunto,
vamos implementar agora o método que recupera todas as
palavras da mesma forma que fazemos neste capítulo.

78
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Respostas:

1. R%

2. R%

79
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

3. R%

4. R%

80
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

5. R%

Obs: depois de fazer alguns testes no código do exercício 3 acima


perceberá que a classe PilhaGenerica contém um erro de compilação.
Quando removemos um elemento da PilhaGenerica recebemos uma
referência do tipo Object e não do tipo Peca.

6. R%

7. R%

81
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

8. R%

Obs: Não esqueça de acrescentar o atributo tamanho para


contabilizar o total de palavras. private int tamanho = 0;

9. R%

82
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press.

83
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

TEMA – III: EXERCÍCIOS E RESOLUÇÃO DE PROBLEMAS REAIS.

UNIDADE Temática 3.1. Introdução de processos para resolução de


problemas reais.
UNIDADE Temática 3.2. Problema 1: “Pegar e Plantar”.
UNIDADE Temática 3.3. Problema 2: “Como Substituir a Rede por uma
Flor”.

• Introduzir os processos básicos usados na resolução de


problemas reais.
• Apresentar as etapas para o desenvolvimento de um
Objectivos algoritmo.
específicos • Mostrar a resolução de exercícios específicos, com base
nas ferramentas e processos estudados.

UNIDADE Temática 3.1. Introdução de processos para resolução de problemas


reais.

Nesta unidade iremos aprender alguns processos bem simples para


desenvolver uma solução para um problema real. Nem tudo o que
veremos nesta unidade é exclusivamente aplicado a um computador
para resolver o problema. Esses processos podem ser usados para
resolver uma ampla variedade de problemas, incluindo aqueles que
não têm nada a ver com computadores.
Problemas, soluções e ferramentas
Vamos supor que tenho um problema! Preciso agradecer à tia Elisa
pelo presente de aniversário que ela me enviou. Eu poderia
simplesmente enviar uma nota de agradecimento pelo correio.
Poderia também ligar para ela por telefone ou até enviar-lhe uma
mensagem de texto ou email. Alternativamente poderia me dirigir
até a casa dela e agradecê-la pessoalmente.
De fato, há muitas maneiras de agradecê-la, mas esse não é o ponto.
A questão é que preciso decidir como quero resolver o problema e
usar a ferramenta apropriada para implementar (executar) o meu
plano. O serviço postal (correios), o telefone, a internet e meu carro
são ferramentas que eu posso usar, mas nenhuma delas realmente
resolve meu problema. De maneira semelhante, um computador não

84
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

resolve problemas, é apenas uma ferramenta que eu posso usar para


implementar meu plano para resolver o problema.
Sabendo que a tia Elisa aprecia coisas criativas e incomuns, decidi
contratar um mensageiro cantor para agradecer. Neste contexto, o
mensageiro é uma ferramenta, mas que precisa de instruções
minhas. Eu tenho que dizer ao mensageiro onde a tia Elisa mora, a
que horas eu gostaria que a mensagem fosse entregue e quais letras
eu queria cantar. Um programa de computador é semelhante às
minhas instruções para o mensageiro.
A história da tia Elisa usa um contexto familiar para preparar o
terreno para um ponto de vista útil sobre computadores e programas
de computador. A lista a seguir resume os principais aspectos desse
ponto de vista:
• Um computador é uma ferramenta que pode ser usada para
implementar um plano para resolver um problema.
• Um programa de computador é um conjunto de instruções
para um computador. Estas instruções descrevem as etapas
que o computador deve seguir para implementar um plano.
• Um algoritmo é um plano para resolver um problema.
• Uma pessoa deve projetar um algoritmo. Uma pessoa deve
traduzir um algoritmo em um programa de computador.
Este ponto de vista prepara o terreno para um processo que
usaremos para desenvolver as soluções para os problemas das
unidades a seguir. O processo básico é importante porque pode ser
usado para resolver uma grande variedade de problemas, incluindo
aqueles em que a solução será escrita em alguma outra linguagem de
programação.
Processo de desenvolvimento de algoritmo
Toda solução de problema começa com um plano.
Esse plano é chamado de algoritmo.
Um algoritmo é um plano para resolver um problema.
Existem muitas maneiras de escrever um algoritmo, como vimos na
unidade 1.1 deste manual. Algumas são muito informais, outras são
bastante formais e matemáticas, e outras até são bastante gráficas.
Por exemplo: As instruções para conectar um aparelho de DVD a uma

85
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

televisão são um algoritmo. Uma fórmula matemática como πR2 é


um caso especial de um algoritmo.
A forma não é particularmente importante, desde que seja uma boa
maneira de descrever e verificar a lógica do plano. O
desenvolvimento de um algoritmo (um plano) é um passo
fundamental na solução de um problema, uma vez que temos um
algoritmo, podemos traduzi-lo em um programa de computador em
alguma linguagem de programação.
Aqui, o nosso processo de desenvolvimento de algoritmo consiste em
cinco etapas principais.
• Etapa 1: Obtenha uma descrição do problema.
• Etapa 2: Analise o problema.
• Etapa 3: Desenvolva um algoritmo de alto nível.
• Etapa 4: Refine o algoritmo adicionando mais detalhes.
• Etapa 5: Revise o algoritmo.
Etapa 1: Obtenha uma descrição do problema.
Este passo é muito mais difícil do que parece. Na discussão a seguir,
a palavra cliente refere-se a alguém que deseja encontrar uma
solução para um problema, e a palavra desenvolvedor refere-se a
alguém que encontra uma maneira de resolver o problema. O
desenvolvedor deve criar um algoritmo que resolva o problema do
cliente.
O cliente é responsável por criar uma descrição do problema, mas
essa é frequentemente a parte mais fraca do processo. É bastante
comum que uma descrição do problema sofra de um ou mais dos
seguintes tipos de defeitos:
1. A descrição se baseia em suposições não declaradas,
2. A descrição é ambígua,
3. A descrição está incompleta ou
4. A descrição tem contradições internas. Esses defeitos
raramente são devidos a descuido pelo cliente. Em vez disso,
eles se devem ao fato de que as línguas naturais (português,
inglês, francês, coreano, etc.) são bastante imprecisas. Parte
da responsabilidade do desenvolvedor é identificar defeitos

86
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

na descrição de um problema e trabalhar com o cliente para


corrigir esses defeitos.
Etapa 2: Analise o problema.
O objetivo desta etapa é determinar os pontos, inicial e final para
resolver o problema. Esse processo é análogo a um matemático que
determina o que é dado e o que deve ser comprovado. Uma boa
descrição do problema facilita a execução dessa etapa.
Ao determinar o ponto de partida, devemos começar buscando
respostas para as seguintes perguntas:
• Quais dados estão disponíveis?
• Onde estão esses dados?
• Quais fórmulas dizem respeito ao problema?
• Quais são as regras para trabalhar com os dados?
• Quais relações existem entre os valores de dados?
Ao determinar o ponto final, precisamos descrever as características
de uma solução. Em outras palavras, como saberemos quando
terminarmos? Fazer as seguintes perguntas frequentemente ajuda a
determinar o ponto final.
• Que novos fatos teremos?
• Quais itens terão mudado?
• Quais alterações foram feitas nesses itens?
• Que coisas não existirão mais?
Etapa 3: Desenvolva um algoritmo de alto nível.
Um algoritmo é um plano para resolver um problema, mas os planos
vêm em vários níveis de detalhe. Geralmente, é melhor começar com
um algoritmo de alto nível que inclua a maior parte de uma solução,
mas deixe os detalhes até mais tarde. Podemos usar um exemplo
cotidiano para demonstrar um algoritmo de alto nível.
Problema: Eu preciso enviar um cartão de aniversário para o meu
irmão, João.
Análise: não tenho cartão. Eu prefiro comprar um cartão em vez de
fazer um eu mesmo.

87
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Algoritmo de alto nível:


i. Vá a uma loja de venda de cartões
ii. Selecione um cartão
iii. Compre um cartão
iv. Envie o cartão
Esse algoritmo é satisfatório para uso diário, mas falta detalhes que
precisariam ser adicionados caso um computador executasse a
solução. Esses detalhes incluem respostas a perguntas como as
seguintes.
• “Qual loja eu vou visitar?”
• “Como eu vou chegar lá: andar, dirigir, andar de bicicleta,
pegar o autocarro público?”
• “Que tipo de cartão o João gosta: humorístico, sentimental?”
Esses tipos de detalhes são considerados na próxima etapa do nosso
processo.
Etapa 4: Refine o algoritmo adicionando mais detalhes
Um algoritmo de alto nível mostra os principais passos que precisam
ser seguidos para resolver um problema. Agora precisamos adicionar
detalhes a essas etapas, mas quanto detalhe devemos adicionar?
Infelizmente, a resposta a esta pergunta depende da situação. Temos
que considerar quem (ou o quê) vai implementar o algoritmo e
quanto essa pessoa (ou coisa) já sabe como fazer.
Se alguém vai comprar o cartão de aniversário para o João em meu
nome, minhas instruções precisam ser adaptadas para saber se essa
pessoa está ou não familiarizada com as lojas da comunidade e como
o comprador conheceu o gosto do meu irmão nos cartões.
Quando nosso objetivo é desenvolver algoritmos que levem a
programas de computador, precisamos considerar as capacidades do
computador e fornecer detalhes suficientes para que a outra pessoa
possa usar o nosso algoritmo para escrever um programa de
computador que siga as etapas do nosso algoritmo. Tal como
acontece com o problema do cartão de aniversário, precisamos
ajustar o nível de detalhe para corresponder à capacidade do
programador. Quando em dúvida, ou quando você está aprendendo,
é melhor ter muitos detalhes do que ter muito pouco.

88
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

A maioria dos nossos exemplos passará de um algoritmo de alto nível


para um algoritmo detalhado em uma única etapa, mas isso nem
sempre é razoável. Para problemas maiores e mais complexos, é
comum passar por esse processo várias vezes, desenvolvendo
algoritmos de nível intermediário à medida que avançamos. Cada
vez, adicionamos mais detalhes ao algoritmo anterior, parando
quando não vemos nenhum benefício para um maior refinamento.
Essa técnica de trabalhar gradualmente de um algoritmo de alto nível
para um algoritmo detalhado é frequentemente chamada de
refinamento gradual.
O refinamento passo a passo é um processo para desenvolver um
algoritmo detalhado adicionando gradualmente detalhes a um
algoritmo de alto nível.
Etapa 5: Revise o Algoritmo.
O passo final é revisar o algoritmo. O que você está procurando?
Primeiro, precisamos trabalhar com o algoritmo passo a passo para
determinar se ele resolverá ou não o problema original. Quando
estamos satisfeitos com o fato de o algoritmo fornecer uma solução
para o problema, começamos a procurar outras coisas. As perguntas
a seguir são típicas daquelas que devem ser feitas sempre que
revisamos um algoritmo. Fazer essas perguntas e buscar suas
respostas é uma boa maneira de desenvolver habilidades que podem
ser aplicadas ao próximo problema.
• Esse algoritmo resolve um problema muito específico ou
resolve um problema mais geral?
• Se resolve um problema muito específico, deveria ser
generalizado?
Por exemplo, um algoritmo que calcula a área de um círculo com raio
de 5,2 metros (fórmula π * 5,22) resolve um problema muito
específico, mas um algoritmo que calcula a área de qualquer círculo
(fórmula 𝐴 = 𝜋𝑟2) resolve um problema mais geral.
• Este algoritmo pode ser simplificado?
Uma fórmula para calcular o perímetro de um retângulo é:
Comprimento + Largura + Comprimento + Largura
Uma fórmula mais simples seria:
2,0 * (Comprimento + Largura)

89
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• Esta solução é semelhante à solução para outro problema?


• Como elas são parecidas?
• O que difere nelas?
Por exemplo, considere as duas fórmulas a seguir:
Área Do Retângulo = Comprimento * Largura
Área Do Triângulo = 0,5 * Base * Altura
Semelhanças: Cada um calcula uma área. Cada um multiplica duas
medições.
Diferenças: diferentes medidas são usadas. A fórmula do triângulo
contém 0,5.
Hipótese: Talvez todas as fórmulas da área envolvam a multiplicação
de duas medições.

Sumário

Nesta unidade temática introduzimos alguns processos simples


usados para resolução de problemas reais. Neste contexto
aprendemos que o uso de algoritmos não se limita a resolver
problemas apenas relacionados aos computadores, pelo contrário,
esses processos podem ser usados para resolver uma ampla
variedade de problemas do nosso quotidiano.

90
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press;
• Edwards, S., Dorn, B., & Sanders, D. (2012). Problem Solving and
Algorithms. Obtido de Sofia - Objects First:
http://sofia.cs.vt.edu/cs1114-ebooklet/chapter4.htmll.

UNIDADE Temática 3.2. Problema 1: “Pegar e Plantar”.

Esta unidade contém um exemplo estendido que demonstra o


processo de desenvolvimento de um algoritmo. Daqui em diante
trataremos o canguru do exemplo por “Jeroo”.

Para completar o algoritmo, precisamos saber que todo Jeroo (todo


canguru) pode pular para frente, virar para a esquerda e para a
direita, escolher uma flor a partir de sua localização atual e plantar
uma flor em sua localização atual.

91
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Etapa 1: Declaração do problema.

Um Jeroo começa na posição (0, 0) voltado para o leste sem flores na


bolsa. Há uma flor no local (3, 0).

Escreva um programa que direcione o Jeroo para pegar a flor e


plantá-la no local (3, 2). Depois de plantar a flor, o Jeroo deve pular
um espaço para o leste e parar. Não há outras redes, flores ou jeroos
(cangurus) na ilha.

Figura: Posição inicial (início)

Figura: Situação pretendida (fim)


Etapa 2: Análise do problema
• A flor está exatamente três espaços à frente do jeroo.
• A flor deve ser plantada exatamente dois espaços ao sul de
sua localização atual.

92
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• O Jeroo deve terminar de frente para o leste a leste de um


espaço da flor plantada.
• Não há redes para se preocupar.
Etapa 3: Algoritmo de alto nível
O Jeroo deve fazer o seguinte:
• Pegar a flor
• Colocar a flor
• Saltar Leste
Passo 4: Algoritmo detalhado
O Jeroo deve fazer o seguinte:
• Pegar a flor
• Pular 3 vezes
• Pegar a flor
• Colocar a flor
• Virar à direita. Saltar 2 vezes
• Plantar a flor
• Saltar Leste
• Virar à esquerda. Saltar uma vez
Etapa 5: Revise o algoritmo
O algoritmo de alto nível particionou o problema em três
subproblemas fáceis. Isso parece uma boa técnica. Este algoritmo
resolve um problema muito específico porque o Jeroo e a flor estão
em locais muito específicos. Este algoritmo é na verdade uma solução
para um problema um pouco mais geral no qual o Jeroo começa em
qualquer lugar, e a flor tem 3 espaços diretamente à frente do Jeroo.

93
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta unidade temática apresentamos o primeiro problema com o


intuito de resolvê-lo utilizando os processos estudados na unidade
anterior. A solução deste problema consistia em direcionar o canguru
Jeroo a pegar uma flor e plantá-la numa posição específica.

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New Delhi:
Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java.
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press;
• Edwards, S., Dorn, B., & Sanders, D. (2012). Problem Solving and
Algorithms. Obtido de Sofia - Objects First:
http://sofia.cs.vt.edu/cs1114-ebooklet/chapter4.htmll.

94
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

UNIDADE Temática 3.3. Problema 2: “Como Substituir a Rede por uma Flor”.

Esta unidade contém um segundo exemplo que demonstra o


processo de desenvolvimento do algoritmo.

Etapa 1: Declaração de problema

Existem dois Jeroos. Um Jeroo começa em (0, 0) voltado para o norte


com uma flor em sua bolsa. O segundo começa em (0, 2) voltado para
o leste com uma flor em sua bolsa. Existe uma rede no local (3, 2).

Escreva um programa que direcione o primeiro Jeroo a dar sua flor


ao segundo. Depois de receber a flor, o segundo Jeroo deve desativar
a rede e plantar uma flor em seu lugar. Depois de plantar a flor, o
Jeroo deve virar e enfrentar o sul. Não há outras redes, flores ou
jeroos na ilha.

Figura: Posição inicial (início)

95
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Figura: Situação pretendida (fim)


Etapa 2: Análise do problema
• O Jeroo_2 está exatamente dois espaços atrás do Jeroo_1.
• A única rede está exatamente três espaços à frente do
Jeroo_2.
• Cada Jeroo tem exatamente uma flor.
• Jeroo_2 terá duas flores depois de receber uma do Jeroo_1.
• Uma flor deve ser usada para desativar a rede.
• A outra flor deve ser plantada no local da rede, ou seja, (3, 2).
• Jeroo_1 terminará em (0, 1) voltado para o sul.
• Jeroo_2 terminará em (3, 2) voltado para o sul.
Cada Jeroo terminará com 0 flores em sua bolsa. Uma flor foi usada
para desativar a rede e a outra foi plantada.
Etapa 3: Algoritmo de alto nível
O Jeroo_1 deve fazer o seguinte:
• Encontrar Jeroo_2 (mas não colidir com ele)
• Dar uma flor para Jeroo_2 (ele estará em frente)
• Depois de receber a flor, Jeroo_2 deve fazer o seguinte:
• Encontrar a rede (mas não pular nela)
• Desativar a rede
• Plante uma flor no local da rede

96
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• Virar Sul
Passo 4: Algoritmo detalhado
Jeroo_1 deve fazer o seguinte:
• Encontrar Jeroo_2
• Virar-se (para a esquerda ou para a direita duas vezes)
• Saltar (para localização (0, 1))
• Dê uma flor para Jeroo_2
• Dar a frente
• Agora Andy deve fazer o seguinte:
• Encontre a rede
• Saltar duas vezes (para a localização (2, 2))
• Desativar a rede
• Sorteio
• Plante uma flor no local da rede
• Saltar (para a localização (3, 2))
• Plante uma flor
• Virar Sul
• Virar à direita
Etapa 5: Revise o algoritmo
O algoritmo de alto nível ajuda a gerenciar os detalhes.
Esse algoritmo resolve um problema muito específico, mas os locais
específicos não são importantes. A única coisa importante é a
localização inicial dos Jeroos em relação um ao outro e a localização
da rede em relação à localização e direção do segundo Jeroo.

97
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta unidade temática apresentamos o segundo problema com o


intuito de resolvê-lo utilizando mesmos os processos estudados na
unidade 3.1. A solução deste problema consistia em direcionar os 2
Jeroos a pegar uma flor e plantá-la numa posição específica da ilha,
desta vez com obstáculos.

Exercícios de AUTO-AVALIAÇÃO

Perguntas

1. Para que tipo de problemas são destinados os processos de


resolução vistos neste tema?
2. De que depende a escolha da ferramenta apropriada para
resolução de um problema?
3. No contexto deste tema defina o que é um algoritmo?
4. Encontre as semelhanças da definição dada no número
anterior com a definição da UNIDADE Temática 1.1.
Introdução a Algoritmos?
5. Em quantas etapas básicas consiste o processo de
desenvolvimento de algoritmos?
6. Mencione-as.
Respostas:

1. R% Rever página 76 parágrafo 1.


2. R% Rever páginas 76, 77.
3. R% Rever páginas 77, 78.
4. R% Rever páginas 9, 10, 77, 78.
5. R% Rever página 78.
6. R% Rever página 77 a 81.

98
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press;
• Edwards, S., Dorn, B., & Sanders, D. (2012). Problem Solving and
Algorithms. Obtido de Sofia - Objects First:
http://sofia.cs.vt.edu/cs1114-ebooklet/chapter4.htmll.

99
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

TEMA – IV: INTERFACE DE PROGRAMAÇÃO DE APLICAÇÕES JAVA.

UNIDADE Temática 2.1. Introdução à API Collections do JAVA.


UNIDADE Temática 2.2. Listas: java.util.List.
UNIDADE Temática 2.3. Ordenação: Collections.sort.
UNIDADE Temática 2.4. Conjunto: java.util.Set.

• Introduzir os recursos do Java API Collections usados


para algoritmos e estruturas de dados.
• Apresentar interfaces e classes da API Collections do Java.
Objectivos • Apresentar as diversas implementações disponíveis nas
específicos interfaces da API.

UNIDADE Temática 2.1. Introdução à API Collections do JAVA.

Na linguagem de programação Java, Coleções (Collections) são


usadas para armazenar grupos de objetos. A API Collections fornece
várias interfaces (incluindo Collection, List, Map e Set) para definir
uma maneira padrão de usar um intervalo de estruturas de dados
concretas. As interfaces e classes da API Collections pertencem ao
pacote java.util.

Figura: Classes e interfaces comumente usadas do Framework Java


Collections.
Características do Collection

As características das coleções incluem:

100
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Ordenação. É possível iterar sobre os elementos de uma coleção


ordenada em uma ordem previsível.

Exclusividade dos elementos. Algumas coleções não permitem


elementos duplicados. Objetos são considerados duplicados se, de
acordo com seus métodos equals(Object), forem iguais.

Armazenamento baseado em Array. Algumas coleções usam um


array internamente para armazenar seus elementos. O array é
redimensionado para acomodar mais elementos. O armazenamento
de array geralmente é rápido para acessar, mas lento para remover
ou inserir elementos.

Armazenamento de lista vinculada (Linked-list). Em Linked-list, cada


elemento é armazenado em outro objeto que possui uma referência
ao elemento anterior e (em uma lista com dupla encadernação)
anterior. Listas vinculadas são eficientes na remoção ou inserção de
elementos, mas mais lentas para acesso.

Armazenamento baseado em hash. O armazenamento baseado em


hash gera chaves de identificação para os elementos que ele
armazena. Em Java, as coleções baseadas em hash usam o método
Object.hashCode() para gerar as chaves de identificação. O
armazenamento baseado em hash pode fornecer acesso e
crescimento razoavelmente eficientes, mas sua eficácia depende do
hashCode() dos elementos que armazena para, tanto quanto
possível, retornar valores diferentes para objetos diferentes. Se uma
coleção baseada em hash armazena objetos de uma classe cujo
hashCode() sempre retorna o mesmo valor, a coleção na verdade
funcionará mais como uma coleção baseada em array, mas com a
sobrecarga adicional de calcular os valores de hash.

Armazenamento baseado em árvore. Uma árvore requer uma


maneira de ordenar os elementos que ela armazena. As árvores são
eficientes para pesquisar.

101
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta unidade temática introduzimos API Collections do JAVA, que


possui muitas interfaces para o uso em algoritmos e estruturas de
dados. Os recursos dessas interfaces serão apresentados nas
unidades a suir.

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New Delhi:
Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press;
• how2examples.com. (s.d.). The Java Collections API. Obtido de
how2examples: http://how2examples.com/java/collections;
• Rocha, F. G. (2013). API Collections em Java: fundamentos e
implementação básica. Obtido de DEVMEDIA:
https://www.devmedia.com.br/api-collections-em-java-
fundamentos-e-implementacao-basica/28445;
• Collins, W. (2011). Data Structures and the Java
Collections Framework - Third Edition. JOHN
WILEY & SONS, INC.

102
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

UNIDADE Temática 2.2. Listas: java.util.List.

As listas são consideradas como primeiro recurso que a API de


Collections traz. Uma lista é uma coleção ordenada. As listas
permitem um controle preciso sobre o posicionamento de elementos
individuais dentro da estrutura de dados. É possível adicionar,
recuperar e remover elementos em posições especificadas. O
comportamento padrão para listas é permitir duplicatas. As
implementações de java.util.List incluem:

• ArrayList - usa armazenamento baseado em array.


• LinkedList - usa o armazenamento de lista vinculada. Também
implementa o Deque para permitir que ele seja usado como
uma fila ou pilha.

Listas permitem elementos duplicados e mantém uma ordenação


específica entre os elementos.

Em outras palavras, temos a garantia de que, quando percorrer a


lista, os elementos serão encontrados em uma ordem pré-
determinada, definida na hora da inserção dos mesmos.

A API de Collections traz a interface java.util.List, que especifica o que


uma classe deve ser capaz de fazer para ser uma lista. Há diversas
implementações disponíveis, cada uma com uma forma diferente de
representar uma lista.

A implementação mais utilizada da interface List é a ArrayList, que


trabalha com um array interno para gerar uma lista. Portanto, ela é
mais rápida na pesquisa do que sua concorrente, a LinkedList, que é
mais rápida na inserção e remoção de itens nas pontas.

A seguir temos o exemplo de uma LinkedList, implementada na classe


ExemploLinkedLista.java:

import java.util.LinkedList;

public class ExemploLinkedLista {

public static void main(String[] args)

103
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

{
LinkedList<String>
listaVinculada = new LinkedList<String>()
;
System.out.println(listaVinculada.s
ize()+" "+ listaVinculada.isEmpty());
listaVinculada.add("a");
listaVinculada.add("b");
listaVinculada.add("c");
listaVinculada.add("d");
listaVinculada.add("e");
listaVinculada.add("f");
System.out.println(listaVinculada);
System.out.println(listaVinculada.s
et(1, "x"));
l.add(2, "a");
System.out.println(listaVinculada);
System.out.println(listaVinculada.p
ollFirst()+ "
"+ listaVinculada.peekFirst());
System.out.println(listaVinculada);
System.out.println(listaVinculada.g
et(4));
listaVinculada.remove("a");
System.out.println(listaVinculada);
System.out.println(listaVinculada.s
ize()+ " "+ listaVinculada.isEmpty());
for (String s : listaVinculada) {
System.out.print(s);
}
}
}
Comando para compilar a classe ExemploLinkedLista.java:

javac ExemploLinkedLista.java
Comando para executar a classe ExemploLinkedLista.java, após
compilação:

java ExemploLinkedLista

104
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

O resultado (saída) da execução:

Sumário

Nesta unidade apresentamos a interface java.util.List, usada para


implementação de Listas em Java.

105
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press;
• how2examples.com. (s.d.). The Java Collections API. Obtido de
how2examples: http://how2examples.com/java/collections;
• Rocha, F. G. (2013). API Collections em Java: fundamentos e
implementação básica. Obtido de DEVMEDIA:
https://www.devmedia.com.br/api-collections-em-java-
fundamentos-e-implementacao-basica/28445;
• Collins, W. (2011). Data Structures and the Java Collections
Framework - Third Edition. JOHN WILEY & SONS, INC.

UNIDADE Temática 2.3. Ordenação: Collections.sort.

Vimos na unidade anterior que as listas são percorridas de maneira


pré-determinada de acordo com a inclusão dos itens. Mas, muitas
vezes, queremos percorrer a nossa lista de maneira ordenada.

A classe Collections traz um método estático sort (ordenar) que


recebe um List como argumento e o ordena por ordem crescente. Por
exemplo:

106
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

List<String> listaFrutas = new ArrayList<>


();

listaFrutas.add("Goiaba");
listaFrutas.add("Abacate");
listaFrutas.add("Papaia");

System.out.println(listaFrutas);
Collections.sort(listaFrutas);
System.out.println(listaFrutas);
Ao testarmos o exemplo acima, observará que, primeiro, a lista é
impressa na ordem de inserção e, depois de invocar o sort, ela é
impressa em ordem alfabética do nome das frutas.
Mas toda lista em Java pode ser de qualquer tipo de objeto, por
exemplo, Estudante. E se quisermos ordenar uma lista de Estudante?
Em que ordem a classe Collections ordenará? Pelo ano de ingresso?
Pelo nome desse estudante ou número de matrícula?
Exemplo de uma simples classe Estudante:
public class Estudante {
private String nome;
private String apelido;
private String numeroMatricula;
private int anoIngresso;
//... getters e setters
}

107
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sempre que falamos em ordenação, precisamos pensar em um


critério de ordenação, uma forma de determinar qual elemento vem
antes de qual. É necessário instruir o sort sobre como comparar os
nossos Estudante a fim de determinar uma ordem na lista. Para isto,
o método sort necessita que todos seus objetos da lista sejam
comparáveis e possuam um método que se compara com outro
Estudante. Como é que o método sort terá a garantia de que a sua
classe possui esse método? Isso será feito, através de uma interface.
Vamos fazer com que os elementos da nossa coleção implementem
a interface java.lang.Comparable, que define o método int
compareTo(Object). Este método deve retornar zero, se o objeto
comparado for igual a este objeto, um número negativo, se este
objeto for menor que o objeto dado, e um número positivo, se este
objeto for maior que o objeto dado.
Para ordenar os Estudantes por anoIngresso, basta implementar o
Comparable:

Com o código anterior, a nossa classe Estudante tornou-se


“comparável”: dados dois objetos da classe, conseguimos dizer se um
objeto é maior, menor ou igual ao outro, segundo algum critério por
nós definido. No nosso caso, a comparação será feita baseando-se no
ano de ingresso do estudante.
Repare que o critério de ordenação é totalmente aberto, definido
pelo programador. Se quisermos ordenar por outro atributo (ou até
por uma combinação de atributos), basta modificar a implementação
do método compareTo na classe.
Quando chamarmos o método sort de Collections, ele saberá como
fazer a ordenação da lista; ele usará o critério que definimos no
método compareTo.

108
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta unidade apresentamos a interface Collections.sort, que


permite a ordenação de elementos de uma lista de acordo com o
critério definido pelo programador.

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New Delhi:
Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press;
• how2examples.com. (s.d.). The Java Collections API. Obtido de
how2examples: http://how2examples.com/java/collections;
• Rocha, F. G. (2013). API Collections em Java: fundamentos e
implementação básica. Obtido de DEVMEDIA:
https://www.devmedia.com.br/api-collections-em-java-
fundamentos-e-implementacao-basica/28445;
• Collins, W. (2011). Data Structures and the Java Collections
Framework - Third Edition. JOHN WILEY & SONS, INC.

109
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

UNIDADE Temática 2.4. Conjunto: java.util.Set

Em java, um conjunto (Set) funciona de forma análoga aos conjuntos


da matemática, ele é uma coleção que não permite elementos
duplicados.

Outra característica fundamental destes é o fato de que a ordem em


que os elementos são armazenados pode não ser a ordem na qual
eles foram inseridos no conjunto. A interface não define como deve
ser este comportamento. Tal ordem varia de implementação para
implementação.

Um conjunto é representado pela interface Set e tem como suas


principais implementações as classes HashSet, LinkedHashSet e
TreeSet.

O código a seguir cria um conjunto e adiciona diversos elementos, e


alguns repetidos:

Aqui, o segundo “Física” não será adicionado e o método add lhe


retornará false.

O uso de um Set pode parecer desvantajoso, já que ele não armazena


a ordem, e não aceita elementos repetidos. Não há métodos que
trabalham com índices, como o get(int) que as listas possuem. A
grande vantagem do Set é que existem implementações, como a
HashSet, que possui uma performance incomparável com as Lists
quando usado para pesquisa (método contains por exemplo).

110
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Ordem de um Set

Seria possível usar uma outra implementação de conjuntos, como um


TreeSet, que insere os elementos de tal forma que, quando forem
percorridos, eles apareçam em uma ordem definida pelo método de
comparação entre seus elementos. Esse método é definido pela
interface java.lang.Comparable. Ou, ainda, pode se passar um
Comparator para seu construtor.
Já o LinkedHashSet mantém a ordem de inserção dos elementos.
Antes do Java 5, não podíamos utilizar generics, e usávamos o Set de
forma que ele trabalhava com Object, havendo necessidade de
castings.
A Interface Set
Considerada uma interface que faz parte do pacote “java.util” e
representa grupos de elementos sem duplicatas, ou seja, são usados
quando o programador não precisar ter nenhum dado duplicado na
coleção. Segue abaixo na Figura a hierarquia da interface Set.

Figura: Hierarquia da interface Set.


Características da interface Set
• Velocidade na pesquisa de dados, sendo mais rápida que um
objeto do tipo List;
• A inserção de dados é mais lenta;
• Permite trabalhar com conjuntos e pode ser implementado
como instâncias das classes HashSet ou TreeSet; Não precisa
especificar a posição para adicionar um elemento;

111
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

• Não aceita valores duplicados. Se caso inserir um registo que


já tenha no Set não será adicionado.
• Podem ser implementados como instâncias das classes
HashSet ou TreeSet.
Para realizar alguns testes, será necessário criar a classe Cliente
destacada a seguir.

112
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

A seguir é mostrado como imprimir dados a partir do objeto Cliente.


Impressão de registos não duplicados do objeto Cliente

Classe HashSet

Classe que faz parte do pacote “java.util” e que é uma


implementação da interface Set onde utiliza uma tabela hash, por
isso do nome da classe.

Características do HashSet

• Não tem ordenação na varredura ou impressão;


• A ordem de saída não é a mesma de entrada;
• Aceitam valores do tipo null;
• Não é sincronizada (thread-safe);
• Velocidade no acesso, leitura e modificação de dados.

113
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Declaração - HashSet

Na classe HashSet para construir objetos é a mesma ideia da interface


Set, precisa informar que tipo de coleção será implementada.

Sintaxe: HashSet<E> set = new Type<E> ();

E - É o objeto declarado, podendo ser classes Wrappers ou tipo de


coleção;

Type - é o tipo de objeto da coleção a ser usado.

Na Listagem 3, está sendo adicionado, comparado e exibido valores


através do HashSet. Nesse caso, para varrer os dados e realizar a
impressão está sendo utilizado o Iterator, sendo a mesma forma de
acesso do “for aprimorado” utilizado no exemplo da interface Set.

Abaixo, apresentamos um exemplo do uso da classe HashSet

114
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Classe TreeSet

Essa classe fornece objetos de coleção de ordenação natural e faz


parte da implementação da interface Set e está localizada dentro do
pacote “java.util”.

Características

• Os elementos inseridos dentro desse tipo de conjunto devem


implementar a interface Comparable;
• A ordenação é por elementos únicos;
• Não suporta objetos nulos, se caso um elemento ser nulo é
lançado a exceção NullPointerException;
Declaração - TreeSet

Nessa classe para construir objetos é a mesma ideia da interface Set,


precisa informar que tipo de coleção será implementada.

Sintaxe: Set<E> set = new TreeSet<E> ();

E - É o objeto declarado, podendo ser classes Wrappers ou tipo de


coleção. Os métodos da interface TreeSet podem ser encontrados no
link oficial.

Ordenação de registos do tipo String

Ordenação de registos com o objeto Cliente

115
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

A interface Set as classes que a implementam ajudam a facilitar


alguns problemas enfrentados pelos programadores em casos de
ordenação e desempenho de listas. Pelo fato, de que muitas vezes é
necessário realizar uma ordenação específica de coleções de dados
de acordo com a necessidade, usar os recursos e opções oferecidas
por esta interface é altamente recomendável.

116
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Sumário

Nesta unidade temática apresentamos o Conjunto: java.util.Set,


como um dos recursos da API Collections do Java para representação
de coleções de dados. Vimos que a interface Set possui uma série de
classes e funções que podem facilitar a vida do programador, quando
houver necessidade de ordenação de conjuntos de dados.

Exercícios de AUTO-AVALIAÇÃO

Perguntas

1. Qual é o primeiro recurso que uma API de Collections traz?


2. No contexo desto Tema IV, defina o que é uma lista?
3. Quais são os métodos mais importantes da interface
java.util.List?
4. Qual é A diferença entre as classes ArrayList e LinkedList?
5. Escrever um programa java que receba dois números e exiba
o resultado da sua soma.
6. Escrever um programa para determinar o consumo médio de
um automóvel sendo fornecida a distância total percorrida
pelo automóvel e o total de combustível gasto.

Respostas:

1. R% Um primeiro recurso que a API de Collections traz são


listas.
2. R% Uma lista é uma coleção que permite elementos
duplicados e mantém uma ordenação específica entre os
elementos.
3. R% Os métodos mais importantes dessa interface são:
• Add: adiciona um objeto na lista;
• Get: recupera um objeto da lista, passando como
parâmetro o índice do objeto;
• Remove: remove o objeto da lista.
4. R% A diferença entre as classes ArrayList e LinkedList está na
performance, pois o ArrayList é mais rápido na recuperação
de dados, enquanto o LinkedList tem melhor performance na
adição e exclusão de dados.
5. R%

117
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

6. R%

118
ISCED CURSO: Gestão de Sistemas de Informação; 2° Ano Disciplina/Módulo: Programação II

Bibliografia

• Edelsbrunner, H., & Gu, Z. (2008). DESIGN AND ANALYSIS OF


ALGORITHMS;
• Andrade, E., & Veiga, A. O. (s.d.). Princípios de Programação.
Universidade Virtual Africana;
• Point, T. (2016). Data Structure and Algorithms. Obtido de
Tutorials Point:
https://www.tutorialspoint.com/data_structures_algorithm;
• Vilanculos, A. M., & Sambo, J. L. (s.d.). DESIGN E ANÁLISE DE
ALGORITMOS. Universidade Virtual Africana;
• Bhasin, H. (2005). ALGORITHMS: Design and Analysis. New
Delhi: Oxford University Press;
• Kleinberg, J., & Tardos, E. (2006). Algorithm Design. Pearson
Education, Inc;
• Caelum. (s.d.). Algoritmos e Estruturas de Dados em Java .
Caelum;
• Johnson, M. J. (2014). A Concise Introduction to Data Structures
using Java. Nova York: CRC Press;
• how2examples.com. (s.d.). The Java Collections API. Obtido de
how2examples: http://how2examples.com/java/collections;
• Rocha, F. G. (2013). API Collections em Java: fundamentos e
implementação básica. Obtido de DEVMEDIA:
https://www.devmedia.com.br/api-collections-em-java-
fundamentos-e-implementacao-basica/28445;
• Collins, W. (2011). Data Structures and the Java Collections
Framework - Third Edition. JOHN WILEY & SONS, INC;
• Palmeira, T. V. (s.d.). Trabalhando com a Interface Set no Java. Obtido
de Linha de código:
http://www.linhadecodigo.com.br/artigo/3669/trabalhando-com-a-
interface-set-no-java.aspx.

119
121

121

Você também pode gostar