Estrutura de Dados - Sonia Virginia Alves Franca

Propaganda
Estrutura de Dados
Sônia Virginia Alves França
2007
Estrutura de Dados
Índice
1. Estrutura de Dados .............................................................................................................................. 4
2. Tipos de Estruturas de Dados .............................................................................................................. 5
2.1 Listas Lineares ..............................................................................................................................................5
2.2 Filas ................................................................................................................................................................6
2.3 Pilhas ..............................................................................................................................................................6
2.4 Árvores...........................................................................................................................................................7
3. Implementação das Estruturas Estáticas .......................................................................................... 12
3.1 Lista Estática Desordenada........................................................................................................................12
3.1.1 Operações Básicas.................................................................................................................................................12
3.1.2 Algoritmo...............................................................................................................................................................15
3.1.3 Programa em C .....................................................................................................................................................17
3.2 Lista Estática Ordenada.............................................................................................................................21
3.2.1 Operações Básicas.................................................................................................................................................21
3.2.2 Algoritmo...............................................................................................................................................................24
3.2.3 Programa em C .....................................................................................................................................................27
3.3 Fila Estática .................................................................................................................................................32
3.3.1 Operações Básicas.................................................................................................................................................32
3.3.2 Algoritmo...............................................................................................................................................................33
3.3.3 Programa em C .....................................................................................................................................................35
3.4 Pilha Estática...............................................................................................................................................38
3.4.1 Operações Básicas.................................................................................................................................................38
3.4.2 Algoritmo...............................................................................................................................................................39
3.4.3 Programa em C .....................................................................................................................................................41
4. Implementação das Estruturas Dinâmicas ....................................................................................... 44
4.1 Alocação Dinâmica......................................................................................................................................44
4.2 Lista Dinâmica Desordenada .....................................................................................................................46
4.2.1 Operações Básicas.................................................................................................................................................47
4.2.2 Programa em C .....................................................................................................................................................49
4.3 Lista Dinâmica Ordenada ..........................................................................................................................53
4.3.1 Operações Básicas.................................................................................................................................................53
4.3.2 Programa em C .....................................................................................................................................................56
2
Estrutura de Dados
4.4 Lista Duplamente Encadeada Ordenada..................................................................................................60
4.4.1 Operações Básicas.................................................................................................................................................60
4.4.2 Programa em C .....................................................................................................................................................61
4.5 Fila Dinâmica ..............................................................................................................................................66
4.5.1 Operações Básicas.................................................................................................................................................66
4.5.2 Programa em C .....................................................................................................................................................68
4.6 Pilha Dinâmica ............................................................................................................................................71
4.6.1 Operações Básicas.................................................................................................................................................71
4.6.1 Programa em C .....................................................................................................................................................72
5. Ordenação e Pesquisa ........................................................................................................................ 76
5.1 Ordenação....................................................................................................................................................76
5.1.1 Método da Ordenação por Troca ........................................................................................................................76
5.1.2 Método da Ordenação por Seleção......................................................................................................................77
5.1.3 Método da Ordenação por Inserção....................................................................................................................79
5.2 Pesquisa........................................................................................................................................................80
3
Estrutura de Dados
1. Estrutura de Dados
Estruturas de dados e algoritmos são temas fundamentais da ciência da computação, sendo que são
utilizados nas mais diversas áreas e com os mais diferentes propósitos. Algoritmos manipulam dados.
Quando estes dados estão organizados de forma coerente caracterizam uma estrutura de dados. São a
organização e os métodos que manipulam determinada estrutura que lhe conferem singularidade. A escolha
de uma estrutura de dados apropriada pode tornar um problema complicado em uma solução trivial. O
estudo das estruturas de dados está em constante desenvolvimento, apesar disso, existem estruturas
clássicas que têm se mostrado padrão de facto.
As estruturas têm as suas características básicas e tem finalidades diferentes. Podem ser
implementadas usando vetores (estática) ou ponteiros (dinâmica)
Conceito de Estrutura de Dados
Para definir o que é uma estrutura de dados devemos definir o que é dado e tipo de dado.
Podemos definir dado como um elemento sobre o qual serão efetuadas operações e tipo de dado
é o conjunto de valores ao qual pertence um dado. Exemplos de tipos de dados são inteiro, real, lógico, etc.
Uma primeira classificação para os tipos de dados é: primitivos ou derivados. Os tipos de dados
primitivos são aqueles que não podem ser decompostos, por exemplo: inteiro, real, lógico e caracter. Os
tipos de dados derivados são aqueles definidos a partir dos tipos primitivos, por exemplo: vetores,
matrizes, registros, etc.
Os tipos de dados derivados podem ser homogêneos ou heterogêneos. Os tipos de dados
homogêneos agrupam dados primitivos do mesmo tipo, por exemplo: vetores, cadeias e matrizes. Os
tipos de dados heterogêneos agrupam dados primitivos de tipos diferentes, por exemplo: registros.
Os tipos de dados também podem ser estáticos ou dinâmicos. Os tipos de dados estáticos têm
tamanho sempre finito, por exemplo: tipos primitivos, registros vetores e matrizes. Os tipos de dados
dinâmicos têm um tamanho que pode variar durante o seu tempo de vida, por exemplo: pilhas, filas, listas
encadeadas e árvores.
Visto isso, definimos estrutura de dados como um tipo derivado de dado concebido com o
objetivo de ser manipulado de maneira sistemática por algoritmos e, conseqüentemente, por programas de
computador.
4
Estrutura de Dados
2. Tipos de Estruturas de Dados
2.1 Listas Lineares
Uma das formas mais comumente usadas para se manter dados agrupados é a lista. Afinal, quem
nunca organizou uma lista de compras antes de ir ao mercado, ou então uma lista dos amigos que
participarão da festa? As listas têm-se mostrado um recurso bastante útil e eficiente no dia-a-dia das
pessoas. Em computação, não tem sido diferente: a lista é uma das estruturas de dados mais empregadas
no desenvolvimento de programas.
Ao desenvolver uma implementação para listas lineares, o primeiro problema que surge é: como
podemos armazenar os elementos da lista, dentro do computador?
Sabemos que antes de executar um programa, o computador precisa carregar seu código executável
para a memória. Da área de memória que é reservada para o programa, uma parte é usada para armazenar
as instruções a serem executadas e a outra é destinada ao armazenamento dos dados. Quem determina
quanto de memória será usado para as instruções é o compilador. Alocar área para armazenamento de
dados entretanto, é responsabilidade do programador.
Uma lista linear pode ser implementada usando vetores ou ponteiros. Se for implementada usando
vetores, deve estipular qual a quantidade de elementos que a lista pode armazenar. A memória para
armazenamento dos dados é alocada em tempo de compilação. Quando implementada usando ponteiros, a
memória é alocada conforme novos elementos são colocados na lista e desalocada quando elementos são
retirados. Ou seja, vai alocando memória dinamicamente, em tempo de execução.
Tipos de Listas Lineares:
1. Lista estática desordenada
2. Lista estática ordenada
3. Lista dinâmica desordenada
4. Lista dinâmica ordenada
5. Lista dinâmica duplamente encadeada
Na lista desordenada os elementos são colocados na primeira posição vazia da lista (normalmente,
no final). Na lista ordenada, é escolhido um dado que será o campo de ordenação da lista. Quando se
5
Estrutura de Dados
deseja inserir um novo elemento na lista, primeiro tem que ser verificado em que local ele dever ser
colocado para que seja mantida a ordem da lista.
Operações básicas das listas: inserir elemento, remover elemento, consultar elemento, alterar
elemento, listagem dos elementos da lista.
2.2 Filas
Uma fila é um tipo especial de lista linear em que as inserções são realizadas em um extremo,
ficando as remoções restritas ao outro. O extremo onde os elementos são inseridos é denominado final da
fila, e aquele de onde são removidos é denominado começo da fila.
Cada vez que uma operação de inserção é executada, um novo elemento é colocado no final da fila.
Na remoção, é sempre retornado o elemento que aguarda há mais tempo na fila, ou seja, aquele
posicionado no começo. A ordem de saída corresponde diretamente à ordem de entrada dos elementos na
fila, de modo que os primeiros elementos que entram são sempre os primeiros a sair. Por este motivo, as
filas são denominadas listas FIFO (First-In/First-Out) ou PEPS (Primeiro que Entra/Primeiro que Sai).
Um exemplo bastante comum de filas verifica-se num balcão de atendimento, onde pessoas
formam uma fila para aguardar até serem atendidas. Naturalmente, devemos desconsiderar os casos de
pessoas que “furam” a fila ou que desistem de aguardar! Diferentemente das filas no mundo real, o tipo
abstrato de dados não suporta inserção nem remoção no meio da lista.
Um exemplo de utilização em computação é a implementação de uma fila de impressão. Se uma
impressora é compartilhada por várias máquinas, deve-se adotar uma estratégia para determinar qual
documento será impresso primeiro. A estratégia mais simples é tratar todas as requisições com a mesma
prioridade e imprimir os documentos na ordem em que foram submetidos – o primeiro submetido é o
primeiro a ser impresso.
2.3 Pilhas
Uma das estruturas de dados mais simples é a pilha. Possivelmente por essa razão, é a estrutura de
dados mais utilizada em programação, sendo inclusive implementada diretamente pelo hardware da maioria
das máquinas modernas. A idéia fundamental da pilha é que todo o acesso a seus elementos é feito através
do seu topo. Assim, quando um elemento novo é introduzido na pilha, passa a ser o elemento do topo, e o
único elemento que pode ser removido da pilha é o do topo. Isto faz com que os elementos da pilha sejam
retirados na ordem inversa à ordem em que foram introduzidos: o primeiro que sai é o último que entrou
6
Estrutura de Dados
(a sigla LIFO – last in, first out – é usada para descrever esta estratégia ou UEPS em português - Último que
Entra/Primeiro que Sai).
Para entendermos o funcionamento de uma estrutura de pilha, podemos fazer uma analogia com
uma pilha de pratos. Se quisermos adicionar um prato na pilha, o colocamos no topo. Para pegar um prato
da pilha, retiramos o do topo. Assim, temos que retirar o prato do topo para ter acesso ao próximo prato.
A estrutura de pilha funciona de maneira análoga. Cada novo elemento é inserido no topo e só temos
acesso ao elemento do topo da pilha.
Existem três operações básicas que devem ser implementadas numa estrutura de pilha: a operação
para empilhar um novo elemento, inserindo-o no topo, a operação para desempilhar um elemento,
removendo-o do topo e a operação para consultar qual elemento está no topo da pilha. É comum nos
referirmos a essas operações pelos termos em inglês push (empilhar) e pop (desempilhar).
2.4 Árvores
Nos tópicos anteriores examinamos as estruturas de dados que podem ser chamadas de
unidimensionais ou lineares, como as listas. A importância dessas estruturas é inegável, mas elas não são
adequadas para representarmos dados que devem ser dispostos de maneira hierárquica. Por exemplo, os
arquivos (documentos) que criamos num computador são armazenados dentro de uma estrutura
hierárquica de diretórios (pastas). Existe um diretório base dentro do qual podemos armazenar diversos
subdiretórios e arquivos. Por sua vez, dentro dos sub-diretórios podemos armazenar outros sub-diretórios
e arquivos, e assim por diante, recursivamente.
Arvore são estruturas de dados adequadas para a representação de hierarquias. A forma mais natural
para definirmos uma estrutura de árvore é usando recursividade. Uma árvore é composta por um conjunto
de nós. Existe um nó r, denominado raiz, que contém zero ou mais sub-árvores, cujas raízes são ligadas
diretamente a r. Esses nós raízes das sub-árvores são ditos filhos do nó pai, r. Nós com filhos são
comumente chamados de nós internos e nós que não têm filhos são chamados de folhas, ou nós externos.
Existem três formas de representação gráfica são:
Representação por parênteses aninhados
(
A (B) ( C (D (G) (H)) (E) (F (I)) )
)
7
Estrutura de Dados
Diagrama de inclusão
Representação hierárquica
Motivação
•
diversas aplicações necessitam de estruturas mais complexas que as estruturas básicas(listas, filas e
pilhas);
•
inúmeros problemas podem ser modelados através de árvores
•
árvores admitem tratamento computacional eficiente quando comparadas às estruturas mais genéricas
como os grafos (os quais, por sua vez são mais flexíveis e complexos)
Definição
Uma árvore enraizada T, ou simplesmente uma árvore, é um conjunto finito de elementos denominados
nós ou vértices tais que:
•
T = 0 é a árvore dita vazia ou
•
existe um nó especial r, chamado raiz de T; os restantes constituem um único conjunto vazio ou
são divididos em m (deve ser maior ou igual a 1) conjuntos distintos não vazios que são as
subárvores de r, cada subárvore a qual é, por sua vez, uma árvore.
Subárvore
Seja a árvore acima T = {A, B, ...}
8
Estrutura de Dados
A árvore T possui duas subárvores:
Tb e Tc onde
Tb = { B } e Tc = {C, D, ...}
A subárvore Tc possui 3 subárvores:
Td, Tf e Te onde
Td = {D, G, H}
Tf = {F, I}
Te = {E}
As subárvores Tb, Te, Tg, Th, Ti possuem apenas o nó raiz e nenhuma subárvore.
Nós filhos, pais, tios, irmãos e avô
Seja v o nó raiz da subárvore Tv de T.
Os nós raízes w1, w2, ... wj das subárvores de Tv são chamados filhos de v.
v é chamado pai de w1, w2, ... wj.
Os nós w1, w2, ...wj são irmãos.
Se z é filho de w1 então w2 é tio de z e v é avô de z.
Grau de saída, descendente e ancestral
Número de filhos de um nó é chamado grau de saída desse nó. Se x pertence à subárvore Tv,
então, x é descendente de v e v é ancestral, ou antecessor, de x. Se neste caso x é diferente de v então x é
descendente próprio de v e v é ancestral próprio de x.
Nó folha e nó interior
Um nó que não possui descendentes próprios é chamado de nó folha, ou seja, um nó folha é aquele
com grau de saída nulo. Um nó que não é folha (isto é, possui grau de saída diferente de zero) é chamado
nó interior ou nó interno.
Grau de uma árvore
Grau de uma árvore é o máximo entre os graus de seus nós.
Floresta
Uma floresta é um conjunto de zero ou mais árvores.
9
Estrutura de Dados
Caminho, comprimento do caminho
Uma seqüência de nós distintos v1, v2, ..., vk, tal que existe sempre entre nós consecutivos ( isto é,
entre v1 e v2, entre v2 e v3, ... , v(k-1) e vk) a relação "é filho de"ou "é pai de" é denominada um caminho
na árvore. Diz-se que v1 alcança vk e que vk é alcançado por v1. Um caminho de vk vértices é obtido pela
sequência de k-1 pares. O valor k-1 é o comprimento do caminho.
Nível (ou profundidade) e altura de um nó
Nível ou profundidade, de um nó é o número de nós do caminho da raiz até o nó.
O nível da raiz, é portanto, 1. A altura de um nó v é o número de nós no maior caminho de v até um de
seus descendentes. As folhas têm altura 1.
Nível da raiz (profundidade) e altura de uma árvore
O nível da raiz é 1 (acima). A altura de uma árvore T é igual ao máximo nível de seus nós.
Representa-se a altura de T por h(T) e a altura da subárvore de raiz v por h(v).
Árvore Ordenada
Uma árvore ordenada é aquela na qual os filhos de cada nó estão ordenados. Assume-se ordenação
da esquerda para a direita. Desse modo, a árvore do primeiro exemplo é ordenada, mas, a árvore abaixo
não.
Árvores Isomorfas
Duas árvores não ordenadas são isomorfas quando puderem se tornar coincidentes através de uma
permutação na ordem das subárvores de seus nós. Duas árvores ordenadas são isomorfas quando forem
coincidentes segundo a ordenação existente entre seus nós.
Árvore Cheia
Uma árvore de grau d é uma árvore cheia se possui o número máximo de nós, isto é, todos os nós
têm número máximo de filhos exceto as folhas, e todas as folhas estão na mesma altura.
10
Estrutura de Dados
Árvore cheia de grau 2: implementação seqüencial.
Árvore Binária
Uma Árvore Binária T é um conjunto finito de elementos denominados nós ou vértices, tal que:
• T = 0 e a árvore é dita vazia ou
• existe um nó especial r, chamado raiz de T, os restantes podem ser divididos em dois
subconjuntos disjuntos, Tre e Trd, que são as subárvores esquerda e direita de r,
respectivamente e as quais, por sua vez, também são árvores binárias.
Árvore Binária de Busca
Uma Árvore Binária de Busca T (ABB) ou Árvore Binária de Pesquisa é tal que ou T = 0 e a
árvore é dita vazia ou seu nó raiz contém uma chave e:
•
Todas as chaves da subárvore esquerda são menores que a chave da raiz.
•
Todas as chaves da subárvore direita são maiores que a chave raiz.
•
As subárvores direita e esquerda são também Árvores Binárias de Busca.
11
Estrutura de Dados
3. Implementação das Estruturas Estáticas
A seguir, faremos a implementação de todas as operações básicas das estruturas de dados vistas na
seção anterior. Primeiramente, serão implementadas as estruturas estáticas, usando vetores. Para estas,
também serão feitos os algoritmos, com o objetivo de facilitar o aprendizado. As estruturas dinâmicas
serão implementadas diretamente na linguagem C, na seção 4.
3.1 Lista Estática Desordenada
Esta estrutura é implementada usando vetores e não se preocupa com ordenação. Os elementos
são colocados na estrutura por ordem de chegada. Nas próximas seções será descrita cada uma das
operações feitas nesta estrutura. Em seguida será apresentado o algoritmo de cada operação e o programa
em C. No exemplo, teremos uma lista com os dados dos alunos de uma turma (para simplificar, cada aluno
tem apenas a matrícula e o nome).
3.1.1 Operações Básicas
Inserir Elemento
A figura abaixo ilustra a inserção de três elementos em uma lista estática desordenada. Inicialmente
o vetor está vazio. O primeiro elemento a chegar é o aluno José com matrícula 256. Este será colocado na
primeira posição do vetor.
12
Estrutura de Dados
Posteriormente, chegam mais dois alunos (Ana com matrícula 132 e Paulo com matrícula 429), que
são colocados nas próximas posições disponíveis do vetor (posição 2 e posição 3). Quando uma inserção
vai ser executada, é necessário verificar se o vetor tem posições disponíveis. Caso contrário, a inserção não
pode ser efetuada.
Consultar Elemento
Depois que um elemento é inserido, a operação mais executada é a consulta. Para a consulta é
necessário saber qual elemento deseja consultar. Neste caso faremos uma consulta por matrícula. Para isso,
a matrícula do aluno a ser consultado deve ser lida. É feita uma “visita” ou “varredura” em todas as
posições ocupadas do vetor, a procura do elemento.
No vetor da figura acima temos seis elementos. Vamos consultar o elemento de matrícula 578. Para
encontrá-lo, temos que varrer o vetor desde o seu início e paramos na posição 4 que é a posição onde ele
se encontra. Caso quiséssemos consultar o elemento de matrícula 192, iríamos varrer todo o vetor,
elemento a elemento e ao chegar na sexta posição (que é a ultima) ficaríamos sabendo que este elemento
não se encontra no vetor. Quando um elemento é encontrado, seus dados são apresentados e quando ele
não está no vetor, uma mensagem de erro deve ser dada ao usuário.
Alterar Elemento
A alteração é importante para o momento que se tenha cadastrado um dado incorretamente ou
mesmo eles sofram uma alteração (exemplo: modificar o telefone do cliente). Para a alterar os dados de um
elemento é necessário saber qual elemento deseja alterar. Neste caso faremos a busca por matrícula. Para
isso, a matrícula do aluno a ser alterado deve ser lida.
13
Estrutura de Dados
É feita a varredura em todas as posições ocupadas do vetor, a procura da matrícula. Assim que o
elemento é encontrado, seus dados devem ser apresentados ao usuário (neste caso a matrícula e o nome).
Dessa forma ele pode verificar se realmente é aquele o elemento a ser alterado, além de informar qual
campo dever ser alterado e qual o novo valor para aquele campo. Quando o elemento não é encontrado,
uma mensagem de erro deve ser dada ao usuário. Caso deseje, assim que os dados forem alterados, o
registro do aluno é apresentado novamente para o usuário. Deve tomar cuidado quando a alteração de um
campo, influencie em outro campo, fazendo-se necessário uma alteração indireta, por exemplo: o professor
cadastrou a nota do aluno incorretamente. A alteração desta nota irá influenciar na média do aluno.
Remover Elemento
Caso um elemento não precise mais fazer parte da estrutura, ele pode ser removido. Para remover
os dados de um elemento é necessário saber qual elemento deseja remover. Já que iremos Neste caso
faremos a busca por matrícula. Para isso, a matrícula do aluno a ser removido deve ser lida. É feita uma
varredura em todas as posições ocupadas do vetor, a procura da matrícula. Assim que o elemento é
encontrado, seus dados devem ser apresentados ao usuário (neste caso a matrícula e o nome). Dessa forma
ele pode verificar se realmente é aquele o elemento a ser removido. Quando o elemento não é encontrado,
uma mensagem de erro deve ser dada ao usuário. Numa lista desordenada, para a remoção ser efetuada, o
último elemento do vetor deve ser transferido para a posição do elemento removido.
Listagem de Todos os Elementos
A operação de listagem possibilita a visualização dos dados de todos os elementos cadastrados. É
feita uma varredura no vetor e todos os dados de todos os elementos são apresentados ao usuário. Caso a
lista esteja vazia, será apresentada uma mensagem.
14
Estrutura de Dados
3.1.2 Algoritmo
INICIO
tipo regaluno = registro
caracter: nome;
inteiro: mat;
real: media;
fimregistro;
tipo vetorturma = vetor [1..50] de regaluno;
vetorturma: turma;
inteiro: op, qa;
módulo inserir;
se (qa = 50) então
escreva(″não pode inserir″);
senão
inicio
qa ← qa + 1;
leia(turma[qa].mat, turma[qa].nome, turma[qa].med);
escreva(″Inserido com sucesso″);
fim;
fimse;
fimmódulo;
módulo procura(inteiro: matprocurada);
inteiro i, p;
p ← 0;
i ← 0;
enquanto (i<qa) e (p=0) faça
i ← i+1;
se (turma[i].mat = matprocurada) então
p ← i;
fimse;
fimenquanto;
retorne(p);
fimmódulo;
módulo consultar;
inteiro: posicao, matcon;
leia(matcon);
posicao ← procura(matcon);
se (posicao <> 0) então
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
senão
escreva(″Matricula não cadastrada″);
fimse;
fimmódulo;
15
Estrutura de Dados
módulo remover;
inteiro: posicao, matrem, confirma;
leia(matrem);
posicao ← procura(matrem);
se (posicao <> 0) então
inicio
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
escreva(″Confirma remoção(1-sim/2-não)?″);
leia(confirma)
se (confirma = 1) então
inicio
turma[posicao] ← turma[qa];
qa ← qa - 1;
escreva(″Removido com Sucesso!″);
fim;
senão
escreva(″Remocao Cancelada″);
fimse;
fim;
senão
escreva(″Matricula nao cadastrada″);
fimse;
fimmódulo;
módulo alterar;
inteiro: posicao, matalt,confirma;
leia(matalt);
posicao ← procura(matalt);
se (posicao <> 0) então
inicio
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
escreva(″Alterar Nome(1-sim/2-não)?″);
leia(confirma)
se (confirma = 1) então
leia(turma[posicao].nome);
fimse;
escreva(″Alterar Media(1-sim/2-não)?″);
leia(confirma)
se (confirma = 1) então
leia(turma[posicao].med);
fimse;
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
escreva(″Alterado com Sucesso!″);
fim;
senão
escreva(″Matricula não cadastrada″);
fimse;
fimmódulo;
16
Estrutura de Dados
módulo listagem;
inteiro: i;
se (qa > 0) então
inicio
escreva(″Matricula
Nome
Media″);
para i de 1 até qa faça
escreva(turma[i].mat, turma[i].nome, turma[i].med);
fimpara;
fim;
senão
escreva(″Turma Vazia″);
fimse;
fimmódulo;
qa ← 0;
repita
escreva(“Informe a opcao desejada(1-inserir/2remover/3-consultar
/4-alterar/5-listagem/0-sair: “);
leia(op);
escolha op
caso 1: inserir;
caso 2: remover;
caso 3: consultar;
caso 4: alterar;
caso 5: listagem;
fimescolha;
até op = 0;
FIM.
3.1.3 Programa em C
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
// Programa para executar funcoes de uma lista estatica desordenada
typedef struct { int mat;
char nome[31];
float media;
}TAlunos;
TAlunos turma[30];
const int maximo= 30;
int qa, op;
//***********************************************************************
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
17
Estrutura de Dados
void cabec()
{ system("cls");
printf("Faculdade Santa Maria - Lista Estatica Desordenada\n");
linha();
}
// modulo que retorna a posicao do elemento procurado
int procura(int procurado)
{ int j, posicao;
posicao = -1;
for(j = 0; j<qa; j++)
{ if (procurado==turma[j].mat)
{ posicao = j;
break;
}
}
return posicao;
}
// modulo para mostrar o elemento na posicao indice
void mostre (int pos)
{ printf("\n\nMatricula
Aluno
Media");
printf("\n--------------------------------------------");
printf("\n%9d
%-20s
%5.2f",
turma[pos].mat, turma[pos].nome, turma[pos].media);
printf("\n--------------------------------------------\n\n");
}
//Inserir novo aluno
void inserir()
{ int cont;
do{ cabec();
printf("\nInserir Novo Aluno\n\n");
if (qa < maximo) // verifica se o vetor pode receber novo aluno
{ printf("\nMatricula do Aluno: ");
scanf("%d",&turma[qa].mat);
printf("\nNome: ");
fflush(stdin);
gets(turma[qa].nome);
printf("\nMedia: ");
scanf("%f",&turma[qa].media);
qa++;
printf("\n\nAluno Inserido com Sucesso!!!\n\n");
}
else // vetor cheio
{ printf("\n\n\aNao Pode Inserir - Turma Cheia!!!\n\n");
getche();
break;
}
printf("\n\nInserir outro(1-sim/2-nao)? ");
scanf("%d",&cont);
}while (cont == 1);
}
18
Estrutura de Dados
//Remover aluno cadastrado
void remover()
{ int matrem, i, cont, achou, conrem;
do{ cabec();
printf("\nRemover Aluno\n\n");
printf("\nMatricula do Aluno: ");
scanf("%d",&matrem);
achou = procura(matrem);
if (achou != -1)
{ mostre(achou);
printf("\nDeseja remover o aluno (1-sim/2-nao)? ");
scanf("%d",&conrem);
if (conrem==1) // verifica se quer remover
{ turma[i]= turma[qa-1];
qa--;
printf("\n\nAluno removido com Sucesso!!!\n");
}
else
printf("\n\n\aO aluno nao foi removido!!!\n");
break;
}
else // aluno nao foi encontrado
printf("\n\naNumero de Matricula Incorreto!!!!!!\n");
printf("\n\nRemover outro(1-sim/2-nao)? ");
scanf("%d",&cont);
}while (cont == 1);
}
//Consultar aluno cadastrado por matricula
void consultarmat()
{ int i, matcon, achou, cont;
do
{ cabec();
printf("\nConsultar Aluno por Matricula\n\n");
printf("\nMatricula do Aluno: ");
scanf("%d",&matcon);
achou = procura(matcon);
if (achou != -1)
mostre(achou);
else // aluno nao foi encontrado
printf("\n\n\aNumero de Matricula Incorreto!!!!!!\n");
printf("\n\nConsultar outro(1-sim/2-nao)? ");
scanf("%d",&cont);
} while (cont == 1);
}
//Alterar dados de aluno cadastrado
void alterar()
{ int achou, i, matalt, conalt, cont;
do
{ cabec();
printf("\nAlterar Dados do Aluno\n\n");
printf("\nMatricula do Aluno: ");
19
Estrutura de Dados
scanf("%d",&matalt);
achou = procura(matalt);
if (achou != -1)
{ mostre(achou);
printf("\nDeseja Alterar o nome do aluno (1-sim/2-nao)? ");
scanf("%d",&conalt);
if (conalt == 1)
{ printf("\n\tNome : ");
fflush(stdin);
gets(turma[achou].nome);
}
printf("\nDeseja Alterar a Media do aluno (1-sim/2-nao)? ");
scanf("%d",&conalt);
if (conalt == 1)
{
printf("\nMedia: ");
scanf("%f",&turma[achou].media);
}
mostre(achou);
printf("\n\nAluno Alterado com Sucesso!!!\n");
}
else // aluno nao foi encontrado
printf("\n\n\aNumero de Matricula Incorreto!!!!!!\n");
printf("\n\nContinuar alterando aluno (1-sim/2-nao)? ");
scanf("%d",&cont);
} while (cont == 1);
}
//Imprimir relatorio com as informaçoes de todos alunos
void listagem()
{ int i;
cabec();
printf("\nRelatorio Geral\n");
printf("\n\nMatricula
Aluno
Media");
printf("\n---------------------------------------------");
for(i = 0; i < qa; i++)
printf("\n%9d
%-20s
%5.2f", turma[i].mat, turma[i].nome,
turma[i].media);
printf("\n---------------------------------------------");
printf("\n\nDigite qualquer tecla para sair... ");
getche();
}
//Programa principal
main()
{ qa =0;
do // tela com o menu do opcoes
{ cabec();
printf("Opcoes:\n\n");
printf("
1- Inserir novo Aluno\n\n");
printf("
2- Remover Aluno\n\n");
printf("
3- Consultar Aluno por Matricula\n\n");
printf("
4- Alterar Dados de Aluno\n\n");
printf("
5- Listagem de Alunos\n\n");
printf("
0- Sair do Programa\n");
20
Estrutura de Dados
linha();
printf("\n
Informe a Opcao desejada: ");
scanf("%d",&op);
switch(op)
{ case 1: inserir(); break;
case 2: remover(); break;
case 3: consultarmat(); break;
case 4: alterar(); break;
case 5: listagem(); break;
case 0: break;
default : printf("\n\a
Opcao Invalida! Tecle enter...");
getche(); break;
}
} while (op != 0);
}
3.2 Lista Estática Ordenada
Nesse tipo de lista, os elementos devem ser colocados na estrutura obedecendo a uma ordenação.
Qualquer operação feita na estrutura, não pode afetar na ordenação da mesma. A vantagem dessa lista será
notada principalmente nos momentos que necessite percorrer a lista a procura de algum elemento.
Aqui o programa anterior é modificado, fazendo com que os alunos sejam armazenados no vetor
por ordem de matrícula.
3.2.1 Operações Básicas
Inserir Elemento
Para inserir um elemento em uma lista ordenada podem ocorrer cinco possibilidades:
1. a lista está cheia:nesse caso a inserção é cancelada;
2. a lista está vazia: o elemento é colocado na primeira posição do vetor;
3. o elemento a ser inserido é menor do que o primeiro da lista;
4. o elemento a ser inserido é maior do que o ultimo da lista;
5. o elemento novo será inserido entre elementos da lista.
A figura a seguir ilustra a inserção de quatro elementos em uma lista estática ordenada. Inicialmente
o vetor está vazio. O primeiro elemento a chegar é o aluno José com matrícula 256. Este será colocado na
primeira posição do vetor. Posteriormente, chega Ana com matrícula 132. Para que a lista fique ordenada,
deve verificar em qual posição o elemento deve ser inserido. Nesse caso, a matrícula 132 é menor que 256
21
Estrutura de Dados
(que é a primeira da lista). Assim, todos os elementos a partir da posição onde o elemento de matrícula 256
se encontra, devem se deslocar uma posição, abrindo espaço para o elemento ser inserido.
Mais tarde chega o elemento de matrícula 429. Esta matrícula é maior do que todas as matrículas do
vetor, portanto, ele é inserido no final do vetor, sem necessidade de deslocamentos. Por fim, chega o
elemento de matrícula 197. Devemos descobrir onde se encontra o primeiro elemento maior do que o que
será inserido, ou seja, seu sucessor imediato. Neste caso, ele deve entrar na posição do elemento de
matrícula 256. O espaço deve ser liberado, fazendo-se necessário o deslocamento de todos os elementos a
partir do elemento de matrícula 256. A principal questão da inserção ordenada é descobrir o local onde o
elemento deve ser inserido e, se necessário, fazer os deslocamentos.
22
Estrutura de Dados
Consultar Elemento
A matrícula do aluno a ser consultado deve ser lida. É feita uma varredura em todas as posições
ocupadas do vetor, a procura da matrícula. No caso de uma lista ordenada, se estivéssemos procurando um
aluno de matrícula 120, assim que fizéssemos a leitura da primeira matrícula do vetor, já saberíamos que a
matrícula 120 não está no vetor, evitando uma varredura até o final do vetor. Na estrutura ordenada, as
consultas são mais eficientes.
Alterar Elemento
A diferença da alteração ordenada e desordenada é que, numa lista ordenada, se o campo que
ordena a lista for alterado, deve verificar se a lista permanece ordenada. Por exemplo, se alterarmos a
matrícula de um aluno, pode ser que a lista fique desordenada. Tem duas soluções - não permitir a
alteração do campo que ordena a lista ou sempre que o campo for alterado é verificada se a lista continua
ordenada, os demais passos para alterar são iguais à lista desordenada.
Remover Elemento
Começamos com a leitura da matrícula do aluno a ser removido. É feita uma varredura em todas as
posições ocupadas do vetor, a procura da matrícula. Assim que o elemento é encontrado, seus dados
devem ser apresentados ao usuário (neste caso a matrícula e o nome). Dessa forma ele pode verificar se
realmente é aquele o elemento a ser removido. Quando o elemento não é encontrado, uma mensagem de
erro deve ser dada ao usuário.
No exemplo da figura a seguir, desejamos remover o elemento de matrícula 256. Para que a lista
fique contínua e ordenada, todos os elementos que vem depois do elemento que será removido, devem ser
trazidos uma posição a frente.
23
Estrutura de Dados
Listagem de Todos os Elementos
A operação de listagem possibilita a visualização dos dados de todos os elementos cadastrados. É
feita uma varredura no vetor e todos os dados de todos os elementos são apresentados ao usuário.
3.2.2 Algoritmo
INICIO
tipo regaluno = registro
caracter: nome;
inteiro: mat;
real: media;
fimregistro;
tipo vetorturma = vetor [1..50] de regaluno;
vetorturma: turma;
inteiro: op, qa;
módulo verificalocal(inteiro: matins);
inteiro i, local;
local ← 0;
se (qa = 0) então
local ← 1;
senão
inicio
se (matins > turma[qa].mat) então
local ← qa + 1;
senão
inicio
local ← 1;
enquanto (turma[local].mat < matins) faça
local ← local + 1;
fimenquanto;
24
Estrutura de Dados
para i de qa até local passo -1 faça
turma[i+1]=turma[i];
fimpara;
fim;
fimse;
fim;
fimse;
retorne (local);
fimmódulo;
módulo inserir;
inteiro: l, matl;
se (qa = 50) então
escreva(″não pode inserir″);
senão
inicio
leia(matl);
l ← verificalocal(matl);
turma[l].mat ← matl;
leia(turma[l].nome, turma[l].med);
qa ← qa + 1;
escreva(″Inserido com sucesso″);
fim;
fimse;
fimmódulo;
módulo procura(inteiro: matprocurada);
inteiro i, p;
p ← 0;
i ← 1;
enquanto (i<=qa) e (p=0) e (turma[i].mat<=matprocurada) faça
se (turma[i].mat = matprocurada) então
p ← i;
fimse;
i ← i+1;
fimenquanto;
retorne(p);
fimmódulo;
módulo consultar;
inteiro: posicao, matcon;
leia(matcon);
posicao ← procura(matcon);
se (posicao <> 0) então
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
senão
escreva(″Matricula não cadastrada″);
fimse;
fimmódulo;
25
Estrutura de Dados
módulo remover;
inteiro: posicao, matrem, confirma, i;
leia(matrem);
posicao ← procura(matrem);
se (posição <> 0) então
inicio
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
escreva(″Confirma remoção(1-sim/2-não)?″);
leia(confirma)
se (confirma = 1) entao
inicio
para i de posicao até qa-1 faça
turma[i] ← turma[i+1];
fimpara;
qa ← qa - 1;
escreva(″Removido com Sucesso!″);
fim
senão
escreva(″Remocao Cancelada″);
fimse;
fim;
senão
escreva(″Matricula não cadastrada″);
fimse;
fimmódulo;
módulo alterar;
inteiro: posicao, matalt,confirma;
leia(matalt);
posicao ← procura(matalt);
se (posicao <> 0) então
inicio
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
escreva(″Alterar Nome(1-sim/2-não)?″);
leia(confirma)
se (confirma = 1) então
leia(turma[posicao].nome);
fimse;
escreva(″Alterar Media(1-sim/2-não)?″);
leia(confirma)
se (confirma = 1) então
leia(turma[posicao].med);
fimse;
escreva(turma[posicao].mat, turma[posicao].nome, turma[posicao].med);
escreva(″Alterado com Sucesso!″);
fim;
senão
escreva(″Matricula não cadastrada″);
fimse;
fimmódulo;
26
Estrutura de Dados
módulo listagem;
inteiro: i;
se (qa > 0) então
inicio
escreva(″Matricula
Nome
Media″);
para i de 1 até qa faça
escreva(turma[i].mat, turma[i].nome, turma[i].med);
fimpara;
fim;
senão
escreva(″Turma Vazia″);
fimse;
fimmódulo;
qa ← 0;
repita
escreva(“Informe a opcao desejada(1-inserir/2remover/3-consultar
/4-alterar/5-listagem/0-sair: “);
leia(op)
escolha op
caso 1: inserir;
caso 2: remover;
caso 3: consultar;
caso 4: alterar;
caso 5: listagem;
fimescolha
ate op = 0;
FIM.
3.2.3 Programa em C
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
// Programa para executar funcoes de uma lista estatica ordenada.
typedef struct { int mat;
char nome[31];
float media;
}TAlunos;
TAlunos turma[30];
TAlunos al;
const int maximo= 30;
int qa, op;
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
27
Estrutura de Dados
void cabec()
{ system("cls");
printf("Faculdade Santa Maria - Lista Estatica Ordenada\n");
linha();
}
// Verificar em que posicao deve ser colocado o novo aluno a ser inserido.
void colocarordem()
{ int i, local;
local = -1;
if (qa==0)
turma[0] = al;
else
{ for (i=0;i<qa;i++)
{ if (al.mat<turma[i].mat)
{ local = i;
break;
}
}
if (local==-1)
turma[qa] = al;
else
{ for (i=qa;i>local;i--)
turma[i]=turma[i-1];
turma[local]=al;
}
}
}
// modulo que retorna a posicao do elemento procurado
int procura(int procurado)
{ int j, posicao;
posicao = -1;
for(j = 0; j<qa; j++)
{ if (procurado==turma[j].mat)
{ posicao = j;
break;
}
else
{ if (procurado<turma[j].mat)
break;
}
}
return posicao;
}
// modulo para mostrar o elemento na posicao indice
void mostre (int indice)
{ printf("\n\nMatricula
Aluno
Media");
printf("\n---------------------------------------------");
printf("\n%9d
%-20s
%5.2f", turma[indice].mat,
turma[indice].nome, turma[indice].media);
printf("\n----------------------------------------------\n\n");
}
28
Estrutura de Dados
// Inserir um novo aluno na escola
void inserir()
{ int cont;
do{ cabec();
printf("\nInserir Novo Aluno\n");
if (qa < maximo) // verifica se o vetor pode receber novo aluno
{ printf("\nMatricula do Aluno: ");
scanf("%d",&al.mat);
printf("\nNome: ");
fflush(stdin);
gets(al.nome);
printf("\nMedia: ");
scanf("%f",&al.media);
colocarordem();
qa++;
printf("\n\nAluno Inserido com Sucesso!!!\n");
}
else // vetor cheio
{ printf("\n\n\aNao Pode Inserir - Turma Cheia!!!\n");
getche();
break;
}
printf("\n\nContinuar inserindo aluno (1-sim/2-nao)? ");
scanf("%d",&cont);
}while (cont == 1);
}
// Remover um aluno da escola
void remover()
{
int matrem, i, achou, continuar, conrem;
do{ cabec();
printf("\nRemover Aluno\n\n");
printf("\nMatricula do Aluno: ");
scanf("%d",&matrem);
achou = procura(matrem);
if (achou!=-1)
{ mostre(achou);
printf("\nDeseja remover o aluno (1-sim/2-nao)? ");
scanf("%d",&conrem);
if (conrem == 1)
{ for (i=achou;i<qa;i++)
turma[i]=turma[i+1];
qa--;
printf("\n\nAluno removido com Sucesso!!!\n");
}
else
printf("\n\n\aO aluno nao foi removido!!!\n");
}
else
printf("\n\n\aNumero de Matricula Incorreto!!!!!!\n");
printf("\n\nContinuar removendo aluno (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
}
29
Estrutura de Dados
//Consultar um aluno da escola
void consultar()
{
int matcon, achou, continuar;
do{ cabec();
printf("\nConsultar Aluno\n\n");
printf("\nMatricula do Aluno: ");
scanf("%d",&matcon);
achou = procura(matcon);
if (achou!=-1)
mostre(achou);
else
printf("\n\n\aNumero de Matricula Incorreto!!!!!!\n");
printf("\n\nContinuar consultando aluno(1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
}
//Fazer alteracao dos dados de um aluno
void alterar()
{
int matalt, achou, conalt, continuar;
do{ cabec();
printf("\nAlterar Dados do Aluno\n\n");
printf("\nMatricula do Aluno: ");
scanf("%d",&matalt);
achou = procura(matalt);
if (achou!=-1)
{ mostre(achou);
printf("\nDeseja Alterar o nome do aluno (1-sim/2-nao)? ");
scanf("%d",&conalt);
if (conalt == 1)
{ printf("\nNome : ");
fflush(stdin);
gets(turma[achou].nome);
}
printf("\nDeseja Alterar a media do aluno (1-sim/2-nao)? ");
scanf("%d",&conalt);
if (conalt == 1)
{
printf("\nMedia: ");
scanf("%f",&turma[achou].media);
}
mostre(achou);
printf("\n\nAluno Alterado com Sucesso!!!\n");
}
else
printf("\n\n\aNumero de Matricula Incorreto!!!!!!\n");
printf("\n\nContinuar alterando aluno(1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
}
30
Estrutura de Dados
//Imprimir o relatorio contendo os dados de todos os alunos
void listagem()
{ int i;
float soma=0;
cabec();
printf("\nRelatorio Geral\n");
printf("\nMatricula
Aluno
Media");
printf("\n--------------------------------------------");
for(i = 0; i<qa; i++)
{ printf("\n%9d
%-20s
%5.2f", turma[i].mat, turma[i].nome,
turma[i].media);
soma += turma[i].media;
}
printf("\n--------------------------------------------");
printf("\n\nMedia da turma = %.2f",soma/qa);
printf("\n\nDigite qualquer tecla para sair");
getche();
}
//Programa principal
main()
{ qa=0;
do
{ cabec();
printf("\n Opcoes: \n\n");
printf("\t1- Inserir novo Aluno\n\n");
printf("\t2- Remover Aluno\n\n");
printf("\t3- Consultar Aluno\n\n");
printf("\t4- Alterar dados de Aluno\n\n");
printf("\t5- Listagem de Alunos\n\n");
printf("\t0- Sair do Programa\n\n\n");
linha();
printf("Informe a Opcao desejada: ");
scanf("%d",&op);
switch(op)
{ case 1: inserir(); break;
case 2: remover(); break;
case 3: consultar(); break;
case 4: alterar(); break;
case 5: listagem(); break;
case 0: break;
default : printf("\nOpcao Invalida! Tecle enter.."); getche(); break;
}
}while(op!=0);
}
31
Estrutura de Dados
3.3 Fila Estática
Nesta seção iremos verificar as operações em uma fila implementada com vetores. As operações
básicas em uma fila: inserir elemento no final da fila, remover o elemento do início da fila, consultar o
primeiro da fila, listar todos oserá implementado simula a fila de atendimento de um banco.
3.3.1 Operações Básicas
Inserir Elemento
Todo elemento que vai ser inserido em uma fila é colocado no final da estrutura. A figura abaixo
ilustra a chegada de três clientes na fila. Os clientes vão sendo inseridos por ordem de chegada.
Consultar Primeiro da Fila
Em uma fila, a consulta é feita apenas do primeiro elemento da fila. Assim, teremos a informação
de qual será o próximo elemento a ser retirado. Na figura abaixo, o primeiro elemento da fila é o cliente
João, com conta número 3456. Quando o vetor estiver vazio, é apresentada uma mensagem de fila vazia ao
usuário.
32
Estrutura de Dados
Remover Primeiro da Fila
Em uma fila, o elemento removido é sempre o que chegou há mais tempo, ou seja, o elemento da
primeira posição do vetor. Na figura abaixo iremos remover o primeiro elemento da fila (neste caso, João).
Os elementos seguintes devem ser deslocados uma posição a frente. Com isso, o segundo elemento da fila
passa a ser o primeiro, o terceiro passa a ser o segundo e assim por diante.
Listagem de Todos os Elementos da Fila
A operação de listagem possibilita a visualização dos dados de todos os elementos da fila. É feita
uma varredura no vetor e todos os dados de todos os elementos são apresentados ao usuário.
3.3.2 Algoritmo
INICIO
tipo regfila = registro
caracter: nome;
inteiro: conta, agencia;
fimregistro;
tipo vetorfila = vetor [1..50] de regfila;
vetorfila: fila;
inteiro: op, qe;
módulo inserir;
se (qe = 50) então
escreva(″Fila cheia - não pode inserir″);
senão
33
Estrutura de Dados
inicio
qe ← qe + 1;
leia(fila[qe].agencia, fila[qe].conta, fila[qe].nome);
escreva(″Inserido com sucesso″);
fim;
fimse;
fimmóodulo;
módulo consultarprimeiro;
se (qe <> 0) então
escreva(fila[1].agencia, fila[1].conta, fila[1].nome);
senão
escreva(″Fila Vazia″);
fimse;
fimmódulo;
módulo removerprimeiro;
inteiro: confirma, i;
se (qe <> 0) então
inicio
escreva(fila[1].agencia, fila[1].conta, fila[1].nome);
escreva(″Confirma remoção(1-sim/2-não)?″);
leia(confirma);
se (confirma = 1) então
inicio
para i de 1 até qe-1 faça
turma[i] ← turma[i+1];
fimpara;
qe ← qe - 1;
escreva(″Removido com Sucesso″);
fim;
senão
escreva(″Remocao Cancelada″);
fimse;
fim;
senão
escreva(″Fila Vazia″);
fimse;
fimmódulo;
módulo listagem;
inteiro: i;
se (qe > 0) então
inicio
escreva(″Agencia
Conta
Nome″);
para i de 1 até qe faça
escreva(fila[i].agencia, fila[i].conta, fila[i].nome);
fimpara;
fim;
senão
escreva(″Fila Vazia″);
fimse;
fimmódulo;
34
Estrutura de Dados
qe ← 0;
repita
escreva(“Informe a opcao desejada(1-inserir/2-remover primeiro
/3-consultar primeiro/4-listagem/0-sair: “);
leia(op);
escolha op
caso 1: inserir;
caso 2: removerprimeiro;
caso 3: consultarprimeiro;
caso 4: listagem;
fimescolha;
até op = 0;
FIM.
3.3.3 Programa em C
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
// Implementação de fila usando vetor
/* Estrutura que será usada para cada elemento da fila */
typedef struct tipo_cliente {
int conta, agencia;
char nome[15];
int tipo;
} TCliente;
TCliente cliente[30];
TCliente cl;
int op, tamfila;
/************************************************************************/
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Banco Poupe Muito - Fila Estatica\n");
linha();
}
/* Funcao para inserir um novo cliente no final da fila */
void inserir ()
{ int continuar;
do{ // leitura dos dados do cliente
35
Estrutura de Dados
cabec();
printf("\n Chegada de novo cliente na fila \n");
printf("\n
Numero da conta: ");
scanf("%d",&cl.conta);
printf("\n
Numero da agencia: ");
scanf("%d",&cl.agencia);
printf("\n
Nome: ");
fflush(stdin);
gets(cl.nome);
printf("\n
Tipo de cliente(1- especial, 2-normal): ");
scanf("%d",&cl.tipo);
// Inserir cliente na fila
if (tamfila <30)
/* Se ainda tem vaga na fila */
{ cliente[tamfila] = cl;
tamfila++;
printf("\n\nInserido com Sucesso!!!!\n\n");
}
else /* Fila cheia*/
printf("\n\nFila cheia, cliente nao inserido!!!!\n\n");
printf("\n Continuar inserindo (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1); // verifica se quer continuar inserindo
}
/* Consultar um primeiro cliente da fila */
void consultarprimeiro()
{ cabec();
printf("\nConsulta primeiro cliente da fila\n");
if (tamfila != 0)
{ printf("\n\nAgencia
Conta
Nome
Tipo\n");
printf("--------------------------------------------------------\n");
printf("%4d
%4d
%-15s
%2d\n",
cliente[0].agencia,cliente[0].conta, cliente[0].nome,
cliente[0].tipo);
printf("--------------------------------------------------------\n");
}
else
printf("\n\nA fila está vazia!!\n\n");
printf("\n\nTecle enter para voltar para o menu\n");
getche();
}
/* remover um cliente da fila */
void retirafila()
{ int i, confrem, continuar;
do{ cabec();
printf("\nRetira primeiro cliente da fila \n");
if (tamfila != 0)
// verifica se tem elementos na fila
{ printf("\n\nAgencia
Conta
Nome
Tipo\n");
printf("---------------------------------------------------\n");
printf("%4d
%4d
%-15s
%2d\n",
cliente[0].agencia, cliente[0].conta, cliente[0].nome,
cliente[0].tipo);
printf("---------------------------------------------------\n");
36
Estrutura de Dados
printf("\n\nconfirma retirada do cliente (1-sim, 2-nao)? ");
scanf("%d",&confrem);
if (confrem ==1) // confirma que quer remover
{ for (i=0; i<tamfila; i++)
cliente[i] = cliente[i+1];
tamfila--;
printf("\n\n Retirado da fila com sucesso!!!!\n\n");
}
else // cancelou a remocao
printf("\n\n Retirada cancelada\n\n");
}
else // fila vazia
printf("\n\nFila vazia!!\n\n");
printf("\n\nDeseja retirar outro cliente(1-sim, 2-nao)? ");
scanf("%d",&continuar);
}while (continuar ==1); // continuar retirando cliente da fila
}
/* Lista todos os clientes da fila */
void listar ()
{
int i;
cabec();
printf("\nListagem de clientes da fila\n");
if (tamfila != 0)
{ printf("\n\nAgencia
Conta
Nome
Tipo\n");
printf("-------------------------------------------------------\n");
for (i=0;i<tamfila;i++)
printf("%4d
%4d
%-15s
%2d\n",
cliente[i].agencia,cliente[i].conta, cliente[i].nome,
cliente[i].tipo);
printf("-------------------------------------------------------\n");
printf("\n\nQuantidade de clientes na fila = %d\n",tamfila);
}
else
printf("\n\n Nao tem nenhum cliente na fila");
printf("\n\n\nTecle enter para voltar para o menu\n");
getche();
}
// Programa principal
main()
{ tamfila= 0;
do { cabec();
printf("\nOpcoes: ");
printf("\n\n
1 - Inserir cliente na fila");
printf("\n\n
2 - Consultar primeiro da fila");
printf("\n\n
3 - Retirar primeiro cliente da fila");
printf("\n\n
4 - Listar todos os clientes da fila");
printf("\n\n
0 - para sair \n");
linha();
printf("\nEntre com a sua opcao: ");
scanf("%d", &op);
/* Le a opcao do usuario */
switch(op)
{ case 1: inserir(); break;
37
Estrutura de Dados
case 2: consultarprimeiro();break;
case 3: retirafila(); break;
case 4: listar(); break;
case 0: break;
default: printf("\nOpcao nao valida");
}
} while (op != 0);
}
3.4 Pilha Estática
A seguir vamos analisar a implementação de pilha estática. Neste exemplo será implementada uma
pilha de livros.
3.4.1 Operações Básicas
Inserir Elemento
Todo elemento que vai ser inserido em uma pilha é colocado no final da estrutura. A figura abaixo
ilustra a chegada de três livros colocados na pilha. Os livros vão sendo inseridos por ordem de chegada.
Consultar Topo da Pilha
Em uma pilha, a consulta é feita apenas do elemento do topo, ou seja o último elemento a ser
inserido. Assim, teremos a informação de qual será o próximo elemento a ser retirado. Na figura abaixo, o
elemento do topo da pilha é o livro de código 4 e título Física, armazenado na posição 3 do vetor. Quando
o vetor estiver vazio, é apresentada uma mensagem de pilha vazia ao usuário.
38
Estrutura de Dados
Remover Topo da Pilha
Em uma pilha, o elemento removido é sempre o que chegou há menos tempo, ou seja, o elemento
da última posição do vetor. Na figura abaixo iremos remover o elemento do topo da pilha (neste caso, o
elemento da posição 3). Não há necessidade de deslocamentos.
Listagem de Todos os Elementos da Pilha
A operação de listagem possibilita a visualização dos dados de todos os elementos da pilha. É feita
uma varredura no vetor e todos os dados de todos os elementos são apresentados ao usuário.
3.4.2 Algoritmo
INICIO
tipo regpilha = registro
caracter: titulo;
inteiro: codigo, editora;
fimregistro;
tipo vetorpilha = vetor [1..50] de regpilha;
vetorpilha: pilha;
inteiro: op, qe;
módulo inserir;
se (qe = 50) então
escreva(″Pilha cheia - não pode inserir″);
senão
inicio
qe ← qe + 1;
39
Estrutura de Dados
leia(pilha[qe].codigo, pilha[qe].editora, pilha[qe].titulo);
escreva(″Inserido com sucesso″);
fim;
fimse;
fimmódulo;
módulo consultartopo;
se (qe <> 0) então
escreva(pilha[qe].codigo, pilha[qe].editora, pilha[qe].titulo);
senão
escreva(″Pilha Vazia″);
fimse;
fimmódulo;
módulo removertopo;
inteiro: confirma;
se (qe <> 0) então
inicio
escreva(pilha[qe].codigo, pilha[qe].editora, pilha[qe].titulo);
escreva(″Confirma remoção(1-sim/2-não)?″);
leia(confirma);
se (confirma = 1) então
inicio
qe ← qe - 1;
escreva(″Removido com Sucesso″);
fim
senão
escreva(″Remocao Cancelada″);
fimse;
fim
senão
escreva(″Pilha Vazia″);
fimse;
fimmódulo;
módulo listagem;
inteiro: i;
se (qe > 0) então
inicio
escreva(″Codigo
Editora
Titulo″);
para i de 1 até qe faça
escreva(pilha[i].codigo, pilha[i].editora, pilha[i].titulo);
fimpara;
fim;
senão
escreva(″Pilha Vazia″);
fimse;
fimmódulo;
qe ← 0;
repita
escreva(“Informe a opcao desejada(1-inserir/2-remover topo
/3-consultar topo/4-listagem/0-sair: “);
40
Estrutura de Dados
leia(op);
escolha op
caso 1: inserir;
caso 2: removertopo;
caso 3: consultartopo;
caso 4: listagem;
fimescolha;
até op = 0;
FIM.
3.4.3 Programa em C
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
// Implementação de pilha usando vetor
/* Estrutura que será usada para cada elemento da pilha */
typedef struct tipo_livro {
int codigo, editora;
char titulo[30];
} TLivro;
TLivro livro[30];
TLivro ll;
int op, tampilha;
/***********************************************************************/
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Pilha de Livros - Estatica\n");
linha();
}
/* Funcao para inserir um novo livro na pilha */
void inserir ()
{ int continuar;
do{ cabec();
printf("\nColocar livro no topo da pilha \n");
printf("\nCodigo do livro: ");
scanf("%d",&ll.codigo);
printf("\nTitulo do Livro: ");
fflush(stdin);
gets(ll.titulo);
printf("\nEditora(1- Campus, 2-Makron Books, 3-Moderna): ");
scanf("%d",&ll.editora);
41
Estrutura de Dados
// Inserir livro na pilha
if (tampilha <30)
/* Se ainda tem vaga na pilha */
{ livro[tampilha] = ll;
tampilha++;
printf("\n\nInserido com Sucesso!!!!\n\n");
}
else /* Pilha cheia*/
printf("\n\nPilha cheia, Livro nao inserido!!!!\n\n");
printf("\n Continuar inserindo (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1); // verifica se quer continuar inserindo livros
}
/* Consultar topo da pilha*/
void consultatopo()
{
cabec();
printf("\nConsulta topo da pilha\n");
if (tampilha != 0)
{
printf("\n\nCod
Titulo
Editora\n");
printf("-----------------------------------------------------\n");
printf("%2d
%-20s
%7d\n", livro[tampilha-1].codigo,
livro[tampilha-1].titulo, livro[tampilha-1].editora);
printf("-----------------------------------------------------\n");
}
else
printf("\n\nA pilha esta vazia!!\n\n");
printf("\n\nTecle enter para voltar para o menu\n");
getche();
}
/* remover um livro da pilha */
void retirapilha()
{ int i, confrem, continuar;
do{ cabec();
printf("\nRetira livro do topo da pilha \n");
if (tampilha != 0)
// verifica se tem elementos na pilha
{ printf("\n\nCodigo
Titulo
Editora\n");
printf("---------------------------------------------------\n");
printf("%6d
%-20s
%7d\n", livro[tampilha-1].codigo,
livro[tampilha-1].titulo, livro[tampilha-1].editora);
printf("---------------------------------------------------\n");
printf("\n\nconfirma retirada do livro (1-sim, 2-nao)? ");
scanf("%d",&confrem);
if (confrem ==1) // confirma que quer remover
{
tampilha--;
printf("\n\n Retirado da Pilha com sucesso!!!!\n\n");
}
else // cancelou a remocao
printf("\n\n Retirada cancelada\n\n");
}
else // pilha vazia
printf("\n\nPilha vazia!!\n\n");
printf("\n\nDeseja retirar outro livro(1-sim, 2-nao)? ");
scanf("%d",&continuar);
42
Estrutura de Dados
}while (continuar ==1); // continuar retirando livro da pilha
}
/* Lista todos os livros da pilha */
void listar ()
{
int i;
cabec();
printf("\nListagem dos livros da pilha\n");
if (tampilha != 0)
{
printf("\n\nCodigo
Titulo
Editora\n");
printf("-----------------------------------------------------\n");
for (i=tampilha-1;i>=0;i--)
printf("%6d
%-20s
%7d\n", livro[i].codigo,
livro[i].titulo, livro[i].editora);
printf("-----------------------------------------------------\n");
printf("\n\nQuantidade de livros na pilha = %d\n",tampilha);
}
else
printf("\n\n Nao tem nenhum livro na pilha");
printf("\n\n\nTecle enter para voltar para o menu\n");
getche();
}
// Programa principal
main()
{ tampilha= 0;
do { cabec();
printf("\nOpcoes: \n");
printf("\n
1 - Inserir livro na pilha");
printf("\n
2 - Consultar topo da pilha");
printf("\n
3 - Retirar livro do topo");
printf("\n
4 - Listar todos os livros da pilha");
printf("\n
0 - Sair \n");
linha();
printf("\nEntre com a sua opcao: ");
scanf("%d", &op);
/* Le a opcao do usuario */
switch(op)
{ case 1: inserir(); break;
case 2: consultatopo();break;
case 3: retirapilha(); break;
case 4: listar(); break;
case 0: break;
default: printf("\n\n Opcao invalida"); getche(); break;
}
} while (op != 0);
}
43
Estrutura de Dados
4. Implementação das Estruturas Dinâmicas
A seguir, todos os programas das estruturas de dados feitos na seção anterior serão implementados
utilizando alocação dinâmica (ponteiros). Quando alocamos espaço de memória de forma dinâmica, temos
as seguintes vantagens: programas mais rápidos e uso eficiente da memória. No caso das estruturas
dinâmicas, a implementação será mostrada diretamente na linguagem C.
4.1 Alocação Dinâmica
Ponteiros
Ponteiros são variáveis que armazenam um endereço de memória. Se uma variável contém o
endereço de outra, então a primeira (o ponteiro) aponta para a segunda.
int a,*x;
x = &a;
O ‘*’significa que esta sendo declarado o ponteiro x.
O ponteiro "x" aponta para o "inteiro" a, ou seja, ele armazena o endereço de memória da variável a.
Operadores
•
& (E comercial) fornece o endereço de determinada variável. Atribui o endereço de uma variável
para um ponteiro.
•
* (Asterístico) que acessa o conteúdo de uma variável, cujo endereço é o valor do ponteiro. Não
confundir com o operador aritmético de multiplicação de mesmo símbolo. Devolve o valor
endereçado pelo ponteiro.
main()
{ int *pont, cont, valor;
cont = 100;
pont = &cont;
valor = *pont;
printf("%d",valor);
/* 100 */
}
main()
{ int x,y,*px,*py;
x = 100;
px = &x;
// px tem o endereco de x
44
Estrutura de Dados
py = px;
// py tem o endereco de x
y = *py;
// y = 100, pois recebe o valor de x através de py
printf("%d %d",x,y);
}
Simule a execução dos programas abaixo:
#include <stdio.h>
main()
{ int i,k,*pi,*pk;
i = 2; k = 0;
pk = &k;
pi = &i;
*pk = i;
// variável apontada por pk recebe o valor de i
printf("para *pk = i, temos k= %d\n",k);
k = *pi;
printf("para k = *pi, temos k= %d\n",k);
scanf("%c",&a);
}
#include <stdio.h>
main()
{ int x,y,*px,*py;
printf("Digite um valor: ");
scanf("%d",&x);
px = &x;
y = *px;
printf("digitou= %d e y= %d\n",x,y);
*px = 8;
printf("valor mudou para %d\n",x);
}
Funções malloc e free
As funções malloc() e free() permitem que utilizemos a área de memória livre para criar nossas
variáveis. As variáveis serão criadas em tempo de execução.
A função malloc() aloca memória e tem esse protótipo:
ponteiro = malloc(numero_de_bytes);
– O numero_de_bytes é a quantidade de memória que deseja alocar;
– A função malloc() retorna um ponteiro para a primeira área livre;
– A função malloc faz parte a biblioteca stdlib.h
int *p;
p = malloc(10000);
45
Estrutura de Dados
A função free() desaloca memória e tem esse protótipo:
free(ponteiro);
Ponteiro para registros
typedef struct { int mat;
char nome[15];
}TAluno;
Declaração do ponteiro para registro
TAluno *pa1 = NULL, *pa2 = NULL;
Alocação de memória para um registro
pa2 = (TAluno *)malloc(sizeof(TAluno));
Atribuição a um campo do registro
pa2->mat = 3;
for (i=0;i<=14;i++)
pa2->nome[i] =nomel[i];
Liberar memória de endereço pa2
free(pa2);
4.2 Lista Dinâmica Desordenada
Esta lista é implementada usando ponteiros. A memória para armazenar os dados é alocada em
tempo de execução. Na próxima seção será descrito o funcionamento de cada uma das operações e na
seção 4.2.2 temos o código de um programa completo que faz o cadastro dos alunos de uma turma em
uma lista usando ponteiros. Esta lista possui dois ponteiros, um que guarda o endereço do primeiro
elemento da lista (início) e outro que guarda o endereço do último elemento da lista (fim).
46
Estrutura de Dados
4.2.1 Operações Básicas
Inserir Elemento
A figura abaixo ilustra a inserção de três elementos em uma lista dinâmica desordenada.
Inicialmente a lista está vazia, portanto o valor do ponteiro início e fim é NULL (passo 1). Quando um
elemento vai ser inserido, a memória é alocada e os dados são armazenados (passo 2). Todo nó criado em
uma lista dinâmica desordenada, não tem vizinho seguinte, por isso ele aponta para NULL. Na inserção do
primeiro elemento, os ponteiros início e fim apontam para este elemento (no exemplo, endereço 1010).
No passo 3 temos a chegada de um outro elemento. A memória é alocada e o novo nó tem os
dados preenchidos e tem que ser anexado aos outros nós da lista. Todo nó que chega aponta para NULL e
o ponteiro fim passa a ter o endereço do nó que acabou de chegar. O nó que anteriormente era o último da
lista(1010) passará a ter como vizinho o nó que acabou de chegar (ou seja, aponta para 1040).
O passo 4 mostra uma outra inserção de nó. Veja que a cada novo elemento, apenas o endereço do
ponteiro fim é modificado. O ponteiro início permanece com o mesmo valor.
47
Estrutura de Dados
Consultar Elemento
Para fazer uma consulta em uma lista dinâmica é necessário saber qual elemento deseja consultar.
Neste caso faremos uma consulta por matrícula. Um ponteiro auxiliar será usado para percorrer a lista,
visitando cada nó a procura do elemento.
Na figura acima temos uma lista com três elementos. Caso quiséssemos consultar o elemento de
matrícula 25, iríamos percorrer a lista até chegar no último nó, cujo endereço do vizinho é NULL (nó de
endereço 1080) e ficaríamos sabendo que este elemento não se encontra na lista. Quando um elemento é
encontrado, seus dados são apresentados e quando ele não está na lista, uma mensagem de erro deve ser
dada ao usuário.
Remover Elemento
Para a remover um elemento é necessário saber qual elemento deseja remover. Para isso, a
matrícula do aluno a ser removido deve ser lida. É feita uma varredura em todos os nós da lista. Assim que
o elemento é encontrado, seus dados devem ser apresentados ao usuário (neste caso a matrícula e o nome).
Dessa forma ele pode verificar se realmente é aquele o elemento a ser removido. Quando o elemento não é
encontrado, uma mensagem de erro deve ser dada ao usuário.
Na figura a seguir são ilustrados os três casos de remoção: remover primeiro da lista, último da lista,
elemento no meio da lista. No passo 1 temos a lista com cinco elementos. Primeiramente será feita a
remoção do aluno com matrícula 10. Este é o primeiro nó da lista. Esta remoção é feita modificando o
valor do nó início para o endereço do vizinho do nó que está sendo removido, neste caso, endereço 1040
(Passo 2).
Em seguida será removido a aluno de matrícula 17. Este aluno é o ultimo nó da lista, a sua remoção
irá ter que atualizar o ponteiro fim. Além disso o elemento que tinha como vizinho seguinte o nó de
matrícula 17, terá agora NULL como vizinho. Portanto, dois ponteiros são atualizados (Passo 3).
No passo 4 será feita a última remoção, aluno com matrícula 14 (endereço 1050), que está
armazenado em um nó no meio da lista. Nesta remoção, os ponteiros início e fim não são alterados. No
entanto, o elemento que vem antes do removido (1040), terá agora como vizinho o elemento que era
vizinho do que será removido (1070).
48
Estrutura de Dados
Listagem de Todos os Elementos
A operação de listagem possibilita a visualização dos dados de todos os elementos cadastrados. É
feita uma varredura na lista partindo do endereço início até o último nó, todos os dados de todos os
elementos são apresentados ao usuário.
4.2.2 Programa em C
#include
#include
#include
// Lista
<stdio.h>
<conio.h>
<stdlib.h>
desordenada usando ponteiro - alocacao dinamica
typedef struct tipo_aluno {
int mat;
char nome[20];
struct tipo_aluno *prox;
} TAluno;
49
Estrutura de Dados
TAluno *inicio = NULL;
TAluno *fim = NULL;
TAluno *noatual;
int op, qa;
/*****************************************************************/
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Faculdade Santa Maria - Lista Dinamica Desordenada\n");
linha();
}
/* Funcao para inserir um novo no, ao final da lista */
void inserir ()
{
TAluno *novono;
int i, matl, continuar;
char nomel[20];
do{ cabec();
printf("\n Inserir novo aluno \n");
printf("\n Matricula: ");
scanf("%d",&matl);
printf("\n Nome: ");
fflush(stdin);
gets(nomel);
fflush(stdin);
qa++;
//Aloca memoria para o novo aluno e coloca os dados
novono = (TAluno *)malloc(sizeof(TAluno));
novono->mat = matl;
for (i=0;i<=19;i++)
novono->nome[i] =nomel[i];
novono->prox = NULL;
// Inserir novono na lista de alunos
if (inicio == NULL)
{ inicio = novono;
fim = novono;
}
else
{ fim->prox = novono;
fim = novono;
}
printf("\n\nInserido com Sucesso!!!!\n");
printf("\nContinuar inserindo (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
}
50
Estrutura de Dados
/* Consultar um aluno na lista */
void consultar()
{
int matc, continuar, achou=0;
do{ cabec();
printf("\nConsulta aluno pelo numero de matricula\n\n");
printf("\nMatricula: ");
scanf("%d",&matc);
noatual = inicio;
while(noatual != NULL)
{ if (noatual->mat == matc)
{ achou = 1;
printf("\n\nMatricula Nome\n");
printf("---------------------------------------\n");
printf("%9d
%-20s\n",noatual->mat, noatual->nome);
printf("---------------------------------------\n");
break;
}
else
noatual = noatual->prox;
}
if (achou == 0)
printf("\n\nAluno nao encontrado!!\n");
printf("\nContinuar consultando (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
}
/* remover um aluno da lista */
void remover()
{ TAluno *noantrem;
int matr, confrem, continuar, achou;
do{ achou = 0;
cabec();
printf("\nRemove aluno \n\n");
printf("\nMatricula: ");
scanf("%d",&matr);
noatual = inicio;
while(noatual != NULL)
{
if (noatual->mat == matr)
{ achou = 1;
printf("\n\nMatricula Nome\n");
printf("---------------------------------------\n");
printf("%9d
%-20s\n",noatual->mat, noatual->nome);
printf("---------------------------------------\n");
printf("\n\nDeseja remover o aluno (1-sim, 2-nao)? ");
scanf("%d",&confrem);
if (confrem ==1)
{
if (noatual == inicio)
inicio = inicio->prox;
else
{ noantrem->prox=noatual->prox;
if (noatual == fim)
fim=noantrem;
51
Estrutura de Dados
}
qa--;
free(noatual);
printf("\n\nRemovido com sucesso!!!!\n");
}
else
printf("\n\nRemocao cancelada\n");
break;
}
else
{ noantrem = noatual;
noatual = noatual->prox;
}
}
if (achou == 0)
printf("\n\nAluno nao encontrado!!\n");
printf("\n\nDeseja remover outro (1-sim, 2-nao)? ");
scanf("%d",&continuar);
}while (continuar ==1);
}
/* Lista todos os alunos presentes na lista */
void listar ()
{
noatual = inicio;
cabec();
printf("\nListagem de Alunos\n\n");
if (qa != 0)
{ printf("\n\nMatricula Nome\n");
printf("---------------------------------------\n");
while( noatual != NULL)
{
printf("%9d
%-20s\n",noatual->mat, noatual->nome);
noatual = noatual->prox;
}
printf("---------------------------------------\n");
printf("\n\nQuantidade de Alunos = %d\n",qa);
}
else
printf("\n\n Nao tem nenhum aluno cadastrado");
printf("\n\n\nTecle enter para voltar para o menu\n");
getche();
}
//Programa Principal
main()
{ qa = 0;
do
{ cabec();
printf("\n Opcoes: \n\n");
printf("\t1- Inserir novo Aluno\n\n");
printf("\t2- Remover Aluno\n\n");
printf("\t3- Consultar Aluno\n\n");
printf("\t4- Listagem de Alunos\n\n");
printf("\t0- Sair do Programa\n\n\n");
linha();
52
Estrutura de Dados
printf("Informe a Opcao desejada: ");
scanf("%d",&op);
switch(op)
{ case 1: inserir(); break;
case 2: remover(); break;
case 3: consultar(); break;
case 4: listar(); break;
case 0: break;
default : printf("\nOpcao Invalida!
break;
}
}while(op!=0);
noatual = inicio;
while (noatual != NULL)
{ inicio = noatual->prox;
free(noatual);
noatual = inicio;
}
}
Tecle
enter...");
getche();
4.3 Lista Dinâmica Ordenada
Esta lista é implementada usando ponteiros, no entanto, quando for feito o caminhamento pelos
nós da lista, ela deve estar ordenada por algum campo, neste exemplo o campo de ordenação é a matrícula.
Esta lista possui apenas o ponteiro início, que guarda o endereço do primeiro elemento da lista.
4.3.1 Operações Básicas
Inserir Elemento
Na figura é ilustrada a inserção de quatro elementos em uma lista dinâmica ordenada. No passo 1 a
lista está vazia, com o ponteiro início apontando para NULL. No passo 2 temos a inserção do elemento de
matrícula 17. Como a lista está vazia, o ponteiro início vai apontar para este elemento (endereço 1080).
No passo 3 temos a chegada de um outro elemento, matrícula 10. É verificado que ele tem a
matrícula menor do que o primeiro elemento da lista, então este novo elemento terá que ser inserido no
início da lista. Assim, o elemento novo vai apontar para o primeiro da lista e o ponteiro início irá apontar
para o novo nó.
Em seguida, teremos a inserção de um aluno com matrícula 14, que será inserido no meio da lista.
Para isso, teremos que descobrir entre quais elementos ele irá ser inserido, para manter a lista ordenada e
fazer as ligações dos ponteiros corretamente.
53
Estrutura de Dados
Finalmente, no passo 5 teremos a inserção do aluno com matrícula 22. Esse será inserido no final
da lista.
Consultar Elemento
Para fazer uma consulta é necessário primeiro saber qual elemento deseja consultar. Um ponteiro
auxiliar será usado para percorrer a lista, visitando cada nó a procura do elemento.
Na figura acima temos uma lista com quatro elementos. Caso quiséssemos consultar o elemento de
matrícula 25, iríamos percorrer a lista até chegar no último nó, cujo endereço do vizinho é NULL (nó de
endereço 1040) e ficaríamos sabendo que este elemento não se encontra na lista. Se procurássemos a
matrícula 8, assim que fosse feita a comparação com o primeiro elemento da lista, já saberíamos que a
matricula 8 não se encontra na lista e a consulta é finalizada. A busca é executada enquanto não encontra o
elemento procurado ou enquanto não encontra um elemento cuja matrícula é maior do que a matrícula que
está sendo procurada.
54
Estrutura de Dados
Remover Elemento
A remoção em uma lista dinâmica ordenada segue a mesma regra de uma lista desordenada. A única
diferença é que não teremos o ponteiro fim para atualizar. Para remover um elemento é necessário saber
qual elemento deseja remover. Para isso, a matrícula do aluno a ser removido deve ser lida. É feita uma
varredura em todos os nós da lista. Assim que o elemento é encontrado, seus dados devem ser
apresentados ao usuário (neste caso a matrícula e o nome). Quando o elemento não é encontrado, uma
mensagem de erro deve ser dada ao usuário.
Na figura a seguir são ilustrados os dois casos de remoção: primeiro da lista e meio ou fim da lista.
Quando o primeiro elemento da lista é removido, passo 2, o endereço do início precisa ser atualizado. No
passo 3 o elemento a ser removido é o último da lista. Neste caso, o elemento que apontava para o
elemento removido (1080), terá que apontar para o elemento que o elemento removido aponta (NULL).
Listagem de Todos os Elementos
A operação de listagem possibilita a visualização dos dados de todos os elementos cadastrados. É
feita uma varredura na lista partindo do endereço início até o último nó, todos os dados de todos os
elementos são apresentados ao usuário.
55
Estrutura de Dados
4.3.2 Programa em C
#include
#include
#include
// Lista
<stdio.h>
<conio.h>
<stdlib.h>
ordenada usando ponteiro - alocacao dinamica
/* Estrutura que será usada para criar os nós da lista */
typedef struct tipo_aluno { int mat;
char nome[15];
struct tipo_aluno *prox;
} TAluno;
TAluno *inicio = NULL; /* Ponteiro para a inicio da lista */
TAluno *noatual;
/* Ponteiro a ser usado para percorrer a lista*/
int op, qa;
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Faculdade Santa Maria - Lista Dinamica Ordenada\n");
linha();
}
/* Funcao para inserir um novo no, ao final da lista */
void inserir ()
{
TAluno *novono, *antinserido;
int i, matl,continuar;
char nomel[15];
do{ cabec();
printf("\nInserir novo aluno \n");
printf("\nMatricula: ");
scanf("%d",&matl);
fflush(stdin);
printf("\nNome: ");
gets(nomel);
qa++;
//Aloca memoria para o novo aluno e coloca os dados
novono = (TAluno *) malloc(sizeof(TAluno));
novono->mat = matl;
for (i=0;i<=14;i++)
novono->nome[i] =nomel[i];
antinserido = NULL;
// Inserir novono na lista de alunos
if (inicio == NULL)
/* Ainda nao existe nenhum aluno na lista */
{ inicio = novono;
novono->prox = NULL;
}
56
Estrutura de Dados
else
{
noatual = inicio;
if (noatual->mat > matl) // aluno inserido no inicio da lista
{ novono->prox = inicio;
inicio = novono;
}
else // aluno sera inserido no meio ou final da lista
{
while(noatual != NULL)
{ if (noatual->mat < matl) // procura o local da insercao
{ antinserido = noatual;
noatual = noatual->prox;
}
else // encontrou o local onde sera inserido
noatual = NULL;
}
novono->prox = antinserido->prox;
antinserido->prox = novono;
}
}
printf("\n\nInserido com Sucesso!!!!\n");
printf("\nContinuar inserindo (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1); // verifica se quer continuar removendo
}
/* Consultar um aluno na lista */
void consultar()
{
int matc, continuar, achou=0;
do{ cabec();
printf("\nConsulta aluno pelo numero de matricula\n\n");
printf("Matricula: ");
scanf("%d",&matc);
noatual = inicio;
// coloca ponteiro no inicio da lista
while(noatual != NULL)
// percorre a lista procurando o aluno
{ if (noatual->mat == matc) // aluno encontrado
{ achou = 1;
printf("\n\nMat Nome
\n");
printf("----------------------------\n");
printf("%2d
%-15s\n", noatual->mat, noatual->nome);
printf("----------------------------\n");
break;
}
else // procura no proximo aluno
{ noatual = noatual->prox;
if (noatual != NULL)
{ if (noatual->mat > matc)
break;
}
}
}
if (achou == 0) // aluno nao esta na lista
printf("\n\nAluno nao encontrado!!\n\n");
printf("\nContinuar consultando (1-sim/2-nao)? ");
scanf("%d",&continuar);
57
Estrutura de Dados
}while (continuar == 1);
}
/* remover um aluno da lista */
void remover()
{ TAluno *noantrem;
int matr, confrem, continuar, achou;
do{ achou = 0;
cabec();
printf("\nRemove aluno \n\n");
printf("Matricula: ");
scanf("%d",&matr);
noatual = inicio;
//ponteiro que ira percorrer a lista
while(noatual != NULL)
// percorre a lista a procura do aluno
{
if (noatual->mat == matr) // verifica se é o aluno
{ achou = 1;
// impressao dos dados do aluno para conferencia
printf("\n\nMatricula Nome\n");
printf("----------------------------------------\n");
printf("%9d
%-15s\n", noatual->mat, noatual->nome);
printf("----------------------------------------\n");
printf("\n\nDeseja remover o aluno (1-sim, 2-nao)? ");
scanf("%d",&confrem);
if (confrem ==1) // confirma que quer remover
{ if (noatual == inicio) // verifica se é o primeiro da lista
inicio = inicio->prox;
else // removido esta no meio ou final da lista
noantrem->prox=noatual->prox;
// atualiza a quatidade de alunos e reprovados ou aprovados
qa--;
free(noatual); // libera memoria do no removido
printf("\n\n Removido com sucesso!!!!\n");
}
else // cancelou a remocao
printf("\n\n Remocao cancelada\n");
break;
}
else // passa para o proximo no para continuar a busca
{ noantrem = noatual;
noatual = noatual->prox;
if (noatual !=NULL)
{ if (noatual->mat > matr)
break;
}
}
}
if (achou == 0) // o elemento nao foi encontrado na lista
printf("\n\nAluno nao encontrado!!\n\n");
printf("\n\nDeseja remover outro (1-sim, 2-nao)? ");
scanf("%d",&continuar);
}while (continuar ==1); // continuar removendo aluno
}
58
Estrutura de Dados
/* Lista todos os alunos presentes na lista */
void listar ()
{
noatual = inicio; // no auxiliar marca o inicio da lista
cabec();
printf("\nListagem de Alunos\n\n");
if (qa != 0) // verifica se tem aluno cadastrado
{ printf("\n\nMatricula Nome\n");
printf("----------------------------------------\n");
while( noatual != NULL) // percorre toda a lista ate chegar no final
{ printf("%9d
%-15s\n", noatual->mat, noatual->nome);
noatual = noatual->prox; // Faz noatual apontar para o proximo no
}
printf("----------------------------------------\n");
printf("\n\nQuantidade de Alunos: %d\n",qa);
}
else
printf("\n\nNao tem nenhum aluno cadastrado");
printf("\n\nTecle enter para voltar para o menu...");
getche();
}
// Programa principal
main()
{
qa = 0;
do { cabec();
printf("\nOpcoes: \n\n");
printf("
1 - Inserir novo aluno\n");
printf("
2 - Consultar aluno\n");
printf("
3 - Remover aluno\n");
printf("
4 - Listar todos os alunos\n");
printf("
0 - para sair \n\n");
printf("Entre com a sua opcao: ");
scanf("%d", &op);
/* Le a opcao do usuario */
switch(op)
{ case 1: inserir(); break;
case 2: consultar();break;
case 3: remover(); break;
case 4: listar(); break;
case 0: break;
default: printf("\n\n Opcao invalida"); getche(); break;
}
fflush(stdin);
/* Limpa o buffer de entrada */
} while (op != 0);
/* Desaloca a memoria alocada para os elementos da lista */
noatual = inicio;
while (noatual != NULL)
{ inicio = noatual->prox;
free(noatual);
noatual = inicio;
}
}
59
Estrutura de Dados
4.4 Lista Duplamente Encadeada Ordenada
Nessa lista teremos dois ponteiros em cada nó. Um que irá armazenar o endereço do nó anterior e
o outro pra armazenar o endereço do nó posterior. Dessa forma, as consultas serão melhoradas e podemos
percorrer a lista da esquerda para direita e da direita para esquerda.
4.4.1 Operações Básicas
Inserir Elemento
Na figura é ilustrada a inserção de três elementos em uma lista duplamente encadeada ordenada.
No passo 1 a lista está vazia, com o ponteiro início apontando para NULL. No passo 2 temos a inserção
do elemento de matrícula 17. Como a lista está vazia, o ponteiro início vai apontar para este elemento
(endereço 1080). Este nó não tem vizinhos, por isso os seus ponteiros apontam para NULL.
No passo 3 temos a chegada de um outro elemento, matrícula 10. É verificado que ele tem a
matrícula menor do que o primeiro elemento da lista, então este novo elemento terá que ser inserido no
início da lista. Assim, o elemento novo vai apontar para o primeiro da lista e o ponteiro início irá apontar
para o novo nó e o elemento que era o primeiro da lista, terá o elemento novo como vizinho anterior.
Em seguida, teremos a inserção de um aluno com matrícula 14, que será inserido no meio da lista.
Para isso, teremos que descobrir entre quais elementos ele irá ser inserido, para manter a lista ordenada e
fazer as ligações dos ponteiros corretamente.
60
Estrutura de Dados
Consultar Elemento
Para fazer uma consulta é necessário primeiro saber qual elemento deseja consultar. Um ponteiro
auxiliar será usado para percorrer a lista, visitando cada nó a procura do elemento. A consulta é similar a
consulta em uma lista de encadeamento simples.
Remover Elemento
Para remover um elemento é necessário saber qual elemento deseja remover. Para isso, a matrícula
do aluno a ser removido deve ser lida. É feita uma varredura em todos os nós da lista. Assim que o
elemento é encontrado, seus dados devem ser apresentados ao usuário (neste caso a matrícula e o nome).
Quando o elemento não é encontrado, uma mensagem de erro deve ser dada ao usuário.
Na figura a seguir será ilustrada a remoção do primeiro elemento da lista (matrícula 10). Quando o
primeiro elemento da lista é removido, passo 2, o endereço do início precisa ser atualizado. Além disso, o
segundo elemento da lista (matrícula 14), passará a ser o primeiro e por isso, não terá mais vizinho anterior.
Listagem de Todos os Elementos
A operação de listagem possibilita a visualização dos dados de todos os elementos cadastrados. É
feita uma varredura na lista partindo do endereço início até o último nó, todos os dados de todos os
elementos são apresentados ao usuário.
4.4.2 Programa em C
#include
#include
#include
// Lista
<stdio.h>
<conio.h>
<stdlib.h>
duplamente encadeada - alocacao dinamica
typedef struct tipo_aluno {
int mat;
char nome[15];
float m;
61
Estrutura de Dados
struct tipo_aluno *ant, *prox;
} TAluno;
TAluno *inicio = NULL; /* Ponteiro para a inicio da lista */
TAluno *noatual;
/* Ponteiro a ser usado para percorrer a lista*/
int op, qa;
/*************************************************************************/
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Faculdade Santa Maria - Lista Duplamente Encadeada Ordenada\n");
linha();
}
/* Funcao para inserir um novo no, ao final da lista */
void inserir ()
{
TAluno *novono, *antinserido;
int i, matl, continuar;
float ml;
char st, nomel[15];
do{ cabec();
printf("\n Inserir novo aluno \n");
printf("\n Matricula: ");
scanf("%d",&matl);
printf("\n Nome: ");
fflush(stdin);
gets(nomel);
printf("\n media: ");
scanf("%f",&ml);
qa++;
//Aloca memoria para o novo aluno e coloca os dados
novono = (TAluno *) malloc(sizeof(TAluno));
novono->mat = matl;
for (i=0;i<=14;i++)
novono->nome[i] =nomel[i];
novono->m = ml;
antinserido = NULL;
// Inserir novono na lista de alunos
if (inicio == NULL)
/* Ainda nao existe nenhum aluno na lista */
{ inicio = novono;
novono->prox = NULL;
novono->ant = NULL;
}
else // ja existem alunos na lista
{
noatual = inicio;
if (noatual->mat > matl) // aluno sera inserido no inicio
62
Estrutura de Dados
{ novono->prox = inicio;
novono->ant = NULL;
inicio->ant = novono;
inicio = novono;
}
else // aluno sera inserido no meio ou final da lista
{
while(noatual != NULL)
{ if (noatual->mat < matl) // procura o local da insercao
{ antinserido = noatual;
noatual = noatual->prox;
}
else // encontrou o local onde sera inserido
break;
}
novono->prox = antinserido->prox;
novono->ant = antinserido;
antinserido->prox = novono;
if (noatual != NULL)
noatual->ant = novono;
}
}
printf("\n\nInserido com Sucesso!!!!\n\n");
printf("\n Continuar inserindo (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1); // verifica se quer continuar removendo
}
/* Consultar um aluno na lista */
void consultar()
{ int matc, continuar, achou=0;
do{ cabec();
printf("\nConsulta aluno pelo numero de matricula\n\n");
printf("\nMatricula: ");
scanf("%d",&matc);
noatual = inicio;
// coloca ponteiro no inicio da lista
while(noatual != NULL)
// percorre a lista procurando o aluno
{ if (noatual->mat == matc) // aluno encontrado
{ achou = 1;
printf("\n\nMat Nome
Media\n");
printf("-----------------------------------------\n");
printf("%2d
%-15s
%5.2f\n",
noatual->mat, noatual->nome,noatual->m);
printf("-----------------------------------------\n");
break;
}
else // procura no proximo aluno
{ noatual = noatual->prox;
if (noatual != NULL)
{ if (noatual->mat > matc)
break;
}
}
}
63
Estrutura de Dados
}
if (achou == 0) // aluno nao esta na lista
printf("\n\nAluno nao encontrado!!\n\n");
printf("\nContinuar consultando (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
/* remover um aluno da lista */
void remover()
{ TAluno *noantrem, *noposrem;
int matr, confrem, continuar, achou;
do{ achou = 0;
cabec();
printf("\nRemove aluno \n\n");
printf("\nMatricula: ");
scanf("%d",&matr);
noatual = inicio;
//ponteiro que ira percorrer a lista
while(noatual != NULL)
// percorre a lista a procura do aluno
{
if (noatual->mat == matr) // verifica se é o que deseja remover
{ achou = 1;
// impressao dos dados do aluno para conferencia
printf("\n\nMat Nome
Media\n");
printf("---------------------------------------\n");
printf("%2d
%-15s
%5.2f\n",
noatual->mat, noatual->nome,noatual->m);
printf("---------------------------------------\n");
printf("\n\nDeseja remover o aluno (1-sim, 2-nao)? ");
scanf("%d",&confrem);
if (confrem ==1) // confirma que quer remover
{
if (noatual == inicio) // verifica se é o primeiro da lista
{
inicio = inicio->prox;
inicio->ant = NULL;
}
else // removido esta no meio ou final da lista
{
noantrem->prox=noatual->prox;
noposrem= noatual->prox;
if (noposrem != NULL)
noposrem->ant = noantrem;
}
// atualiza a quatidade de alunos e reprovados ou aprovados
qa--;
free(noatual); // libera memoria do no removido
printf("\n\n Removido com sucesso!!!!\n\n");
}
else // cancelou a remocao
{
printf("\n\n Remocao cancelada\n\n");
}
break;
}
64
Estrutura de Dados
else // passa para o proximo no para continuar a busca
{ noantrem = noatual;
noatual = noatual->prox;
if (noatual !=NULL)
if (noatual->mat > matr)
break;
}
}
if (achou == 0) // o elemento nao foi encontrado na lista
printf("\n\nAluno nao encontrado!!\n\n");
printf("\n\nDeseja remover outro (1-sim, 2-nao)? ");
scanf("%d",&continuar);
}while (continuar ==1); // continuar removendo aluno
}
/* Lista todos os alunos presentes na lista */
void listar ()
{
noatual = inicio; // no auxiliar marca o inicio da lista
cabec();
printf("\nListagem de Alunos\n\n");
if (qa != 0) // verifica se tem aluno cadastrado
{ printf("\n\nMat Nome
Media\n");
printf("-----------------------------------------\n");
while( noatual != NULL)
{ printf("%2d
%-15s
%5.2f\n", noatual->mat,
noatual->nome,noatual->m);
noatual = noatual->prox; // Faz noatual apontar para o proximo no
}
printf("-----------------------------------------\n");
printf("\n\nQuantidade de Alunos = %d\n",qa);
}
else
printf("\n\n Nao tem nenhum aluno cadastrado");
printf("\n\n\nTecle enter para voltar para o menu\n");
getche();
}
//Programa principal
main()
{ qa = 0;
do { cabec();
printf("\n Opcoes: \n\n");
printf("\t1- Inserir novo Aluno\n\n");
printf("\t2- Remover Aluno\n\n");
printf("\t3- Consultar Aluno\n\n");
printf("\t4- Listagem de Alunos\n\n");
printf("\t0- Sair do Programa\n\n\n");
linha();
printf("Informe a Opcao desejada: ");
scanf("%d",&op);
switch(op)
{ case 1: inserir(); break;
case 2: remover(); break;
case 3: consultar(); break;
65
Estrutura de Dados
case 4: listar(); break;
case 0: break;
default : printf("\nOpcao Invalida! Tecle enter..."); getche();
break;
}
}
}while(op!=0);
noatual = inicio;
while (noatual != NULL)
{ inicio = noatual->prox;
free(noatual);
noatual = inicio;
}
4.5 Fila Dinâmica
Nesta seção iremos analisar as operações básicas em uma fila implementada com ponteiros e
posteriormente o seu código em C.
4.5.1 Operações Básicas
Inserir Elemento
Todo elemento que vai ser inserido em uma fila é colocado no final da estrutura.
66
Estrutura de Dados
A figura ilustra a chegada de dois clientes na fila. Inicialmente a fila está vazia, portanto o valor do
ponteiro início e fim é NULL (passo 1). Quando um elemento vai ser inserido, a memória é alocada e os
dados são armazenados (passo 2). Todo nó criado em uma fila dinâmica, não tem vizinho seguinte, por
isso ele aponta para NULL. Na inserção do primeiro elemento, os ponteiros início e fim apontam para este
elemento (no exemplo, endereço 1010).
No passo 3 temos a chegada do cliente 12, que será armazenado no final da estrutura, o último
elemento da fila o terá (endereço 1070) como vizinho e o ponteiro fim irá apontar para o novo elemento.
Consultar Primeiro da Fila
Em uma fila, a consulta é feita apenas do primeiro elemento da fila. Assim teremos a informação
de qual será o próximo elemento a ser retirado. O primeiro elemento da fila é o elemento do endereço
início. Quando início estiver apontando para NULL, significa que a fila está vazia.
Remover Primeiro da Fila
Em uma fila, o elemento removido é sempre o que chegou há mais tempo, ou seja, o elemento
apontado por início. Quando um elemento é removido, o endereço do ponteiro início deve apontar para o
vizinho do primeiro da fila.
Listagem de Todos os Elementos da Fila
A operação de listagem possibilita a visualização dos dados de todos os elementos da fila. É feita
uma varredura na fila e todos os dados de todos os elementos são apresentados ao usuário.
67
Estrutura de Dados
4.5.2 Programa em C
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
// Implementação de fila usando ponteiro
/* Estrutura que será usada para criar os nós da fila */
typedef struct tipo_cliente { int conta, agencia;
char nome[15];
int tipo;
struct tipo_cliente *prox;
} TCliente;
TCliente *inicio = NULL; /* Ponteiro para o inicio da fila */
TCliente *fim = NULL; /* Ponteiro para o fim da fila */
TCliente *noatual;
/* Ponteiro a ser usado para percorrer a fila*/
int op, tamfila;
/*************************************************************************/
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Banco Poupe Muito - Fila Dinamica\n");
linha();
}
/* Funcao para inserir um novo no, ao final da fila */
void inserir ()
{ TCliente *novono;
int i, contal, agencial, tipol, continuar;
char nomel[15];
do{ // leitura dos dados do cliente
cabec();
printf("\n Chegada de novo cliente na fila \n");
printf("\n Numero da conta: ");
scanf("%d",&contal);
printf("\n Numero da agencia: ");
scanf("%d",&agencial);
printf("\n Nome: ");
fflush(stdin);
gets(nomel);
printf("\n Tipo de cliente(1- especial, 2-normal): ");
scanf("%d",&tipol);
tamfila++;
//Aloca memoria para o novo cliente
68
Estrutura de Dados
novono = (TCliente *) malloc(sizeof(TCliente));
novono->conta = contal;
novono->agencia = agencial;
for (i=0;i<=14;i++)
novono->nome[i] =nomel[i];
novono->tipo = tipol;
novono->prox = NULL;
// Inserir novono na fila de cliente
if (inicio == NULL) /* Se ainda nao existe nenhum cliente na fila */
{ inicio = novono;
fim = novono;
}
else /* Se ja existem clientes na fila*/
{ fim->prox = novono; /* Faz o ultimo no apontar para o novo no */
fim = novono; /* final da fila é atualizado */
}
printf("\n\nInserido com Sucesso!!!!\n\n");
printf("\n Continuar inserindo (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1); // verifica se quer continuar inserindo
}
/* Consultar um primeiro cliente da fila */
void consultarprimeiro()
{
cabec();
printf("\nConsulta primeiro cliente da fila\n\n");
noatual = inicio;
// coloca ponteiro no inicio da lista
if (noatual != NULL)
{ printf("\n\nAgencia
Conta
Nome
Tipo\n");
printf("-------------------------------------------------------\n");
printf("%4d
%4d
%-15s
%2d\n",
noatual->agencia, noatual->conta, noatual->nome,
noatual->tipo);
printf("-------------------------------------------------------\n");
}
else
printf("\nA fila está vazia!!\n\n");
printf("\n\nTecle enter para voltar para o menu\n");
getche();
}
/* remover um cliente da fila */
void retirafila()
{ int confrem, continuar;
do{ cabec();
printf("\nRetira primeiro cliente da fila \n\n");
noatual = inicio;
//ponteiro que ira apontar para o primeiro no
if (noatual != NULL)
// verifica se tem elementos na fila
{ printf("\n\nAgencia
Conta
Nome
Tipo\n");
printf("---------------------------------------------------\n");
printf("%4d
%4d
%-15s
%2d\n",
noatual->agencia, noatual->conta, noatual->nome,
noatual->tipo);
printf("---------------------------------------------------\n");
69
Estrutura de Dados
printf("\n\nconfirma retirada do cliente (1-sim, 2-nao)? ");
scanf("%d",&confrem);
if (confrem ==1) // confirma que quer remover
{ inicio = inicio->prox;
free(noatual); // libera memoria do no removido
tamfila--;
printf("\n\n Retirado da fila com sucesso!!!!\n\n");
}
else // cancelou a remocao
printf("\n\n Retirada cancelada\n\n");
}
else // fila vazia
printf("\n\nFila vazia!!\n\n");
printf("\n\nDeseja retirar outro cliente(1-sim, 2-nao)? ");
scanf("%d",&continuar);
}while (continuar ==1); // continuar retirando cliente da fila
}
/* Lista todos os clientes da fila */
void listar ()
{
noatual = inicio; // no auxiliar marca o inicio da lista
cabec();
printf("\nListagem de clientes da fila\n\n");
if (tamfila != 0)
{ printf("\n\nAgencia
Conta
Nome
Tipo\n");
printf("-------------------------------------------------------\n");
while( noatual != NULL) // percorre toda a fila ate chegar no final
{ printf("%4d
%4d
%-15s
%2d\n",
noatual->agencia, noatual->conta, noatual->nome,
noatual->tipo);
noatual = noatual->prox; // Faz noatual apontar para o proximo no
}
printf("-------------------------------------------------------\n");
printf("\n\nQuantidade de clientes na fila = %d\n",tamfila);
}
else
printf("\n\n Nao tem nenhum cliente na fila");
printf("\n\n\nTecle enter para voltar para o menu\n");
getche();
}
// Programa principal
main()
{ tamfila= 0;
do { cabec();
printf("\nOpcoes: ");
printf("\n\n
1 - Inserir cliente na fila");
printf("\n\n
2 - Consultar primeiro da fila");
printf("\n\n
3 - Retirar primeiro cliente da fila");
printf("\n\n
4 - Listar todos os clientes da fila");
printf("\n\n
0 - para sair \n");
linha();
printf("\nEntre com a sua opcao: ");
scanf("%d", &op);
/* Le a opcao do usuario */
70
Estrutura de Dados
}
switch(op)
{ case 1: inserir(); break;
case 2: consultarprimeiro();break;
case 3: retirafila(); break;
case 4: listar(); break;
case 0: break;
default: printf("\nOpcao nao valida");
}
} while (op != 0);
noatual = inicio;
while (noatual != NULL)
{ inicio = noatual->prox;
free(noatual);
noatual = inicio;
}
4.6 Pilha Dinâmica
Nesta seção iremos analisar as operações básicas em uma pilha implementada com ponteiros e
posteriormente o seu código em C.
4.6.1 Operações Básicas
Inserir Elemento
Todo elemento que vai ser inserido em uma pilha é colocado no final da estrutura. A figura abaixo
ilustra a chegada de três livros colocados na pilha.
71
Estrutura de Dados
Cada elemento que chega, será inserido no início da estrutura. Portando, o ponteiro início é sempre
modificado a cada inserção. Na Figura a pilha inicia vazia, com o ponteiro início apontando para NULL
(Passo 1). No passo 2 um elemento é inserido na pilha, por ser o primeiro, ele não tem vizinho e o
ponteiro início passa a apontar para o novo nó (endereço 1080).
No passo 3 um novo elemento é inserido, o ponteiro início deve ser atualizado e o novo nó deve
apontar para o elemento que estava no início da pilha (endereço 1080). No passo 4, um novo elemento é
inserido e as atualizações dos ponteiros devem ser feitas.
Consultar Topo da Pilha
Em uma pilha, a consulta é feita apenas do elemento do topo, ou seja o último elemento a ser
inserido, que neste caso é o elemento apontado pelo ponteiro início. Se o ponteiro início aponta para
NULL significa que a pilha está vazia.
Remover Topo da Pilha
Em uma pilha, o elemento removido é sempre o que chegou há menos tempo, ou seja, o elemento
da apontado pelo ponteiro início. Na figura abaixo iremos remover o elemento do topo da pilha. O
ponteiro início deve ser atualizado, apontando para o elemento que era vizinho do elemento removido.
Listagem de Todos os Elementos da Pilha
A operação de listagem possibilita a visualização dos dados de todos os elementos da pilha. É feita
uma varredura na pilha e todos os dados de todos os elementos são apresentados ao usuário.
4.6.1 Programa em C
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
// Implementação de pilha usando ponteiro
72
Estrutura de Dados
/* Estrutura que será usada para criar os nós da pilha */
typedef struct tipo_livro { int codigo, editora;
char titulo[30];
struct tipo_livro *prox;
} TLivro;
TLivro *inicio = NULL; /* Ponteiro para o inicio da pilha */
TLivro *noatual;
/* Ponteiro a ser usado para percorrer a pilha*/
int op, tampilha;
/*************************************************************************/
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Pilha de Livros - Dinamica\n");
linha();
}
/* Funcao para inserir um novo no, no inicio da pilha */
void inserir ()
{
TLivro *novono;
int i, codl, edl, continuar;
char titl[30];
do{ cabec();
printf("\nColocar livro no topo da pilha \n");
printf("\nCodigo do livro: ");
scanf("%d",&codl);
printf("\nTitulo do Livro: ");
fflush(stdin);
gets(titl);
printf("\nEditora(1- Campus, 2-Makron Books, 3-Moderna): ");
scanf("%d",&edl);
// Inserir livro na pilha
tampilha++;
//Aloca memoria para o novo livro
novono = (TLivro *) malloc(sizeof(TLivro));
novono->codigo = codl;
novono->editora = edl;
for (i=0;i<=29;i++)
novono->titulo[i] =titl[i];
novono->prox = inicio;
inicio = novono;
printf("\n\nInserido com Sucesso!!!!\n\n");
printf("\nContinuar inserindo (1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1); // verifica se quer continuar inserindo livros
}
73
Estrutura de Dados
/* Consultar livro do topo da pilha */
void consultatopo()
{
cabec();
printf("\nConsulta topo da pilha\n\n");
if (inicio != NULL)
{
printf("\n\nCodigo
Titulo
Editora\n");
printf("-----------------------------------------------------\n");
printf("%6d
%-20s
%7d\n", inicio->codigo,
inicio->titulo,inicio->editora);
printf("-----------------------------------------------------\n");
}
else
printf("\nA pilha está vazia!!\n\n");
printf("\n\nTecle enter para voltar para o menu\n");
getche();
}
/* remover livro do topo da pilha */
void retirapilha()
{ int confrem, continuar;
do{ cabec();
printf("\nRetira livro do topo da pilha \n");
noatual = inicio;
//ponteiro que ira apontar para o primeiro no
if (inicio != NULL)
// verifica se tem elementos na pilha
{ printf("\n\nCodigo
Titulo
Editora\n");
printf("---------------------------------------------------\n");
printf("%6d
%-20s
%7d\n", inicio->codigo,
inicio->titulo,inicio->editora);
printf("---------------------------------------------------\n");
printf("\n\nconfirma retirada do livro (1-sim, 2-nao)? ");
scanf("%d",&confrem);
if (confrem ==1) // confirma que quer remover
{
inicio = inicio->prox;
free(noatual); // libera memoria do no removido
tampilha;
printf("\n\n Retirado da Pilha com sucesso!!!!\n\n");
}
else // cancelou a remocao
printf("\n\n Retirada cancelada\n\n");
}
else // pilha vazia
printf("\n\nPilha vazia!!\n\n");
printf("\n\nDeseja retirar outro livro(1-sim, 2-nao)? ");
scanf("%d",&continuar);
}while (continuar ==1); // continuar retirando livro da pilha
}
/* Lista todos os livros da pilha */
void listar ()
{
noatual = inicio; // no auxiliar marca o inicio da lista
cabec();
printf("\nListagem dos livros da pilha\n\n");
74
Estrutura de Dados
}
if (inicio != NULL)
{
printf("\n\nCodigo
Titulo
Editora\n");
printf("-----------------------------------------------------\n");
while( noatual != NULL) // percorre toda a pilha
{ printf("%6d
%-20s
%7d\n", noatual->codigo,
noatual->titulo, noatual->editora);
noatual = noatual->prox; // Faz noatual apontar para proximo no
}
printf("-----------------------------------------------------\n");
printf("\n\nQuantidade de livros na pilha = %d\n",tampilha);
}
else
printf("\n\n Nao tem nenhum livro na pilha");
printf("\n\n\nTecle enter para voltar para o menu\n");
getche();
//Programa principal
main()
{ tampilha= 0;
do { cabec();
printf("\nOpcoes: \n");
printf("\n
1 - Inserir livro na pilha");
printf("\n
2 - Consultar topo da pilha");
printf("\n
3 - Retirar livro do topo");
printf("\n
4 - Listar todos os livros da pilha");
printf("\n
0 - Sair \n");
linha();
printf("\nEntre com a sua opcao: ");
scanf("%d", &op);
/* Le a opcao do usuario */
switch(op)
{ case 1: inserir(); break;
case 2: consultatopo();break;
case 3: retirapilha(); break;
case 4: listar(); break;
case 0: break;
default: printf("\n\n Opcao invalida"); getche(); break;
}
} while (op != 0);
noatual = inicio;
while (noatual != NULL)
{ inicio = noatual->prox;
free(noatual);
noatual = inicio;
}
}
75
Estrutura de Dados
5. Ordenação e Pesquisa
A ordenação facilita o acesso aos dados. Quando recebemos um conjunto de dados desordenados,
devemos realizar sobre eles um pré-processamento de forma a classificá-los. Muitas vezes necessitamos
organizar uma estrutura de dados para facilitar a pesquisa. Para alcançarmos um dado armazenado na
estrutura, também temos que usar métodos de pesquisa (busca) eficientes. Neste tópico iremos tratar
métodos clássicos de ordenar uma lista desordenada implementada com vetores e métodos de pesquisa
para buscas em uma lista estática ordenada.
5.1 Ordenação
Os métodos de ordenação de dados realizam classificações segundo uma chave de ordenação. Nesta
chave, especifica-se o tipo de ordem que queremos dar aos dados (crescente, decrescente, etc.) e o campo
da estrutura que será afetado (campo nome, campo matrícula, etc.). Tipos de métodos de ordenação:
•
Por troca: são baseados na troca de posição dos dados, de forma a ordená-los.
•
Por seleção:parte do princípio de realizar o isolamento de elementos para posições
ordenadas.
•
Por inserção: baseiam-se no deslocamento de elementos da estrutura frente a um elemento
de busca.
Imagine as cartas de um baralho:
• Para ordenar as cartas utilizando troca, espalhe-as voltadas para cima e então troque as
cartas fora de ordem até que todo baralho esteja ordenado;
• Utilizando seleção, espalhe as cartas na mesa, selecione a carta de menor valor, retire-a do
baralho e coloque-a na mão. O processo continua e termina quando todas as cartas
estiverem na sua mão;
• Para ordenar as cartas por inserção, segure todas as cartas na mão. Ponha uma carta por vez
na mesa, sempre a inserindo na posição correta.
5.1.1 Método da Ordenação por Troca
Método da Bolha(bubble sort): esse metodo é muito simples de implementar, no entando é um
dos piores métodos de ordenção quando se fala de desempenho. Ela envolve repetidas comparações e, se
necessário, a troca de dois elementos adjacentes.
A figura a seguir mostra o que acontece com o vetor no decorrer da execução do método da bolha.
76
Estrutura de Dados
5.1.2 Método da Ordenação por Seleção
Este método procura o menor elemento do vetor e coloca na primeira posição. A seguir, procura o
menor elemento do vetor a partir do segundo elemento e coloca na segunda posição do vetor. Continua o
processo até que existam apenas os dois últimos elementos do vetor para serem comparados.
77
Estrutura de Dados
A figura a seguir mostra o que acontece com o vetor no decorrer da execução do método de
ordenação por seleção.
78
Estrutura de Dados
5.1.3 Método da Ordenação por Inserção
Inserção Direta: Neste método, considera-se o segmento já ordenado como sendo formado pelo
primeiro elemento do vetor de chaves. Os demais elementos, ou seja do 2º ao último, pertencem ao
segmento não ordenado. A partir desta situação inicial, toma-se um a um dos elementos não ordenados, a
partir do primeiro e, por busca seqüencial realizada no segmento já ordenado, localiza-se a sua posição
relativa correta. Após a inserção, a fronteira entre os dois segmentos é deslocada uma posição para a
direita, indicando, com isto, que o segmento ordenado ganhou um elemento e o não ordenado perdeu um.
O processo prossegue até que todos os elementos do segundo segmento tenham sido inseridos no
primeiro. A figura a seguir mostra o que acontece com o vetor no decorrer da execução deste método.
79
Estrutura de Dados
5.2 Pesquisa
Busca de dados dentro de um conjunto. A Busca seqüencial procura do primeiro ao último
elemento do vetor até encontrar o elemento. Método mais simples, já utilizado nos nossos programas. A
Busca Binária é o método aplicado para conjunto de dados ordenados. Muito parecido com o método que
usamos quando desejamos procurar um número numa lista telefônica.
Programa que implementa os métodos de ordenação e pesquisa
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
// Programa para executar metodos de ordenação numa lista desordenada
// estatica
typedef struct { int mat;
char nome[31], sit;
float nota1, nota2, media;
}alunos;
alunos turma[30];
float soma;
int qa, ap,rp,op;
void linha()
{ int i;
for (i=1;i<=80;i++)
printf("_");
printf("\n");
}
void cabec()
{ system("cls");
printf("Faculdade Santa Maria - Ordenacao e Pesquisa\n");
linha();
}
//Inserir novo aluno
void inserir()
{ int cont;
do{ cabec();
printf("\n\nInserir Novo Aluno\n\n");
printf("\n\tNumero de Matricula do Aluno: ");
scanf("%d",&turma[qa].mat);
printf("\n\tNome: ");
fflush(stdin);
gets(turma[qa].nome);
printf("\n\tNota 1: ");
scanf("%f",&turma[qa].nota1);
printf("\n\tNota 2: ");
scanf("%f",&turma[qa].nota2);
80
Estrutura de Dados
}
turma[qa].media= (turma[qa].nota1+turma[qa].nota2)/2;
soma += turma[qa].media;
if (turma[qa].media>=6)
{ turma[qa].sit= 'A';
ap++;
}
else
{ turma[qa].sit= 'R';
rp++;
}
qa++;
printf("\n\n\tAluno Inserido com Sucesso!!!\n\n");
printf("\n\n\tContinuar inserindo aluno (1-sim/2-nao)? ");
scanf("%d",&cont);
}while (cont == 1);
//Metodo de ordenação da Bolha
void bolha()
{ int i, fim, troquei;
alunos aux;
fim = qa-1;
do {
troquei = 0;
for (i=0; i<=fim-1; i++)
{
if (turma[i].mat > turma[i+1].mat)
{
aux = turma[i];
turma[i] = turma[i+1];
turma[i+1] = aux;
troquei = 1;
}
}
fim--;
} while (troquei ==1);
printf("\n\n Ordenacao pelo metodo da Bolha\n\n");
printf("\n\n Vetor Ordenado com Sucesso!!!\n\n");
getche();
}
//Metodo de ordenação por Inserção
void insercao()
{ int i, k;
alunos aux;
for (i=1; i<=qa-1; i++)
{ k=i;
aux = turma[i];
while ((k>0)&&(aux.mat<turma[k-1].mat))
{ turma[k] = turma[k-1];
k--;
}
turma[k]=aux;
}
printf("\n\n Ordenacao pelo metodo da Insercao\n\n");
81
Estrutura de Dados
}
printf("\n\n Vetor Ordenado com Sucesso!!!\n\n");
getche();
//Metodo de ordenação por Seleção
void selecao()
{ int i,k,pmenor;
alunos aux;
for (i=0; i<=qa-2; i++)
{
pmenor = i;
for (k=i+1; k<=qa-1; k++)
{ if (turma[k].mat < turma[pmenor].mat)
pmenor = k;
}
if (i!=pmenor)
{
aux = turma[i];
turma[i] = turma[pmenor];
turma[pmenor] = aux;
}
}
printf("\n\n Ordenacao pelo metodo da Selecao\n\n");
printf("\n\n Vetor Ordenado com Sucesso!!!\n\n");
getche();
}
// Metodos de Busca com para listas ordenadas
//Metodo de busca binaria
void binaria()
{ int matcon, achou, continuar, inicio, fim, meio;
alunos aux;
do{ cabec();
printf("\n\nConsultar Aluno - Busca Sequencial\n\n");
printf("\n\tNumero de Matricula do Aluno: ");
scanf("%d",&matcon);
achou = 0;
inicio = 0;
fim = qa-1;
while (inicio<=fim)
{
meio = (inicio + fim)/2;
printf("\nmeio = %d\n\n",meio);
if (turma[meio].mat == matcon)
{
printf("\nMat
Aluno
Nota1
Nota2 Media
Sit");
printf("\n--------------------------------------------------");
printf("\n%2d
%-20s
%5.2f
%5.2f
%5.2f
%c",
turma[meio].mat, turma[meio].nome, turma[meio].nota1,
turma[meio].nota2, turma[meio].media, turma[meio].sit);
printf("\n--------------------------------------------------");
achou = 1;
break;
}
82
Estrutura de Dados
if (matcon >turma[meio].mat)
inicio = meio +1;
else
fim = meio -1;
}
if (achou == 0)
printf("\n\n\tNumero de Matricula Incorreto!!!!!!\n\n");
printf("\n\n\tContinuar consultando aluno(1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
}
//Metodo de busca sequencial
void sequencial()
{
int i, matcon, achou, continuar;
do{ cabec();
printf("\n\nConsultar Aluno - Busca Sequencial\n\n");
printf("\n\tNumero de Matricula do Aluno: ");
scanf("%d",&matcon);
achou = -1;
for(i = 0; i<qa; i++)
{ if (matcon==turma[i].mat)
{ achou = i;
break;
}
else
{ if (matcon<turma[i].mat)
break;
}
}
if (achou!=-1)
{
printf("\nMat
Aluno
Nota1
Nota2 Media
Sit");
printf("\n--------------------------------------------------");
printf("\n%2d
%-20s
%5.2f
%5.2f
%5.2f
%c",
turma[achou].mat,turma[achou].nome, turma[achou].nota1,
turma[achou].nota2,turma[achou].media,turma[achou].sit);
printf("\n--------------------------------------------------");
}
else
printf("\n\n\tNumero de Matricula Incorreto!!!!!!\n\n");
printf("\n\n\tContinuar consultando aluno(1-sim/2-nao)? ");
scanf("%d",&continuar);
}while (continuar == 1);
}
//Imprimir relatorio com as informaçoes de todos alunos
void listagem()
{ int i;
cabec();
printf("\n\nRelatorio Geral\n");
printf("\nMat
Aluno
Nota1
Nota2
Media
Sit");
printf("\n------------------------------------------------------------");
for(i = 0; i < qa; i++)
printf("\n%2d
%-20s
%5.2f
%5.2f
%5.2f
%c",turma[i].mat,
83
Estrutura de Dados
turma[i].nome, turma[i].nota1, turma[i].nota2, turma[i].media,
turma[i].sit);
printf("\n------------------------------------------------------------");
printf("\n\nMedia da turma = %.2f",soma/qa);
printf("\n\nQuantidade de aprovados = %d",ap);
printf("\n\nQuantidade de reprovados = %d",rp);
printf("\n\n\tDigite qualquer tecla para sair\n\n\n ");
getche();
}
//Programa principal
main()
{ op = 1;
soma = 0;
ap = rp = qa =0;
while (op != 0)
{ cabec();
printf("Opcoes: \n\n");
printf("
1- Inserir Aluno\n\n");
printf("
2- Ordenacao Bolha\n\n");
printf("
3- Ordenacao por Selecao\n\n");
printf("
4- Ordenacao por Insercao\n\n");
printf("
5- Busca Sequencial\n\n");
printf("
6- Busca Binaria\n\n");
printf("
7- Listagem\n\n");
printf("
0- Sair do Programa\n");
linha();
printf("
Informe a Opcao desejada: ");
scanf("%d",&op);
switch(op)
{ case 1: inserir(); break;
case 2: bolha(); break;
case 3: selecao(); break;
case 4: insercao(); break;
case 5: sequencial(); break;
case 6: binaria(); break;
case 7: listagem(); break;
case 0: break;
default: printf("\nOpcao Invalida!!!!"); getche();break;
}
}
}
84
Download