ESTRUTURA DE DADOS
Copyright © UVA 2019
Nenhuma parte desta publicação pode ser reproduzida por qualquer
meio sem a prévia autorização desta instituição.
REVISÃO DIAGRAMAÇÃO
Clarissa Penna UVA
Theo Cavalcanti
SUMÁRIO
Apresentação 6
Autor 7
UNIDADE 1
• Ponteiros ou apontadores
UNIDADE 2
• Lista circular
SUMÁRIO
UNIDADE 3
• Filas circulares
UNIDADE 4
Grafos e árvores 70
• Grafos e árvores
• Buscas em árvore
APRESENTAÇÃO
A estrutura de dados tem por objetivo permitir ao estudante conhecer os conceitos bási-
cos de estruturas e seus tipos, implementando soluções computacionais com as princi-
pais estruturas de dados: vetores, matrizes, ponteiros/apontadores, lista, fila, pilha, grafos
e árvores.
6
AUTOR
7
UNIDADE 1
Introdução às
estruturas de dados
INTRODUÇÃO
OBJETIVO
9
Estrutura de dados e seus tipos
Então, é verdadeiro afirmar que uma estrutura de dados se refere a uma forma única e
peculiar de armazenamento e organização de dados que se mostra eficiente quando é
adequada a diferentes tipos de aplicações, com suas tarefas específicas.
Na literatura existem diferentes estruturas de dados, cada qual com suas características
e especificidades.
10
Tipos de estruturas de dados
Vetor (array)
Um vetor pode ser representado por uma linha de contêiner ou espaços predefinidos e
identificados por índice, conforme ilustrado na Figura 1.
índice: [0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
nome: temp 18 17 20 26 32 29 15 12 16 21
Dessa forma, tem-se o vetor como uma coleção de variáveis do mesmo tipo que com-
partilham o mesmo nome e o mesmo endereço de memória em posições consecutivas.
11
Matriz
Uma matriz nada mais é que um vetor multidimensional caracterizado pelo uso de,pelo
menos, duas dimensões do mesmo endereço de memória com dados do mesmo tipo.
Apresenta conceito equivalente ao do estudo de matrizes da disciplina Álgebra Linear,
ou seja, todas as propriedades das matrizes existentes na matemática podem ser ado-
tadas em programas que manipulam essa estrutura de dados em busca de solução de
problemas.
Então, um elemento da matriz pode ser identificado por um número de linha e coluna
dessa matriz, conforme ilustrado na Figura 2.
n
...
5
Valor (R$)
4 Região X
3
2
1
1 2 3 4 5 ... n
Quantidade
Ponteiro
De acordo com Mizrahi (2008), o nome de uma variável indica o que será armazenado
nela. A isso dá-se o nome de variável significativa. O endereço de uma variável é um pon-
teiro. Seu valor indica em que parte da memória do computador a variável está alocada.
Uma variável ponteiro, também conhecida tecnicamente como variável apontadora (ver
Figura 3), é aquela que, no lugar de armazenar conteúdo de dado, guarda o espaço, o
endereço de memória de outra variável, para posterior manipulação.
12
Ponteiros ou apontadores proporcionam um método de acesso à variável sem que haja
a necessidade de a referenciar diretamente, ou seja, realiza o modo indireto de acesso.
Índices 112 113 114 115 116 117 118 119 120 121
Conteúdos 0 0 1 0 2 1 113 0 1 0
Lista
Uma lista é uma estrutura de dados linear que pode ser caracterizada como encadeada
ou circular, composta por nós indicativos do próximo elemento da lista, do primeiro ao
penúltimo, pois o último elemento da lista não aponta para ninguém (NULL).
Lista de tarefas
13
Subentende-se, portanto, que a primeira tarefa da lista a ser realizada é a de número 1
— pagar as contas no banco. Em seguida, a tarefa 2 — comprar os livros na livraria — é a
próxima, e assim por diante, até que a tarefa número 8 — passar na banca de jornal — seja
executada, terminando, assim, todas as tarefas da lista. Note que, depois da tarefa 8, não
existem outras a serem executadas.
Fila
As listas encadeadas, filas e pilhas são, na verdade, listas de dados cuja diferença principal
está na forma de acesso à inclusão e à remoção de seus elementos (PUGGA; RISSETTI,
2009). O conceito de fila de programação é o mesmo de quando esperamos para sermos
atendidos em determinada ordem: o primeiro elemento a entrar na fila será o primeiro a
sair dela. Esse conceito é tecnicamente conhecido como Fifo (first in, first out), ou seja,
o primeiro que entra na fila é o primeiro a sair dela. Em português, também é conhecido
como Peps (primeiro a entrar, primeiro a sair), conforme ilustra a Figura 5.
Pilha
As pilhas, de acordo com Pugga e Rissetti (2009), são estruturas de dados conhecidas
como listas Lifo (last in, first out), ou seja, o último elemento a entrar será o primeiro a sair.
Em português, também é conhecida como Ueps (último a entrar, primeiro a sair).
14
Na verdade, trata-se de uma estrutura do tipo lista linear, em que todas as operações
feitas — inclusão e remoção — são realizadas por um único extremo, pelo topo da pilha,
conforme ilustra a Figura 6.
n Tamanho da pilha
(...)
5
5 B 4
Topo D 3
A 2
1 C 1
Base Itens
Pilha
Grafo
a u v b
15
Saiba mais
Quando um grafo tem arestas que apresentam setas nas extremidades para
representar o sentido, ou seja, a direção do fluxo, ele é chamado tecnicamente
de grafo dirigido, ou dígrafo.
Árvore
A estrutura de dados árvore é uma lista na qual cada elemento possui dois ou mais su-
cessores, porém todos os elementos possuem um, e apenas um, antecessor, conforme
ilustra a Figura 8 (FORBELLONE; EBERSPÄCHER, 2005).
D H
B I
E J
A L
G M
MIDIATECA
16
Dica
Para ler uma abordagem mais aprofundada sobre vetores e matrizes de dados,
com exercícios propostos para fixação de conteúdo, sugerimos o capítulo 7
(p.181-193) do seguinte livro, disponível na Biblioteca Virtual:
17
Vetores e matrizes de dados
Imagine você escrever um programa para ler três notas de alunos de uma turma para
calcular sua média aritmética sem o uso de vetor. A solução poderia ser algo assim:
void main( )
{
printf (“Digite a nota 1: “); scanf (“%f”, nota1);
printf (“Digite a nota 2: “); scanf (“%f”, nota2);
printf (“Digite a nota 3: “); scanf (“%f”, nota3);
Agora vamos escrever um programa para solucionar o mesmo problema, porém com o
uso de vetor unidimensional:
void main( )
{
for (i=1; i<=3; i++)
{
printf (“Digite a nota %d: “, i);
scanf (“%f”, notas[i]);
18
media += notas[i];
}
media /= 3;
printf (“Media = %.2f\n”, media);
}
#include <stdio.h>
Por definição, uma matriz é uma coleção de variáveis do mesmo tipo que compartilham
o mesmo nome (MIZRAHI, 2008). Dessa forma, quando temos vetores com mais de uma
dimensão, dizemos estar manipulando vetores multidimensionais ou, simplesmente, ma-
trizes. Veja o exemplo a seguir:
19
/* Comentario: Exemplo de MATRIZ */
#include <stdio.h>
#define LIN 2
#define COL 2
void main ( )
{
int
mat [LIN][COL],
i, j;
MIDIATECA
20
Ponteiros ou apontadores
void main ( )
{
// Declaracao do ponteiro
int
*ptr;
system(“CLS”);
printf (“Conteudo do ponteiro: %d\n\n”, *ptr);
system(“PAUSE”);
}
Note que, no programa apresentado, atribuímos à variável ptr um valor retornado por
uma função chamada malloc( ), a qual é declarada na biblioteca padrão malloc.h. Para
que possamos entender a instrução ptr = ( int * ) malloc( sizeof( int )), vamos dividi-la em
partes:
21
Dessa forma, a instrução ptr = ( int * ) malloc( sizeof( int )) cria dinamicamente uma variá-
vel inteira referenciada por *ptr. Podemos, ao mesmo tempo, trabalhar com muitas variá-
veis do tipo ponteiro na memória do computador. A determinação referente à quantidade
necessária para utilização em um determinado programa depende exclusivamente de a
que o programa se propõe.
int main(void)
{
int
num = 13;
// Declaracao do ponteiro
int
*ptr;
22
// Atribuicao do endereco da variavel num ao ponteiro ptr
ptr = #
system(“CLS”);
printf (“\nUtilizando ponteiros”);
printf (“\n\nConteudo da variavel num: %d”, num);
printf (“\nEndereco da variavel num: %x”, &num);
printf (“\nConteudo da variavel ponteiro ptr: %x”, ptr);
system(“PAUSE”);
return(0);
}
Saiba mais
23
MIDIATECA
NA PRÁTICA
void main( )
{
/* Entrada de Dados */
for(i=1; i<=50; i++)
{
printf(“\nCodigo ? “); scalf(“%d”, &codigo[ i ]);
printf(“\nMercadoria ? “); scalf(“%s”, &mercadoria[ i ]);
printf(“\nQuantidade ? “); scalf(“%d”, &quantidade[ i ]);
printf(“\nPreco Unitario ? “); scalf(“%f”, &preco_unitario[ i ]);
24
/* Saida de Informacoes */
for(i=1; i<=50; i++)
if(quantidade[ i ] >= 100)
printf(“\nCodigo: %d Preco Total: %.2f “, codigo[ i ], preco_total[ i ]);
}
25
Resumo da Unidade 1
Nesta unidade, você conheceu as principais estruturas de dados e seus tipos, implemen-
tou soluções computacionais que envolvessem o uso de vetores e matrizes de dados,
assim como a estrutura ponteiro/apontador — alocação dinâmica.
Para complementar seus estudos, sugerimos que leia os livros indicados nas referências.
CONCEITO
26
Referências
27
UNIDADE 2
Estruturas lineares
encadeadas: listas
INTRODUÇÃO
OBJETIVO
29
Lista simplesmente encadeada
As listas são estruturas de dados complexas que podem ser trabalhadas sob três confi-
gurações distintas:
Lista 1 2 3
Lista refere-se a um ponteiro para o primeiro nó efetivo da lista, que contém, neste caso,
o valor “1”, assim como um ponteiro para o próximo nó dessa lista. Observe que o último
nó aponta para NULL, ou seja, indica o final da lista.
Curiosidade
30
Vejamos, em seguida, um programa exemplo de lista simplesmente encadeada:
printf(“Lista: “);
for (p = pList->prim; p != NULL; p = p->prox)
{
printf(“%d -> “, p->info);
}
printf(“NULL\n”);
}
if (novo != NULL)
{
31
novo->info = v;
novo->prox = pList->prim;
pList->prim = novo;
}
else
{
printf(“Memória Insuficiente\n”);
}
}
if (pAux != NULL)
{
pList->prim = pList->prim->prox;
free(pAux);
printf(“Valor Removido\n”);
}
else
{
printf(“Lista Vazia\n”);
}
}
novo = (Nodo*)malloc(sizeof(Nodo));
if (novo != NULL)
{
novo->info = v;
pAnt = NULL;
pAtu = pList->prim;
novo->prox = pAtu;
32
if (pAnt != NULL)
{
pAnt->prox = novo;
}
else
{
pList->prim = novo;
}
}
else
{
printf(“Memória Insuficiente\n”);
}
}
/* Comentario: Remover um Elemento Especifico da Lista */
void removerEle(ListaSimplesEnc *pList, int v)
{
Nodo *pAtu, *pAnt;
pAnt = NULL;
pAtu = pList->prim;
if (pAnt != NULL)
{
if (pAtu != NULL) {
pAnt->prox = pAtu->prox;
free(pAtu);
printf(“Valor Removido\n”);
}
else
{
printf(“Valor não encontrado\n”);
}
}
else
{
printf(“Lista Vazia\n”);
}
}
33
if (pAux != NULL)
{
while (pAux != NULL)
{
pList->prim = pAux->prox;
free(pAux);
pAux = pList->prim;
}
printf(“Todos os elementos foram removidos!\n”);
}
else
{
printf(“Lista Vazia\n”);
}
}
/* Comentario: Alterar Elemento da Lista */
void alterarEle(ListaSimplesEnc *pList, int v1, int v2)
{
Nodo *pAtu, *pAnt;
pAnt = NULL;
pAtu = pList->prim;
if (pAnt != NULL)
{
if (pAtu != NULL)
{
pAtu->info = v2;
printf(“Valor alterado\n”);
}
else
{
printf(“Valor não encontrado\n”);
}
}
else
{
printf(“Lista Vazia\n”);
}
}
34
/* Comentario: Programa Principal */
void main()
{
setlocale(LC_ALL, “portuguese”);
ListaSimplesEnc minhaLista;
int valor, op, valorAlt;
criarLista(&minhaLista);
system(“cls”);
switch (op) {
case 1: // inserir elemento no inicio
printf(“Valor? “);
scanf(“%d”, &valor);
inserirIni(&minhaLista, valor);
break;
case 2: // inserir elemento ordenado
printf(“Valor? “);
scanf(“%d”, &valor);
inserirOrd(&minhaLista, valor);
break;
case 3: // remover o primeiro
removerIni(&minhaLista);
break;
case 4: // remover determinado elemento
printf(“Valor? “);
scanf(“%d”, &valor);
removerEle(&minhaLista, valor);
break;
case 5: // mostrar lista
if (estaVazia(&minhaLista)) {
printf(“Lista vazia\n”);
}
else {
mostrarLista(&minhaLista);
35
}
break;
case 6: // apagar todos os elementos da Lista
removerTudo(&minhaLista);
break;
case 7: // alterar um elemento
printf(“Valor a ser alterado? “);
scanf(“%d”, &valor);
printf(“Novo valor? “);
scanf(“%d”, &valorAlt);
alterarEle(&minhaLista, valor, valorAlt);
break;
case 0: // abandonar o programa
removerTudo(&minhaLista);
exit(0);
default:
printf(“Opção inexistente!\n”);
}
}
}
MIDIATECA
36
Lista duplamente encadeada
Conforme afirmam Pugga e Rissetti (2009), o encadeamento duplo de lista, ou lista du-
plamente encadeada, apresenta como característica a possibilidade de ligação com du-
plo sentido — horário e anti-horário —, ou seja, pode varrer os elementos da lista tanto
da esquerda para a direita como da direita para a esquerda, conforme ilustra a Figura 2.
Lista 1 2 3
Em uma lista duplamente encadeada, cada nó tem um ponteiro para o próximo elemento
e um para o elemento anterior. Assim, ao acessar um elemento da lista duplamente en-
cadeada, acessam-se também os elementos adjacentes, ou seja, o próximo e o anterior.
enum OpcoesMenu{SAIR=0,CRIAR_LISTA,INSERIR_AMIGO,IMPRIMIR_LISTA,REMOV-
ER_AMIGO,VERIFICAR_LISTA_VAZIA,LIBERAR_MEMORIA};
#define TAMMAX_AMIGO 40
37
/* Comentario: Lista Duplamente Encadeada */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
enum OpcoesMenu{SAIR=0,CRIAR_LISTA,INSERIR_AMIGO,IMPRIMIR_LISTA,REMOV-
ER_AMIGO,VERIFICAR_LISTA_VAZIA,LIBERAR_MEMORIA};
#define TAMMAX_AMIGO 40
No * e = criar_elemento();
tmp->proximo = e;
}
}
38
/* Comentario: Pesquisar Amigo */
No * pesquisar (No * inicio_lista, char * nome_amigo)
{
No * tmp;
if (is_vazia(inicio_lista))
{
tmp = NULL;
} else
{
tmp = inicio_lista;
while(tmp != NULL)
{
if (strcasecmp(tmp->amigo, nome_amigo) == 0)
return tmp;
tmp = tmp->proximo;
}
}
return tmp;
}
while(tmp != NULL)
{
printf(“%s\n”, tmp->amigo);
tmp = tmp->proximo;
}
}
}
39
tmp_inicio = lista;
tmp_inicio = elemento->proximo;
tmp_inicio->anterior = NULL;
} else
{
tmp_inicio = elemento->anterior;
tmp_inicio->proximo = elemento->proximo;
tmp_inicio = lista;
}
free(elemento);
return tmp_inicio;
}
return strdup(nome);
}
40
/* Comentario: Programa Principal */
int main()
{
int opcao;
char * nome_amigo;
No * lista = NULL;
setlocale(LC_ALL, “portuguese”);
while(1)
{
system(“CLS”);
menu_escolha();
printf(“\nOpção: “);
scanf(“%d%*c”, &opcao);
switch(opcao)
{
case CRIAR_LISTA:
lista = criar_elemento();
printf(“\nLista criada com sucesso.\n”);
break;
case INSERIR_AMIGO:
puts(“\n* * * INCLUSÃO * * *”);
nome_amigo = ler_amigo();
if (pesquisar(lista, nome_amigo) == NULL)
{
inserir(lista, nome_amigo);
} else
{
puts(“\nAmigo já consta na lista.\n”);
}
break;
case IMPRIMIR_LISTA:
imprimir(lista);
break;
41
case REMOVER_AMIGO:
puts(“\n* * * REMOÇÃO * * *”);
nome_amigo = ler_amigo();
No * registro = pesquisar(lista, nome_amigo);
if (registro == NULL)
{
puts(“\nAmigo não encontrado.\n”);
} else
{
lista = remover(lista, registro);
}
break;
case VERIFICAR_LISTA_VAZIA:
printf(“\nA lista%sestá vazia\n”, is_vazia(lista)? “ “ : “ não “);
break;
case LIBERAR_MEMORIA:
liberar_memoria(lista);
lista = NULL;
printf(“\nLista apagada.\n”);
break;
default:
printf(“\nDigite uma opção válida.\n”);
}
}
system(“PAUSE”);
}
return 0;
}
MIDIATECA
42
Lista circular
A lista circular, conforme ilustra a Figura 3, nada mais é que uma lista ligada, ou lista sim-
plesmente encadeada, cujo último elemento aponta diretamente para o primeiro dessa
lista (FORBELLONE; EBERSPÄCHER, 2005).
Lista 1 2 3
43
struct no *p;
printf(“\nValor do Elemento: “);
scanf(“%d”,&valor);
if((p = malloc(sizeof(struct no))) == NULL)
{
printf(“\nErro de Memória\n”);
}
else
{
p->info = valor;
p->prox = head->prox;
head->prox = p;
}
}
while(pNext->prox != head)
{
pNext = pNext->prox;
}
pNow->prox = pNext->prox;
pNext->prox = pNow;
}
}
/* Comentario: Remover Elemento da Lista Circular */
void remover(struct no *head, int valor)
{
struct no *p, *aux;
printf(“\nValor a Remover: “);
scanf(“%d”,&valor);
p = head->prox;
aux = head;
head->info = valor;
44
while(p->info != valor)
{
aux = p;
p = p->prox;
}
if(p == head)
{
printf(“\nElemento não encontrado\n”);
}
else
{
aux->prox = p->prox;
free(p);
printf(“\nElemento removido com Sucesso!\n”);
}
}
45
if(p == head)
{
printf(“\nElemento não encontrado!\n”);
}
else
{
printf(“\nElemento encontrado com sucesso!\n”);
}
}
46
case 2:
addfim(head, valor);
break;
case 3:
buscar(head, valor);
break;
case 4:
remover(head, valor);
break;
case 5:
imprimir(head);
break;
default:
printf(“\nOpçção Inválida!\n”);
break;
}
printf(“\n”);
system(“PAUSE”);
}
while(op!=0);
return 0;
}
}
Curiosidade
47
MIDIATECA
MIDIATECA
NA PRÁTICA
48
strncpy(lista->senha, (const char *) nome_senha, strlen(nome_senha));
} else
{
No * tmp = lista;
while(tmp->proximo != NULL)
{
tmp = tmp->proximo;
}
No * e = criar_elemento();
tmp->proximo = e;
}
}
No * remover(No * lista, No * elemento) // Desabilitar senha na lista duplamente
encadeada
{
No * tmp_inicio;
if (elemento == lista)
{
tmp_inicio = lista;
tmp_inicio = elemento->proximo;
tmp_inicio->anterior = NULL;
} else
{
tmp_inicio = elemento->anterior;
tmp_inicio->proximo = elemento->proximo;
tmp_inicio = lista;
}
free(elemento);
return tmp_inicio;
}
49
Resumo da Unidade 2
Nesta unidade, você conheceu as estruturas lineares encadeadas (listas), nas variações
de lista simplesmente encadeada, lista duplamente encadeada e lista circular, por meio
da implementação de programas de computador.
CONCEITO
50
Referências
51
UNIDADE 3
Estruturas lineares
encadeadas: filas e pilhas
INTRODUÇÃO
OBJETIVO
53
Trabalhando com filas
A fila é uma estrutura de dados dinâmica que admite a inserção e a remoção de ele-
mentos a partir da técnica conhecida como Fifo (first in, first out), ou seja, o primeiro
elemento a entrar na fila será o primeiro a sair dela, conforme ilustrado na Figura 1
(MIZRAHI, 2008).
Remoção Inserção
1 2 3 ... n n+1
54
f->capacidade = c;
f->dados = (int*) malloc (f->capacidade * sizeof(int));
f->primeiro = 0;
f->ultimo = -1;
f->nItens = 0;
}
f->ultimo++;
f->dados[f->ultimo] = v;
f->nItens++;
}
if(f->primeiro == f->capacidade)
f->primeiro = 0;
f->nItens--;
return temp;
}
55
if (i == f->capacidade)
i=0;
}
printf(“\n”);
}
system(“CLS”);
printf(“Capacidade da Fila?”);
scanf(“%d”,&capa);
criarFila(&umaFila, capa);
while( 1 )
{
system(“CLS”);
printf(“ * * * FAÇA SUA ESCOLHA * * * \n\n”);
printf(“ 1- Inserir elemento na Fila \n”);
printf(“ 2- Remover elemento da Fila \n”);
printf(“ 3- Mostrar elementos da Fila \n”);
printf(“ 0- Sair \n\n”);
printf(“Opção? “);
scanf(“%d”, &opcao);
switch(opcao){
case 0: exit(0);
case 1:
if (estaCheia(&umaFila))
{
printf(“\nA Fila está Cheia.\n”);
system(“PAUSE”);
}
else
{
printf(“\nElemento a ser inserido?”);
scanf(“%d”, &valor);
inserir(&umaFila,valor);
}
56
break;
case 2:
if (estaVazia(&umaFila))
{
printf(“\nA Fila está Vazia.\n”);
system(“PAUSE”);
}
else
{
valor = remover(&umaFila);
printf(“\nO Elemento %d foi removido com
sucesso.\n”, valor) ;
system(“PAUSE”);
}
break;
case 3:
if (estaVazia(&umaFila))
{
printf(“\nA Fila está Vazia.\n”);
system(“PAUSE”);
}
else
{
printf(“\nElementos da Fila: “);
mostrarFila(&umaFila);
printf(“\n”);
system(“PAUSE”);
}
break;
default:
printf(“\nOpção Inválida.\n”);
system(“PAUSE”);
}
}
}
57
MIDIATECA
58
Trabalhando com pilhas
As pilhas são uma lista na qual é aplicada a disciplina de acesso antagônica denomi-
nada Ueps (o último a entrar é o primeiro a sair), ou, em inglês, o termo Lifo (last in, first
out), ou seja, qualquer elemento que entrar na pilha somente sairá quando todos os que
entraram depois dele saírem (PUGGA; RISSETTI, 2009). A Figura 2 ilustra a estrutura
de dados pilha linear.
Topo
n+1
n
...
3
2
Pilha 1 Base
int capacidade;
59
/* Comentario: Criar Pilha */
void criarpilha( struct Pilha *p, int c )
{
p->topo = -1;
p->capa = c;
p->pElem = (int*) malloc (c * sizeof(int));
}
60
setlocale(LC_ALL, “portuguese”);
system(“CLS”);
printf( “Capacidade da Pilha?” );
scanf( “%d”, &capacidade );
while( 1 )
{
system(“CLS”);
printf(“ * * * FAÇA SUA ESCOLHA * * * \n\n”);
printf(“ 1- Inserir Elemento na Pilha [Empilhar] \n”);
printf(“ 2- Remover Elemento da Pilha [Desempilhar] \n”);
printf(“ 3- Mostrar Elemento do Topo da Pilha \n”);
printf(“ 0- Sair \n\n”);
printf(“Opção?”);
scanf(“%d”, &op);
switch (op){
case 0:
exit(0);
break;
case 1:
else
{
printf(“\nValor ? “);
scanf(“%d”, &valor);
empilhar (&minhapilha, valor);
}
break;
case 2:
if ( estavazia(&minhapilha) == 1 )
61
case 3:
if ( estavazia (&minhapilha) == 1 )
printf( “\nA Pilha está Vazia. \n” );
else
{
valor = retornatopo (&minhapilha);
printf( “\nElemento do Topo da Pilha: %d\n”, valor );
}
break;
MIDIATECA
62
Filas circulares
De acordo com Forbellone e Eberspächer (2005), uma fila circular é um vetor dinâmi-
co cujo término se encontra com seu início. No entanto, os elementos da fila circular
podem não estar ocupando fisicamente todas as posições desse vetor, identificando
esse final, portanto, como NULL. Vejamos a ilustração de uma fila circular na Figura 3.
Início
1
2
3
4
5
6
Final
#define MAX 5
63
int memo[MAX];
};
if(F->fim == MAX)
F->fim = 0;
F->memo[F->fim] = x;
F->total++;
}
aux = F->memo[F->com];
F->com++;
if(F->com == MAX)
{
F->com = 0;
}
F->total --;
return aux;
}
64
while(B.total!=0)
{
if(x == desenfileirar(&B))
{
achou = 1;
}
}
return achou;
}
system(“CLS”);
printf(“* * * FAÇA SUA ESCOLHA * * *\n\n”);
printf(“ 1- Enfileirar Elemento \n”);
printf(“ 2- Desenfileirar Elemento \n”);
printf(“ 3- Listar Elementos \n”);
printf(“ 4- Buscar Elemento na Fila \n”);
printf(“ 0- Sair \n\n”);
printf(“ Opção: “);
scanf(“%d”, &opc);
return opc;
}
setlocale(LC_ALL, “portuguese”);
do
{
opc = menu();
switch(opc)
{
case 0:
exit (0);
break;
case 1:
if(F.fim==MAX-1)
{
printf(“\nA Fila está Cheia. “);
}
65
else
{
printf(“\n Elemento (número) a ser inserido na Fila: “);
scanf(“%d”, &x);
if(busca(F,x) == 1)
{
printf(“Não é possível inserir elementos repetidos “);
}
else
{
enfileirar(&F, x);
}
}
break;
case 2:
if(F.total == 0)
printf(“\nA Fila está Vazia. “);
else
printf(“\nElemento retirado da Fila Circular => %d”,
desenfileirar(&F));
break;
case 3:
if(F.fim == -1)
printf(“\nA Fila está Vazia. “);
else
listar(F);
break;
case 4:
printf(“\nQual é o elemento que deseja localizar?”);
scanf(“%d”, &x);
if((busca(F,x)==1))
printf(“\nO elemento %d está na Fila. “, x);
else
printf(“\nO elemento %d não está na Fila. “, x);
break;
printf(“\n”);
system(“PAUSE”);
}while(opc!=0);
}
66
MIDIATECA
NA PRÁTICA
67
Resumo da Unidade 3
Nesta unidade, você conheceu e implementou as estruturas de dados fila e pilha lineares.
Também foi desenvolvido programa de computador com a estrutura fila circular com fins
de aprofundamento de estudo.
CONCEITO
O estudo das estruturas de dados, além dos vetores, das matrizes, dos pon-
teiros/apontadores e das listas, também apresenta o recurso de filas e pilhas.
Nesse contexto, quando utilizamos a estrutura de dados fila, aplicamos o méto-
do conhecido como Fifo (first in, first out), ou seja, o primeiro elemento a entrar
na fila será, sempre, o primeiro elemento a ser retirado dela. De forma análoga,
ao utilizarmos a estrutura de dados pilha, aplicamos o método conhecido como
Lifo (last in, first out), ou seja, o último elemento a entrar na pilha (empilhamen-
to) será o primeiro a ser retirado dela (desempilhamento).
68
Referências
69
UNIDADE 4
Grafos e árvores
INTRODUÇÃO
Nesta unidade, o estudante conhecerá a teoria dos grafos e a estrutura de dados árvore
— sua variação como árvore binária e árvore AVL —, explorando também os percursos
em árvore e os algoritmos de busca.
OBJETIVO
71
Grafos e árvores
Grafo
1 2
4 3
1 2
72
As figuras 1 e 2 podem ser representadas, respectivamente, da seguinte forma algébrica:
G = (V’ , E)
V’ = { 1, 2, 3, 4 }
E = { [1, 2], [2, 3], [3, 1], [1, 4] }
D = (V’’, A)
V’’ = { 1, 2, 3 }
A = { (1, 2), (2, 1), (1, 3), (2, 3) }
Importante
Árvore
Segundo Pugga e Rissetti (2009), a árvore é uma estrutura de dados bidirecional, não
linear, constituída de nós que representam um modelo hierárquico, uma vez que armaze-
nam dados com base em relações de dependência.
• Realizam suas tarefas de forma mais eficiente que vetores, listas e conjuntos.
• Oferecem uma organização mais natural para os dados.
73
Figura 3: Representação hierárquica da estrutura árvore.
B C D
E F G H
I J K L
• O nó A tem nível 0.
• Os nós B, C e D têm nível 1.
• Os nós E, F, G e H têm nível 2.
• Os nós I, J, K e L têm nível 3.
• O nó B tem grau 2.
• O nó F tem grau 1.
• O nó C tem grau 0.
74
Subárvore
T1 T2
B C D
E F G H
I J K L
Curiosidade
• Parênteses aninhados.
• Inclusão.
• Identação.
T=(A(B(E(I)(J))(F(K)))(C)(D(G(L))(H)))
75
Representação por inclusão
Cada nó é simbolizado por uma figura geométrica, e seus descendentes são inseridos ou
incluídos nessa figura, de modo que o nó principal englobe os demais.
I C
E J
F K
G L
B H
D
Esse tipo de representação coloca os nós identados, de acordo com a prioridade, acerca
do nó que está classificado como raiz, pai, filho ou folha.
A
B
E
I
J
F
K
C
D
G
L
H
76
Árvores binária e AVL
Árvore binária
Uma árvore binária, de acordo com Mizrahi (2008), é um conjunto de registros ou nós em
forma de estrutura de dados que satisfaz determinadas condições e é caracterizado por:
Saiba mais
77
A árvore binária apresenta como particularidade o posicionamento de seus nós, confor-
me afirmam Pugga e Rissetti (2009):
57
45 77
13 60 84
9 60 78
Uma árvore binária pode também ser classificada como completa ou cheia, conforme
ilustra a Figura 10.
78
Figura 11: Representação de uma árvore em forma de vetor de dados.
0 1 2 3 4 5 6
Árvore AVL
Segundo Mizrahi (2008), a árvore AVL é uma árvore binária de busca balanceada, confor-
me pudemos observar na Figura 10, também conhecida como Adelson-Velsky e Landis,
em homenagem a seus criadores.
Uma árvore balanceada é aquela que busca minimizar o número de comparações rea-
lizadas, no pior caso, para uma busca com chaves de probabilidades de ocorrências
idênticas.
79
Buscas em árvore
As buscas em árvores são estabelecidas pelos percursos que seguimos para percorrer
os nós dessa árvore.
Busca em profundidade
A busca em profundidade pode adotar três técnicas distintas para explorar esses
percursos:
• Pré-ordem.
• Em ordem.
• Pós-ordem.
80
Tomando como base a árvore binária representada a seguir, na Figura 12 temos:
B C
D E F
Busca em largura
Então, para cada um dos vértices mais próximos, exploramos seus vértices vizinhos
inexplorados, e assim por diante, até que ele encontre o alvo da busca ou termine os nós
visitados na árvore.
B C
D E F
81
Importante
Note, na ilustração da Figura 13, que a varredura começa sempre de cima para
baixo e da esquerda para a direita a partir do nó raiz. Ao aplicar a técnica de
busca em largura, com base na árvore apresentada, a seguinte saída é obtida:
A, B, C, D, E e F.
82
(*pRaiz)->numero = numero;
(*pRaiz)->x = x;
}
else
{
if(numero < (*pRaiz)->numero)
inserir(&(*pRaiz)->esquerda, numero, x);
if(numero > (*pRaiz)->numero)
inserir(&(*pRaiz)->direita, numero, x);
}
}
83
if(numero > (*pRaiz)->numero)
remover(&(*pRaiz)->direita, numero);
else
{
No *pAux = *pRaiz;
if (((*pRaiz)->esquerda == NULL) && ((*pRaiz)->direita == NULL))
{
free(pAux);
printf(“\nRemovido com Sucesso! \n”);
(*pRaiz) = NULL;
}
else
{
if ((*pRaiz)->esquerda == NULL)
{
(*pRaiz) = (*pRaiz)->direita;
pAux->direita = NULL;
free(pAux); pAux = NULL;
printf(“\nRemovido com Sucesso! \n”);
}
else
{
if ((*pRaiz)->direita == NULL)
{
(*pRaiz) = (*pRaiz)->esquerda;
pAux->esquerda = NULL;
free(pAux); pAux = NULL;
printf(“\nRemovido com Sucesso! \n”);
}
else
{
pAux = MaiorDireita(&(*pRaiz)->esquerda);
pAux->esquerda = (*pRaiz)->esquerda;
pAux->direita = (*pRaiz)->direita;
(*pRaiz)->esquerda = (*pRaiz)->direita = NULL;
free((*pRaiz)); *pRaiz = pAux; pAux = NULL;
printf(“\nRemovido com Sucesso! \n”);
}
}
}
}
}
84
/* Comentario: Percurso Em Ordem */
void exibirEmOrdem(No **pRaiz)
{
if((*pRaiz) != NULL)
{
exibirEmOrdem(&(*pRaiz)->esquerda);
printf(“%i\n”, (*pRaiz)->numero);
exibirEmOrdem(&(*pRaiz)->direita);
}
}
if((*pRaiz)->esquerda != NULL)
printf(“Esq: %i\t”,(*pRaiz)->esquerda->numero);
else
printf(“Esq: NULL\t”);
if((*pRaiz)->direita != NULL)
printf(“Dir: %i\t”,(*pRaiz)->direita->numero);
else
printf(“Dir: NULL\t”);
if((*pRaiz)->esquerda != NULL)
imprimir(&(*pRaiz)->esquerda);
if((*pRaiz)->direita != NULL)
imprimir(&(*pRaiz)->direita);
}
85
else
printf(“A árvore está vazia! \n”);
}
/* Programa Principal */
int main ()
{
struct carro ca;
int c;
No *pRaiz;
criarArvore(&pRaiz);
setlocale(LC_ALL, “portuguese”);
int op;
do{
system(“CLS”);
printf(“* * * FAÇA SUA ESCOLHA * * *\n\n”);
printf(“1. Inserir Veículo: \n”);
printf(“2. Remover Veículo: \n”);
printf(“3. Mostrar PRÉ-ORDEM: \n”);
printf(“4. Mostrar EM ORDEM: \n”);
printf(“5. Mostrar PÓS-ORDEM: \n”);
printf(“6. Imprimir Árvore \n”);
printf(“\nOpção [0 para Sair]: “);
scanf(“%d”, &op);
switch(op)
{
case 1:
system(“CLS”);
printf(“\nCarro: “);
scanf(“%s”, &ca.nome);
printf(“\nMarca: “);
scanf(“%s”,&ca.marca);
printf(“\nAno de Fabricação: “);
scanf(“%d”, &ca.ano);
printf(“\nPreço do Veículo: “);
scanf(“%f”, &ca.preco);
printf(“\nDigite um Número (Referência na Árvore): “);
scanf(“%d”,&c);
inserir(&pRaiz,c,ca);
system(“PAUSE”);
break;
case 2:
system(“CLS”);
printf(“\nDigite um Número: “);
scanf(“%d”,&c);
remover(&pRaiz,c);
system(“PAUSE”);
break;
86
case 3:
system(“CLS”);
exibirPreOrdem(&pRaiz);
system(“PAUSE”);
break;
case 4:
system(“CLS”);
exibirEmOrdem(&pRaiz);
system(“PAUSE”);
break;
case 5:
system(“CLS”);
exibirPosOrdem(&pRaiz);
system(“PAUSE”);
break;
case 6:
system(“CLS”);
imprimir(&pRaiz);
printf(“\n”);
system(“PAUSE”);
break;
case 0:
break;
default:
printf(“\n\nOpção Inválida. \n”);
system(“PAUSE”);
break;
}
}while(op!=0);
return 0;
}
87
NA PRÁTICA
88
Resumo da Unidade 4
CONCEITO
89
Referências
90