Escolar Documentos
Profissional Documentos
Cultura Documentos
Vetores e registros são estruturas de dados estáticas. Isto porque o número de elementos em cada uma
destas estruturas é determinado no momento de sua alocação na memória; normalmente quando as
variáveis são declaradas.
Em muitos casos, entretanto, o número de elementos em uma estrutura não é conhecido inicialmente; ou
seja, no início de um algoritmo não é possível determinar quantos elementos serão necessários na
resolução de um determinado problema. Nestes casos, é necessário utilizar o conceito de estruturas de
dados dinâmicas, onde a quantidade de elementos pode ser frequentemente alterada, para mais ou para
menos.
Exemplo 2: Para localizar um arquivo no disco, por exemplo, é necessário explorar cada uma das pastas de
armazenamento. Se a busca iniciar na pasta raiz, é preciso identificar que pastas estão contidas nela. Mas,
dentro de cada uma destas pastas existem possivelmente outras, e dentro destas outras, mais outras, até
que um limite é atingido. Nestes casos, também é impossível determinar inicialmente o número de pastas a
pesquisar, assim como o número de ocorrências do arquivo procurado.
Exemplo 3: Considere, finalmente, o seguinte problema: viajar de Natal para Tóquio. Qual a melhor solução
para o problema considerando que o passageiro quer realizar a viagem no tempo mais curto, ou gastando o
menos possível, ou efetuando o menor número de decolagens? Aqui, é necessário mapear todos os
caminhos possíveis entre as cidades e quantificar todas as variáveis pertinentes ao problema: tempo, custo
e decolagens. Certamente, a quantidade de percursos possíveis é desconhecida no início do problema.
Portanto, em problemas mais complexos, é frequentemente necessário utilizar alguma estrutura de dados
que possa aumentar ou diminuir de tamanho de acordo com a solução requisitada para o problema.
As listas são coleções de elementos, em geral de um mesmo tipo, semelhantes aos vetores. A diferença
está no fato delas não terem um tamanho fixo e não serem indexadas. Comumente, uma lista inicia vazia e
os elementos vão sendo adicionados e removidos quando necessário. O acesso aos elementos é realizado
através de apontadores que são variáveis do tipo ponteiro. Em geral, o primeiro elemento da lista possui o
endereço do segundo elemento; o segundo do terceiro e assim por diante. O exemplo 1, apresentado
anteriormente, pode ser resolvido com o auxílio de duas listas: uma para representar a relação de
candidatos e outra para a relação de salas.
1
As árvores são coleções de elementos atraledos a uma estrutura hierárquica onde um elemento possui um
determinado número de subordinados. Em uma árvore, os elementos são comumente chamados de nós. O
nó principal é denominado de nó raiz e pode possuir uma quantidade qualquer de subordinados: os nós-
filhos. Cada nó-filho pode possuir também um determinado número de subordinados, mas possui apenas
um nó-pai. A estrutura de pastas ou diretórios em um disco é um exemplo clássico de árvore e certamente
pode ser utilizada para solucionar o exemplo 2, citado acima.
As árvores são na verdade um tipo particular de grafos, onde um nó possui muitos filhos mas um único pai.
Em um grafo, um nó pode ter vários pais e vários filhos, gerando uma estrutura um pouco mais complexa.
Em um grafo é possível partir de um nó-pai, passar por vários filhos e, de repente, voltar ao nó pai.
A figura abaixo mostra em um digrama os três tipos de estruturas. Na lista, o primeiro elemento possui um
apontador para o segundo e o segundo para o terceiro. Na árvore, o nó pai (1) possui apontadores para os
nós filhos (2) e (3). Finalmente, no grafo, cada nó possui apontadores para os nós interligados a ele.
Os grafos são usados na solução de muitos problemas práticos, como por exemplo, nas áreas de Redes de
Computadores, Telecomunicações, Engenharia Elétrica, Tráfego Aéreo e Computação Gráfica. O exemplo
da viagem Natal-Tóquio, visto anteriormente, é um tipo de problema onde os grafos são comumente
empregados. Certamente, uma das aplicações mais comuns para os grafos é o circuito elétrico; onde os nós
representam os pontos do circuito com mesma tensão e os elementos físicos, as ligações entre eles.
1 1 1
3 2 3 2 3
Na lista simplesmente encadeada, cada elemento possui um apontador para o elemento seguinte. Ou seja,
cada elemento tem um ponteiro que armazena o endereço de memória do próximo elemento. Desta forma,
para que todos os elementos da lista sejam acessíveis, é necessário possuir apenas o endereço do primeiro
elemento.
struct Tipo_Elemento
{
// Declaração dos Campos do Elemento
Tipo_Elemento *Prox;
};
2
Onde Tipo_Elemento é o tipo de cada elemento da lista; Prox é um ponteiro que cada elemento possui
para armazenar o endereço de memória do elemento seguinte e Inicio é um ponteiro para o primeiro
elemento. Como a lista inicia vazia, o ponteiro Inicio deve receber o valor NULL, indicando que nenhum
endereço válido é armazenado. Finalmente, dentro do registro devem ser listados os campos que cada
elemento da estrutura deve armazenar.
As declarações abaixo, por exemplo, são o primeiro passo para criar uma lista com os dados dos veículos
de uma concessionária. Cada elemento da lista armazena o modelo, o ano e o preço de um veículo e o local
de memória onde estão os dados do veículo seguinte.
struct Veiculo
{
AnsiString Modelo;
int Ano;
double Preco;
Veiculo *Prox;
};
Inicio NULL
Neste momento, um elemento é inserido na lista e a variável Inicio armazena o endereço do primeiro
elemento.
Inicio Modelo
Ano
Preco
Prox
Os dados do primeiro elemento devem ser então iniciados. Os comandos abaixo podem ser utilizados para
realizar esta tarefa.
Observe a notação usada para acessar os campos do elemento. Como a variável Inicio é um ponteiro de
struct, o operador -> é utilizado para acessar os campos do endereço de memória apontado por Inicio.
Neste caso, não é necessário utilizar o operador indireto *.
Observe também a iniciação do campo Prox com NULL, uma vez que não existe ainda um segundo
elemento na lista. De fato, o campo Prox do último elemento deve sempre NULL.
3
Inicio Modelo Gol Power
Ano 2006
Preco 38000
Prox NULL
Observe que o campo Prox de Aux, que apontava para o último elemento, é quem possui acesso ao novo
elemento. Para facilitar o acesso ao novo último elemento, podemos alterar o valor de Aux, de acordo com o
comando abaixo, facilitando a definição dos seus dados.
Aux = Aux->Prox;
Aux
Como Aux aponta agora para o último elemento da lista, podemos alterar seus campos através dele como
mostra os comandos a seguir:
4
Aux->Modelo = "Corsa";
Aux->Ano = 2005;
Aux->Preco = 25000;
Aux->Prox = NULL;
Aux
Observe que é sempre conveniente utilizar um ponteiro auxiliar. Isto acontece porque o ponteiro Inicio não
deve ter ser valor alterado visto que é a única variável que armazena o local de memória onde a lista inicia.
É preciso ser prudente ao alterar o valor armazenado em Inicio para evitar que os elementos da lista fiquem
perdidos na memória.
Neste caso, a lista é destruída do início para o fim. Por isso, o ponteiro Inicio vai sendo alterado sempre
para apontar para o elemento seguinte da lista o qual está prestes a ser destruído.
3.3. Exemplo
O programa apresentado a seguir realiza o cadastro de veículos de uma concessionária (na memória)
utilizando uma lista simplesmente encadeada.
5
Programa 11: Lista Simplesmente Encadeada.
A tela principal do programa é apresentada abaixo. São realizadas as operações de cadastro, listagem total
e parcial. Na parcial, devem ser listados os veículos até um determinado preço.
A declaração da lista é a mesma apresentada anteriormente e pode ser feita no cabeçalho do programa.
struct Veiculo
{
AnsiString Modelo;
int Ano;
double Preco;
Veiculo *Prox;
};
O código para o botão Cadastrar é apresentado abaixo. Verifique que é necessário testar se é ou não o
primeiro veículo da lista.
6
Para listar os veículos, é necessário percorrer a lista desde o início. O código para o botão Listar Todos é
apresentado a seguir:
Para listar até um determinado valor, é necessário também percorrer toda a lista. Neste caso, temos que
verificar se cada elemento satisfaz ao critério de busca. O código abaixo mostra a programação do botão
Listar Até.
Memo1->Clear();
double Preco = Edit4->Text.ToDouble();
Finalmente, é necessário destruir a lista no final do programa. Neste caso, podemos utilizar o evento
OnClose do formulário é realizar esta tarefa, conforme visto abaixo:
7
3.4. Exercícios
1. Definir uma lista cujos elementos representem os componentes de um computador, armazenando o nome
do componente e o preço. Implementar uma interface gráfica que permita cadastrar os componentes de um
micro, listar os componentes cadastrados e totalizar o custo total do equipamento.
2. Definir uma lista cujos elementos representam os dados das disciplinas do seu curso, armazenando
semestre, nome da disciplina, média final e situação (aprovado ou reprovado). Implementar uma interface
gráfica que permita cadastrar um vetor com até 50 disciplinas, listar todas as disciplinas cadastradas, obter
as disciplinas com a maior e a menor média e calcular a média das médias de todas as disciplinas em que
tenha sido aprovado.
3. Modificar o programa 11 (Lista de Veículos) de forma que os veículos sejam incluídos em ordem
alfabética de nome. Permitir também que um veículo possa ser excluído da lista.