Escolar Documentos
Profissional Documentos
Cultura Documentos
Maio 2009
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
ÍNDICE:
1. INTRODUÇÃO....................................................................................................................................... 1
2. CONCEITOS GERAIS .......................................................................................................................... 1
3. ESTRUTURAS DE DADOS DINÂMICAS.......................................................................................... 2
3.1. AS CLASSES ARRAYLIST E LIST ....................................................................................................... 2
3.2. PILHAS ............................................................................................................................................. 6
3.3. QUEUE ........................................................................................................................................... 14
3.4. CLASSE SORTEDLIST ..................................................................................................................... 18
3.5. CLASSE GENÉRICA LINKEDLIST ..................................................................................................... 23
3.6. ÁRVORES (TREES) .......................................................................................................................... 27
3.7. GRAFOS (GRAPH) ........................................................................................................................... 27
4. BIBLIOGRAFIA .................................................................................................................................. 27
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
1. Introdução
O Visual Basic em geral e a versão 2008, em particular, possui um conjunto de
características que visam ajudar tanto o programador principiante como o experiente a
desenvolver aplicações de forma simples, rápida e divertida.
Neste contexto e no âmbito do módulo Estrutura de Dados Dinâmicas, pretende‐se
que, no final da frequência da disciplina, os alunos sejam capazes de:
• Compreender os conceitos fundamentais das Ciências da Computação e aplicá‐los
em exemplos concretos;
• Compreender a importância das estruturas dinâmicas na programação de
computadores;
• Saber identificar estruturas de dados lineares (lista ligada, fila, pilha) e não‐
lineares (árvores, grafos);
• Saber definir e manipular estruturas de dados lineares (lista ligada, fila, pilha) bem
como implementar os principais métodos de manipulação destas estruturas;
• Identificar situações em casos práticos passíveis de utilização dos tipos de
estrutura dinâmica – pilha e fila de espera;
• Compreender e distinguir as operações básicas sobre listas simplesmente ligadas e
duplamente ligadas;
• Codificar os programas em Visual Basic e testar as aplicações resultantes.
Refira‐se que nos exemplos apresentados as aplicações são do tipo consola
considerando‐se ser esta a melhor forma de se aprender uma linguagem de programação,
uma vez que o objectivo principal está nos elementos da linguagem de programação.
2. Conceitos Gerais
O Visual Basic 2008 permite criar três tipos principais de aplicações:
• Console Application – aplicações de consola do tipo linha de comando.
• Classes Library – componentes reutilizáveis, isto é, bibliotecas de funções (ficheiros
com extensão .DLL).
• Windows Forms Application ‐ aplicações para Windows com uma interface
gráfica.
Usamos genericamente ao longo deste documento aplicações do tipo consola dado
que o objectivo está relacionado com elementos de programação não com os aspectos
gráficos das janelas e controlos do Windows. Usaremos no entanto nos últimos
exemplos aplicações gráficas para ilustrar o funcionamento de pilhas e filas.
‐ 1 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
3. Estruturas de Dados Dinâmicas
Por norma, as variaveis são de um só tipo (numérico, texto, booleano, etc) mas por
vezes surge a necessidade de associaar numa variavel tipos de dados distintos. Neste
casos define‐se um tipo de dados composto.
Podemos definir as seguintes propriedades das listas:
• os nós estão ligados linearmente
• existem dois extremos na lista: o início e o fim
• os nós podem ser adicionados em qualquer ponto da lista
• os nós podem ser removidos em qualquer ponto da lista
• a lista pode ser percorrida a partir de qualquer ponto
3.1. As classes ArrayList e List
Um vector (classe Array) é uma estrutura de dados muito comum na programação. É,
frequentemente, uma estrutura de dados adequada à modelação de uma grande parte
de problemas. Contudo, existem várias limitações desta classe, designadamente:
• O programador tem de adicionar código para inserir ou remover elemenntos
que não estejam no fim do vector;
• O programador tem de adicionar código para verificar quando o vector
necessita de ser alterado, redimensionando‐o;
• O redimensionamento de um vector, através de ReDim e ReDim Preserve, não
são particularmente eficientes, principalmente em vectores com alguma
dimensão.
A classe tradicional ArrayList e a classe genérica List representam vectores que se
redimensionam automaticamente quando o espaço alocado for atingido. Como com
qualquer colecção, a propriedade Count indica quantos eleementos estão efectivamente
armazenados na colecção, enquanto que a propriedade Capacity retorna o número de
elementos que a colecção pode armazenar sem ser necessário redimensionar‐se. A
gestão do tamanho destas colecções é feita de forma transparente para o programador.
Por outro lado, estas classes disponibilizam um conjunto de métodos que permitem
realizar operações frequentes como, por exemplo, inserir um elemento numa
determinada posição da colecção ou então remover um elemento com um determinado
índice.
A tabela seguinte apresenta uma selecção dos métodos das classes ArrayList e List.
Apesar de haver diferenças entre estas classes, os métodos constantes na tabela seguinte
são comuns às duas classes.
‐ 2 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Tabela 1 ‐ Métodos definidos nas classes ArrayList e List
Método Descrição
Add Adiciona um objecto ao fim da colecção.
AddRange Adiciona um conjunto de elementos, armazenados num objecto
do tipo ICollection, ao fim da colecção.
BinarySearch Overloaded. Procura, usando um algoritmo de pesquisa binário,
um elemento específico da colecção, ou numa parte da colecção,
ordenada.
Clear Remove todos os elementos da colecção.
Contains Retorna um Boolean que indica se um valor existe na colecção.
CopyTo Overloaded. Copia toda a colecção, ou apenas uma parte, para um
vector unidimensional.
IndexOf Overloaded. Retorna o índice, sendo o índice do primeiro zero, da
primeira ocorrência de um nalor na colecção ou numa parte da
colecção.
Insert Insere um elemento na colecção no índice especificado.
InsertRange Insere um conjunto de elementos, armazenados num objecto do
tipo ICollection, na colecção no índice especificado
LastIndexOf Overloaded. Retorna o indice, sendo o indice do primeiro
elemento zero, da última ocorrência de um valor na colecção ou
numa parte da colecção.
RemoveAt Remove o elemento no índice especificado da colecção .
RemoveRange Remove um conjunto de elementos da colecção.
Reverse Overloaded. Inverte a ordem dos elementos na colecção, ou numa
parte da colecção.
Sort Overloaded. Ordena os elementos da colecção, ou de uma parte
da colecção.
ToArray Overloaded. Copia os elementos da colecção para um vector novo.
A propriedade Item é a propriedade por omissão, o que significa que uma colecção
ArrayList ou List pode ser usada de forma análoga a um vector, indicando, entre
parênteses, o índice do elemento a retornar ou definir. Na tabela seguinte são
apresentadas as propriedades mais comuns das classes ArrayList e List.
‐ 3 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Tabela 2 – Propriedades mais comuns das classes ArrayList e List
Propriedades Descrição
Capacity Retorna ou define o número total de elementos que o objecto
ArrayList pode armazenar sem ser necessário redimensionar ‐se.
Count Retorna o número de elementos efectivamente armazenados na
colecção.
Item Retorna ou define o elemento no índice especificado.
A propriedade Item é a propriedade por omissão, o que significa que uma colecção
ArrayList ou List pode ser usada de forma análoga a um vector, indicando, entre
parênteses, o índice do elemento a retornar ou definir.
O programa seguinte ilustra o funcionamento básico de alguns dos principais métodos
da classe List:.
Exemplo 1 – Exemplo com a classe List
Module Module1
Sub Main()
'Cria uma nova colecção de strings.
Dim compras As New List(Of String)
compras.Add("alface")
compras.Add("cereais")
compras.Add(" laranjas")
'Mostra as propriedades da List.
Console.WriteLine("compras")
Console.WriteLine(" Count: " & compras.Count)
Console.WriteLine(" Capacity: " & compras.Capacity)
Console.Write(" Valores:")
MostraValores(compras)
Console.WriteLine()
'Insere "pepino" na primeira posição.
compras.Insert(0, "pepino")
'Adiciona "chocolate" na última posição.
compras.Add("chocolate")
'Mostra número de elementos e capacidade:
Console.WriteLine("O número de produtos é agora:" &compras.Count)
Console.Write(" Valores:")
MostraValores(compras)
Console.WriteLine("A capacidade actual é: " & compras.Capacity)
If (compras.Contains("chocolate")) Then
compras.Remove(" chocolate")
Console.WriteLine("""chocolate"" foi removido das compras.")
‐ 4 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Console.Write(" Valores:")
MostraValores(compras)
Else
Console.WriteLine("""Chocolate"" não existe nas compras.")
End If
'Remove o 3° elemento compras.
compras.RemoveAt(2)
Console.WriteLine("Removido o elemento na posição 2")
Console.Write(" Valores: ")
MostraValores(compras)
'Qual a posição das "laranjas"
Dim pos As Integer = compras.IndexOf("laranjas")
'Se "laranjas" existe na lista, a posição é <> -1
If pos <> -1 Then
Console.WriteLine("""laranjas"" está na posição" & pos)
Else
Console.WriteLine("""laranjas"" não existe nas compras")
End If
Console.ReadKey()
End Sub
Public Sub MostraValores(ByVal lista As IEnumerable)
For Each obj In lista
Console.Write(" " & obj)
Next obj
Console.WriteLine()
End Sub
End Module
A saída do programa anterior será:
‐ 5 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Inserir um elemento ao final da colecção é realizado através do método Add. Inserir
um elemento no meio da colecção é realizado com o método Insert, especificando, como
priimeiro parâmetro, o índice onde o elemento deverá ser inserido. Ao se remover
elementos da colecção os elementos seguintes são deslocados uma posição para a
esquerda, de forma análoga, quando se insere um elemento os elementos à direita são
deslocados para a direita, para arranjar espaço para a inserção.
3.2. Pilhas
A pilha (“Stack”) é uma estrutura de dados linear, em que os dados são armazenados
de forma sequencial, sendo “empilhados” uns em cima dos outros.
Uma Pilha é uma estrutura de dados do tipo LIFO (Last In First Out), cujo
funcionamento é inspirado no de uma pilha “natural”, na qual o último elemento a ser
inserido é sempre o primeiro a ser retirado. Uma analogia mais correcta é a de uma pilha
de objectos, e.g. livros, em que um elemento permanece no local onde é colocado, até
ser removido. O que se altera é a posição em que se efectuam as inserções e remoções.
Assim sendo pode–se referir que uma Pilha (stack)é uma estrutura de dados de
comprimento variável, cujas caracteristicas principais se resumem em:
• O primeiro elemento inserido é o último a ser eliminado ou retirado da pilha (FILO
– First In Last Out).
• O último elemento inserido é o primeiro a ser eliminado (LIFO – Last In First Out).
Suponha que está a empilhar pratos para lavar. Quando coloca um prato na pilha de
pratos para lavar, coloca na parte de cima da pilha, Quando retira um prato da pilha,
retira da parte de cima. Este modo de acesso á pilha designa‐se por LIFO (Last In, First
Out)
Identificam‐se como propriedades das pilhas:
• os itens encontram‐se armazenados sequencialmente
• o último elemento da pilha denomina‐se por topo
• os itens são inseridos no topo da pilha (push)
‐ 6 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
• os itens são removidos no topo(pop)
• apenas o elemento do topo é visível (top)
Assim, as pilhas são estruturas baseadas no princípio LIFO, na qual os dados que foram
inseridos por último na pilha serão os primeiros a serem removidos. Existem duas funções
que se aplicam a todas as pilhas: PUSH, que insere um dado no topo da pilha, e POP, que
remove o item no topo da pilha.
• os elementos são colocados e retirados por um único lado – referenciado por
topo
• sempre que um elemento é adicionado ou retirado da pilha o topo é alterado
• estrutura com uma ordenação "LIFO ‐ Last In First Out"
Na figura seguinte ilustra‐se o funcionamento de uma stack através da simulação de
inserções e remoções de elementos.
7
5 15 15
10 10 10 10 10
Figura 1 - Funcionamento de uma stack
Referem‐se como os seguintes campos de aplicação das pilhas:
• na avaliação de expressões numéricas
• algoritmos para a implementação de tratamento de texto
• na recursividade
• nos compiladores (passagem de parâmetros, valores das variáveis locais,
valores de retorno)
Os exemplos apresentados nesta secção estão associados à manipulação de strings e à
análise dos parênteses numa expressão. Na tabela seguinte serão apresentados os
métodos e propriedade da classe Stack.
‐ 7 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Tabela 3 ‐ Métodos definidos na classe Stack
Método/Propriedade Descrição
Contains Boolean que indica se um elemento existe na Stack
Clear Remove todos os elementos da Stack.
ToArray Copia os elementos da Stack para um vector novo.
Pop Remove e retorna o objecto que está no topo da
Stack.
Push Adiciona um objecto ao topo da Stack.
CopyTo Copia os elementos da Stack para um vector
unidimensional existente, com início num índice
especificado do vector.
Count Propriedade que retorna o número de elementos
contidos na Stack.
Peek Retorna o objecto, sem o remover, que está no topo
da Stack.
Exemplo 1:
Pretende‐se implementar um programa, com base numa estrutura de dados linear do
tipo pilha, que inverta a ordem dos caracteres de uma string (terminada por ponto). Por
exemplo, uma string de entrada “António.” deverá ser invertida para “oinótnA”.
Exemplo 2 ‐ Inversão de uma string
Sub Main()
Dim pstack As New Stack(Of Char)
Dim car As Char
' Empilha todos os caracteres.
car = ChrW(Console.Read())
Do While car <> "."
pstack.Push(car)
car = ChrW(Console.Read())
Loop
'Mostra a stack
Do While (pstack.Count > 0)
car = pstack.Pop()
Console.Write(car)
Loop
End Sub
‐ 8 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Exemplo 2:
Pretende‐se implementar um programa que dada uma lista de palavras, verifica quais
as palavras palíndromas. A função EPalindroma retorna um valor Boolean que indica se
uma palavra passada como argumento é palíndroma ou não (isto é, se a leitura da palavra
é a mesma, quer se faça da esquerda para a direita, quer se faça da direita para a
esquerda). O programa seguinte usa um objecto Stack para empilhar as letras da palavra
para de seguida comparar as letras empilhadas (e que, consequentemente, serão
removidas por ordem inversa) com as letras da palavra a partir da esquerda.
Exemplo 3 ‐ Palavras palíndromas
Module Module1
Sub Main()
‘ Cria uma lista de palavras.
Dim palavras() As String = {"arara", "osso", "reviver", "somavamos", "Ame a
Ema", "estruturas"}
' Verifica quais as palavras palíndromas.
Console.Write("Palíndromas: ")
For Each palavra As String In palavras
If (EPalindroma(palavra)) Then
Console.Write(palavra & "; ")
End If
Next
Console.ReadKey()
End Sub
‐ 9 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
End If
pos += 1
Loop
' A palavra é palíndroma, uma vez que se
' lê da mesma forma nos dois sentidos.
Return True
End Function
End Module
Exemplo 3:
O exemplo seguinte faz a análise sintáctica dos parênteses de uma expressão, uma das
áreas de aplicação típicas das pilhas. Na literatura inglesa esta operação designa‐se por
“balancing brackets”. Por parênteses entendee‐se, neste caso:
• Os caracteres abrir e fechar parênteses curvos "(" e “)";
• Os caracteres abrir e fechar parênteses rectos (“[” e ”]”;
• Os caracteres abrir e fechar chavetas “{“ e “}".
Por mais simples ou complexas que as expressões sejam, por exemplo a seeguinte
expressão:
soma=(2+3*(4+5)/(6+7))
É importante para programas como compiladores analisarem se a expressão é
sintacticamente correcta ou não. Dito de outra forma, se os parênteses estão correctos
ou se, por outro lado, existem parênteses a mais, a menos, ou se não são do mesmo tipo.
O algoritmo de análise sintáctica dos parênteses seguido é o seguinte:
1. Cria uma pilha vazia.
2. Percorre os caracteres do início até ao fim da string.
3. Se o carácter for uma abertura de parênteses, faz o Push para a pilha.
4. Se o carácter for o fecho de parênteses, então, se a pilha estiver vazia, indica
que há um erro.
5. Se a pilha não estiver vazia faz o Pop do elemento no topo da pilha. Se este
carácter não for do mesmo tipo da abertura de parênteses, então indica um
erro.
6. No final do processamento da string, se a pilha não estiver vazia indica que há
um erro (o número de abrir e fechar parênteses não é idêntico).
O programa de análise de expressões será o seguinte:
‐ 10 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Exemplo 4: Análise sintáctica dos parênteses de uma expressão
Module Module1
Sub Main()
' String-exemplo para a análise de parênteses
' Em inglês conhecido como "Balancing Brackets".
Dim prg As String = "{ soma[0]=(2+3*(4+5)/(6+7)) }"
‐ 11 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
' Carácter abrir parênteses não corresponde ao fechar parênteses
Return False
End If
Else
' Pilha vazia, não há carácter para comparar.
Return False
End If
End If
Next
If parenteses.Count > 0 Then
' Erro: faltam caracteres do tipo fechar parênteses.
Return False
End If
Return True
End Function
End Module
Exemplo 4:
Pretende‐se simular um armazém no qual opera um empilhador que tem por missão
arrumar caixotes em compartimentos numerados. Estes caixotes podem ser sobrepostos
até um número máximo de 5 caixotes. Se o empilhador não puder colocar em cima de
outro caixote no compartimento seleccionado, o empilhador tenta colocar o caixote no
compartimento seguinte. Defina a classe Armazém, os métodos empilha, desempilha e
um método que mostra todos os caixotes. A aplicação deverá ter a seguinte interface
gráfica:
• Caixa de Texto “Compartimento”: Selecção do número de compartimento a
empilhar/desempilhar
• Botão “Empilha”: Coloca um caixote no “Compartimento” seleccionado
• Botão “Desempilha”: Retira um caixote do “Compartimento” seleccionado
‐ 12 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Exemplo 5: Armazém de Caixotes
Public Class Caixote
Dim i As Integer
End Class
‐ 13 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Escreve()
End Sub
3.3. Queue
As filas são estruturas de dados que se comportam como as filas que conhecemos.
Uma fila não é mais que uma lista na qual é aplicada uma disciplina de acesso
característica: todo o elemento que entra na lista é inserido no fim da lista e todo o
elemento que sai da lista é removido do início desta.
As filas são estruturas baseadas no princípio FIFO (First In, First Out), em que os
elementos que foram inseridos no início são os primeiros a serem removidos. Uma fila
possui duas funções básicas: ENQUEUE, que adiciona um elemento ao final da fila, e
DEQUEUE, que remove o elemento no início da fila.
A operação DEQUEUE só pode ser aplicado se a fila não estiver vazia, causando um
erro de underflow ou fila vazia se esta operação for realizada nesta situação.
Assim sendo referese‐se que uma fila como uma estrutura de dados de comprimento
variável com as seguintes características:
• A informação é processada pela ordem que foi recebida, isto é, o primeiro
elemento a ser inserido é o primeiro elemento a ser eliminado (FIFO – First In First
Out / FCFS – First Come First Served).
• A inserção é efectuada na cauda (direita) da fila e a eliminação é efectuada na
frente (esquerda) da fila.
Podemos definir as seguintes propriedades das fias:
• os nós estão organizados sequencialmente;
• existem dois extremos na fila: o início e o fim
• os nós são adicionados no fim da fila
‐ 14 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
• os nós são removidos do início da fila
• a fila é percorrida do início até ao fim
Exemplos de áreas de aplicação das filas nos computadores incluem priorizar
processos do sistema operativo e gerir a partilha de recursos, como, por exemplo, enviar
documentos para a fila de uma impressora. No mundo real permite simular um vasto
conjunto de situações, incluindo as seguintes:
• Registo de alunos para um exame;
• Controladores de Tráfego Aéreo a controlar a descolagem e aterragem de
aviões;
• As chamadas feitas para uma linha telefónica;
• Carros a entrar para um parque de estacionamento;
• Clientes numa caixa registadora de um supermercado;
Figura 2 - Funcionamento de uma Fila
Adicionar e remover elementos de uma fila são duas das operações básicas das filas.
Outras operações da classe Queue incluem eliminar todos os elementos (Clear), verificar
se um elemento existe (Contains) e retornar o elemento no início da fila, sem o remover
(Peek, que significa 'espreitar'). À semelhança de outras classes, a propriedade Count
indica quantos elementos existem na colecção. A tabela seguinte apresenta a descrição
destes membros.
‐ 15 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Tabela 4 – Membros da Classe Queue
Método/Propriedade Descrição
Clear Remove todos os elementos da Queue.
Contains Retorna um Boolean que indica se um elemento existe
na Queue.
CopyTo Copia os elementos da Queue para um vector
unidimensional existente, com início num índice
especificado do vector.
Count Retorna o número de elementos contidos no Queue.
Dequeue Remove e retorna o objecto que está no início da Queue.
Enqueue Adiciona um objecto ao fim da Queue.
Peek Retorna o objecto, sem o remover, que está no início da
Queue.
ToArray Copia os elementos da Queue para um vector novo.
Exercicio Resolvido:
Pretende‐se simular um conjunto de caixas num supermercado. Os clientes
seleccionam uma caixa para pagamento e esperam pela sua vez. A funcionária da caixa
será efectuada por um relógio (timer) que será disponibilizado. A aplicação deverá ter a
seguinte interface gráfica:
• Texto “Nome do Cliente”: permite identificar o cliente
• Botão “Caixa X”: Adiciona o cliente “Nome do Cliente” à caixa X
• Existe um Relógio (Timer) que remove aleatoriamente os clientes.
‐ 16 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Exemplo 6: Supermercado
Public Class Supermercado
Dim capacidade As Integer = 10
Dim caixas(capacidade) As Queue(Of Cliente)
Public Sub ColocaNaFila(ByVal i As Integer, ByRef nome As String)
If (i < 0 OrElse i > capacidade) Then Return
If (caixas(i) Is Nothing) Then caixas(i) = New Queue(Of Cliente)
caixas(i).Enqueue(New Cliente(nome))
End Sub
Public Sub RemoveDaFila(ByVal i As Integer)
If (i < 0 OrElse i > capacidade) Then Return
If (caixas(i) Is Nothing) Then Return
caixas(i).Dequeue()
If (caixas(i).Count = 0) Then caixas(i) = Nothing
End Sub
Sub MostraFila(ByVal i As Integer, ByRef lista As IList)
lista.Clear()
Dim q As Queue(Of Cliente) = caixas(i)
If ((q Is Nothing) OrElse (q.Count = 0)) Then
lista.Add("Caixa Vazia!")
Else
Dim x As Integer = 0
For Each c As Cliente In q
lista.Add(c.ToString + " " + x.ToString())
x = x + 1
Next
End If
End Sub
End Class
‐ 17 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
3.4. Classe SortedList
À semelhança das classes HashTable, Dictionary e SortedDictionary, a classe SortedList
é também uma estrutura de dados que armazena dados como um par chave‐valor.
A classe SortedList representa uma colecção ordenada (sorted) sendo possível aceder
aos elementos por chave ou por índice (como na classe List). As outras classes do tipo
dicionário não permitem o acesso por índice.
A classe SortedList é implementada internamente através de dois vectores: um para as
chaves e outro para os valores. A inserção ou remoção de elementos no meio do vector é
uma operação relativamente lenta, uma vez que implica deslocar parte dos elementos da
colecção. A classe genérica Sorted‐Dictionary, que também mantém os elementos
ordenados, é implementada como uma árvore binária, sendo muito mais eficiente para
colecções muito grandes. Contudo, não permite o acesso aos elementos por índice.
As operações disponibilizadas para a classe SortedList, quando comparadas com as
outras estruturas de dados do tipo dicionário, são muito mais extensas.
Mais concretamente, existe um conjunto de métodos que começam com Get que
permitem retornar, por exemplo, o valor de um índice especificado e a chave associada a
um índice especificado. Por outro lado, existem dois métodos, IndexOfKey e IndexONalue,
que permitem retornar o índice de uma determinada chave e de um determinado valor,
respectivamente. Para se remover um elemento num determinado índice usa‐se o
método RemoveAt, passando o índice do elemento a remover como argumento. Uma
selecção dos principais métodos é apresentada na tabela seguinte.
Tabela 5 ‐ Métodos da classe Sorted List
Método/Propriedade Descrição
Add Adiciona um elemento com a chave e valor especificados
a um objecto SortedList.
Clear Remove todos os elementos do SortedList.
Clone Faz uma cópia dos elementos tipo valor do SortedList
Contains Retorna um Boolean que indica se o SortedList contém
uma chave específica .
ContainsKey Retorna um Boolean que indica se o SortedList contém
uma chave específica.
ContainsValue Retorna um Boolean que indica se o SortedList contém
um valor específico.
CopyTo Copia os elementos da SortedList para um vector
unidimensional, com início num índice especificado do
vector.
‐ 18 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
GetBylndex Retorna o valor do índice especificado de um objecto
SortedList.
GetKey Retorna a chave associada ao índice especificado de um
objecto SortedList.
GetKeyList Retorna todas as chaves de um objecto SortedList.
GetValueList Retorna todos os valores de um objecto SortedList.
IndexOfKey Retorna o índice, sendo o índice do primeiro elemento
zero, da chave especificada de um objecto SortedList.
IndexOfValue Retorna o índice, sendo o índice do primeiro elemento
zero, da primeira ocorrência do valor especificado num
objecto SortedList.
Remove Remove o elemento com a chave especificada de um
objecto SortedList.
RemoveAt Remove o eiemento no lndice especificado de um objecto
SortedList.
SetBylndex Substitui o valor no índice especificado num objecto
SortedList.
TrimToSize Define a capacidade como sendo o número actual de
elementos do objecto SortedList
As propriedades disponibilizadas pela classe SortedList são idênticas às outras classes
do tipo dicionário. No entanto, como internamente se trata de vectores, a classe
SortedList disponibiliza a propriedade, Capacity, de leitura e escrita que permite retornar
ou definiri a capacidade de um objecto SortedList. As propriedades da classe SortedList
são apresentadas na tabela seguinte.
Tabela 6 ‐ Propriedades da Classe SortedList
Propriedade Descrição
Capacity Retorna ou define a capacidade de um objecto SortedList.
Count Retorna o número de elementos efectivamente contidos
num objecto SortedList.
Item Retorna ou define um valor associado com a chave
específica num objecto SortedList.
Keys Retorna as chaves existentes num objecto SortedList.
Values Retorna os valores existentes num objecto SortedList.
‐ 19 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
O exemplo seguinte usa um objecto SortedDictionary para manter ordenada uma
listagem de nomes e respectiva frequência (número de ocorrências) lidos de um ficheiro.
Os nomes de pessoas armazenados num ficheiro ("nomes.txt") são lidos linha a linha.
Cada linha (string) é decomposta em palavras, sendo estas palavras a chave a inserir no
dicionário, caso ainda não existam, ou então, tendo já sido inseridas no dicionário, é
incrementado um contador do número de ocorrências (que representa o valor do par
chave‐valor). No final o programa mostra os nomes ordenados e a sua frequência. O
programa converte os elementos do dicionário para um vector para facilitar a ordenação
por frequência e voltar a mostrar os elementos da colecção.
Exemplo 7 ‐ Classe SortedList
' Classe SortedList
' Conta a ocorrência de nomes de um ficheiro.
Try
' Tenta abrir o ficheiro para leitura.
Dim tr As StreamReader = New StreamReader("nomes.txt")
‐ 20 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Catch ex As Exception
Console.WriteLine("O ficheiro não foi encontrado: " &
ex.Message)
Return
End Try
‐ 21 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
A saída do programa anterior seria a listagem seguinte:
Os nomes completos lidos do ficheiro são decompostos (método Split) em palavras
individuais e, para cada palavra, verifica‐se se já existe no dicionário. Se já existir é
incrementado o contador; caso contrário, a palavra é adicionada ao dicionário. A listagem
ordenada por nome e por índice é apresentada. A ordenação alfabética é trivial: a classe
SortedDictionary mantém automaticamente a ordenação por chave. É só necessário
percorrer todos os elementos da colecção, através de um ciclo For Each ...Next.
Para a ordenação por frequência é criado um vector de strings. Cada elemento do
vector é uma string composta pelo número de ocorrências seguido do nome. A
especificação do formato "{0,3}" no método String.Format é importante para que a
ordenação tenha sucesso. Neste caso trata‐se a ordenação numérica como se de uma
string se tratasse. É a inserção de espaços que garante que, por exemplo, a string "10"
não seja avaliada como menor do que a string " 9" (note o espaço no início da string " 9").
Sem o espaço, a comparação indicaria que "9" é maior do que "10", uma vez que a
comparação é feita carácter a carácter. De seguida chama-se o método Sort da classe Array
para a ordenação.
‐ 22 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
3.5. Classe genérica LinkedList
Figura 3 ‐ Lista Duplamente ligada
Os rectângulos a tracejado, First e Last, representam duas propriedades da classe
LinkedList. Estas propriedades retornam, respectivamente, o primeiro e o último nó da
lista. A lista possui quatro nós (uma classe do tipo LinkedListNode), cujos valores são os
quatro frutos. As dez setas representam referências para que a lista mantenha uma
sequência dos nós. A palavra Nothing representa uma referência nula.
A designação da classe associada aos nós que compõem uma lista é LinkedListNode.
Como indicado, esta classe deve possuir pelo menos três variáveis: uma para armazenar o
valor do nó e duas referências: uma para o nó seguinte e outra para o nó anterior da lista
ligada. Na figura 3, uma LinkedListNode é um rectângulo dividido em três partes: um valor
no centro (neste caso, frutas) e dois outros valores, associados às duas referências.
As operações básicas de uma lista ligada incluem a inserção de novos nós (no início,
fim ou a meio da lista; métodos que começam por Add); a remoção de um qualquer nó
existente (no início, fim ou a meio da lista; métodos que começam por Remove); verificar
se existe um nó com um determinado valor (Contains) e ainda procurar o primeiro ou o
último nó com um valor especificado (Find e FindLast). A tabela seguinte descreve os
principais métodos da classe LinkedList.
Tabela 7 ‐ Métodos da classe LinkedList
Método Descrição
AddAfter Overloaded. Adiciona um novo nó ou valor depois de um nó
existente na LinkedList.
AddBefore Overloaded. Adiciona um novo nó ou valor antes de um nó
existente na LinkedList.
AddFirst Overloaded. Adiciona um novo nó ou valor no início da
LinkedList.
‐ 23 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
AddLast Overloaded. Adiciona um novo nó ou valor no fim da
LinkedList.
Clear Remove todos os nós da LinkedList.
Contains Retorna um Boolean que indica se um valor existe na
LinkedList.
CopyTo Copia a LinkedList completa para um vector unidimensional
compatível, com início num índice especificado do vector.
Find Encontra o primeiro nó que contém um valor específico.
FindLast Encontra o último nó que contém um valor específico.
Remove Overloaded. Remove a primeira ocorrência de um nó ou valor
da LinkedList.
RemoveFirst Remove o primeiro nó da LinkedList.
RemoveLast Remove o último nó da LinkedList.
A classe LinkedList disponibiliza, para além da propriedade Count, que retorna o
número de elementos da colecção (o número de nós), duas outras propriedades: First e
Last, que retornam uma referência para um objecto do tipo nó (LinkedListNode),
respectivamente o primeiro e o último nó da lista. A tabela seguinte resume estas
propriedades.
Tabela 8 – Propriedades da classe LinkedList
Propriedade Descrição
Count Retorna o número de nós actualmente armazenados na
LinkedList.
First Retorna o primeiro nó da LinkedList.
Last Retorna o último nó da LinkedList.
A classe LinkedListNode(T) representa um nó numa classe LinkedList(T). O construtor
desta classe permite iniciar uma nova instância com um determinado valor (de um tipo de
dados especificado, uma vez que se trata de uma classe genérica). Os métodos da classe
LinkedListNode(T) são apenas os herdados da classe Object, não possuindo portanto
métodos específicos à classe. As quatro propriedades definidas na classe são as
apresentadas na tabela seguinte.
‐ 24 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Tabela 9 – propriedades da Classe LinkedListNode
Propriedade Descrição
List Retorna o objecto LinkedList a que o LinkedListNode
pertence.
Next Retorna o próximo nó na LinkedList.
Previous Retorna o nó anterior da LinkedList.
Value Retorna o valor armazenado no nó.
O exemplo descrito de seguida ilustra os conceitos anteriores. O seguinte programa
usa diversos métodos e propriedades da classe LinkedList, incluindo: AddFirst, AddLast,
Find, AddAfter, Remove, RemoveFirst, RemoveLast e Contains. Usa ainda a propriedade
Count para percorrer a lista, associada a um ciclo For...Next. Uma novidade da plataforma
.NET, versão 3.5, refere‐se ao facto de ser possível aceder aos elementos de uma lista
através de um índice, como ilustrado na função MostraConteudoDaLista.
Exemplo 8 ‐ Classe LinkedList
Module Module1
' Classe LinkedList.
Sub Main()
Dim lista As New LinkedList(Of String)
Console.Title = "Ana Madureira"
lista.AddFirst("segundo")
lista.AddFirst("primeiro")
lista.AddLast("quarto")
lista.AddLast("quinto")
MostraConteudoDaLista(lista)
‐ 25 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
Dim item As String = "primeiro"
Console.Write("A lista contém """ & item & """? ")
If lista.Contains(item) Then
Console.Write("Verdadeiro")
Else
Console.Write("Falso")
End If
Console.WriteLine()
Console.ReadKey()
End Sub
A saída do programa anterior será:
Como referido anteriorrmente as classe associadas às colecções podem ser
classificadas em duas categorias : classes tradicionais e as classes genéricas. As colecções
tradicionais residem no namespace System.Collection, enquanto que o namespace
System.Collection.Generic é o local onde residem as colecções genéricas.
O namespace Microsoft.VisualBasic possui a classe tradicional Collection que
disponibiliza um conjunto de operações básicas sobre colecções de dados. Diversas
estruturas de dados, designadas como sendo do tipo dicionário, armazenam dados como
um par chave‐valor. As classe genéricas são Dictionary, SortedDictionary e SortedList. As
classes tradicionaissão HashTable e SortedList. Para a representação de uma colecção de
‐ 26 ‐
Aplicações Informáticas de Gestão
Estruturas de Dados Dinâmicas
www.foresp.pt
nós ligados usa‐se a classe genérica LinkedList. Para uma descrição detalhada ver, por
exemplo [1][2[4]].
3.6. Árvores (trees)
Uma árvore é uma estrutura de dados em que cada elemento tem um ou mais
elementos associados. Cada árvore tem apenas uma raiz (nó), a partir da qual nascem
vários “ramos”. Um dos tipos de arvores mais utilizados é a árvore binária onde a partir
de cada nó, nascem no máximo dois ramos. Nas árvores, os valores são armazenados nos
nós. A um nó que não têm descendentes, denomina‐se por folha.
As árvores binárias são muito utilizadas como estruturas de busca, onde os valores
menores são utilizados nos nós dos ramos à esquerda e os valores maiores do que o nó
são armazenados nos nós dos ramos à direita.
3.7. Grafos (graph)
Um grafo é representado como um conjunto vértices (nós) ligados por linhas (as
arestas). Dependendo da aplicação, as arestas podem ser direccionadas, e são
representadas por "setas". Caso os grafos tenham setas, são designados por grafos
direccionados ou orientados.
Como exemplo de utilização de um grafo pode‐se representar uma mapa de estradas e
usar algoritmos específicos para determinar o caminho mais curto entre dois pontos, ou o
caminho mais rápido.
Outro exemplo de utilização de grafos, são as redes PERT, utilizadas para apoio ao
planeamento de projectos.
4. Bibliografia
1. O Guia Prático do Visual Basic 2008, Vítor Pereira, ISBN: 978‐989‐615‐067‐9,
Centro Atlântico, 2008
2. Programação em Visual Basic .NET, Vasco Capitão, FCA (www.fca.pt)
3. An Introduction to Programming Using Visual Basic 2005, 6ª Edição, David I.
Schneider, Prentice Hall
4. Informação suplementar da Microsoft: http://msdn.microsoft.com/library.
‐ 27 ‐