Estrutura de Dados para
Tecnologia
12/05/2015 2
Pilhas
São TADs representados através de listas sequenciais
(fixas) ou encadeadas (dinâmicas), em que a seguinte regra deve ser obedecida:
Todas as operações (inclusão, remoção e consulta) devem
ser realizadas no fim da lista.
Critério: LIFO (Last In, First Out) Operações:
Pilhas
12/05/2015 4
Pilhas
Representando através de lista sequencial (vetor):
1 2 3 4 5 6 7 8 ... MAX
...
Pilha
Elementos Topo
#define MAX 10
typedef struct strpilha {
int elementos[MAX]; int topo;
Pilhas
Criando a pilha:
void cria_pilha(pilha *p) {
12/05/2015 6
Pilhas
Empilhamento (PUSH)
0 1 2 3 4 5 6 7 8 9
p
Elementos
Pilhas
Empilhamento (PUSH)
0 1 2 3 4 5 6 7 8 9
p
12/05/2015 8
Pilhas
Empilhamento (PUSH)
0 1 2 3 4 5 6 7 8 9
p
Pilhas
Empilhamento (PUSH)
0 1 2 3 4 5 6 7 8 9
p
12/05/2015 10
Pilhas
Empilhamento (PUSH)
0 1 2 3 4 5 6 7 8 9
p
Pilhas
Empilhamento (PUSH):
void push(pilha *p, int valor) {
if(p->topo == MAX-1) printf("Pilha cheia !"); else
{
p->elementos[++(p->topo)] = valor;
printf("Empilhamento efetuado com sucesso !"); }
12/05/2015 12
Pilhas
Desempilhamento (POP):
0 1 2 3 4 5 6 7 8 9
p
Pilhas
Desempilhamento (POP):
0 1 2 3 4 5 6 7 8 9
p
12/05/2015 14
Pilhas
Desempilhamento (POP):
0 1 2 3 4 5 6 7 8 9
p
Pilhas
Desempilhamento (POP):
void pop(pilha *p) {
if(p->topo == -1)
printf("A pilha esta vazia !"); else
{
(p->topo)--;
printf("Desempilhamento efetuado com sucesso !"); }
12/05/2015 16
Pilhas
Vantagens da representação através de listas
sequenciais:
Programação fácil
Desvantagens da representação através de listas
sequenciais:
Limitação quanto ao número de elementos que podem ser
empilhados
Desperdício de memória, se o tamanho alocado para a lista
Pilhas
Representando através de lista encadeada:
typedef struct strnode {
int valor;
struct *strnode proximo; } node;
typedef node* pilha; pilha p;
nó 1 nó 2 ... nó n
Criando a pilha:
void cria_pilha(pilha *p) {
*p = NULL; } ... void main() { pilha p; ... cria_pilha(&p); ... }
12/05/2015 18
Pilhas
Empilhamento (PUSH):
Pilhas
p
7
Empilhamento (PUSH):
12/05/2015 20
Pilhas
p
7 3
Empilhamento (PUSH):
Pilhas
p
7 3
4
Empilhamento (PUSH):
12/05/2015 22
Pilhas
p
7 3
4 1
Empilhamento (PUSH):
Pilhas
p
7 3
12/05/2015 24
Pilhas
Empilhamento (PUSH):
void push(pilha *p, int valor) {
node *no;
no = (node *) malloc(sizeof(node)); no->valor = valor;
if (*p == NULL) // A pilha está vazia ? no->proximo = NULL;
else
no->proximo = *p; *p = no;
Desempilhamento (POP):
Pilhas
p
7 3
4 1
Desempilhamento (POP):
12/05/2015 26
Pilhas
p
7 3
4 1
Desempilhamento (POP):
Pilhas
p
7 3
4
Desempilhamento (POP):
12/05/2015 28
Pilhas
p
7 3
4
Pilhas
Desempilhamento (POP): void pop(pilha *p)
{
node *no = *p;
if (*p == NULL) // A pilha está vazia ? printf("Pilha vazia !\n");
else {
*p = (*p)->proximo; free(no);
printf("Desempilhamento efetuado com sucesso.\n"); }
12/05/2015 30
Pilhas
Vantagens da representação através de listas
encadeadas:
A memória só é alocada quando houver empilhamento
O limite para empilhamento é o limite de memória disponível
Desvantagens da representação através de listas
encadeadas:
Filas
São TADs representados através de listas sequenciais
(fixas) ou encadeadas (dinâmicas), em que as seguintes regras devem ser obedecidas:
Todas as operações de inclusão devem ser realizadas no fim
da lista.
Todas as operações de exclusão e consulta devem ser
realizadas no início da lista.
Critério: FIFO (First In, First Out) Operações:
Representando através de lista sequencial (vetor):
#define MAX 10
typedef struct strfila {
int elementos[MAX]; int inicio, fim;
} fila; fila f;
12/05/2015 32
Filas
1 2 3 4 5 6 7 8 ... MAX
...
Fila
Elementos Início
Criando a fila:
void cria_fila(fila *f) {
f->inicio = 0; f->fim = -1; }
Filas
f
elementos inicio
12/05/2015 34
Filas
Enfileiramento (ENQUEUE):
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
Filas
Enfileiramento (ENQUEUE):
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
12/05/2015 36
Filas
Enfileiramento (ENQUEUE):
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
Filas
Enfileiramento (ENQUEUE):
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
12/05/2015 38
Filas
Enfileiramento (ENQUEUE):
void enqueue(fila *f, int valor) {
if(f->fim == MAX-1) // Não há mais posições a avançar ? printf("Sem posicoes para enfileiramento !");
else {
f->elementos[++(f->fim)] = valor;
printf("Elemento enfileirado com sucesso !"); }
Filas
Desenfileiramento (DEQUEUE):
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
12/05/2015 40
Filas
Desenfileiramento (DEQUEUE):
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
Filas
Desenfileiramento (DEQUEUE):
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
12/05/2015 42
Filas
Desenfileiramento (DEQUEUE):
void dequeue(fila *f) {
if(f->fim < f->inicio) // A fila está vazia ? printf("Fila vazia !");
else {
(f->inicio)++;
printf("Desenfileiramento efetuado com sucesso !"); }
Filas
Estado atual do vetor:
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
12/05/2015 44
Filas
DEQUEUE DEQUEUE ENQUEUE ENQUEUE
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
fim
O que acontecerá se
Filas
ENQUEUE
Sempre vai alocar um novo elemento na posição seguinte à
final, se esta posição estiver disponível.
O primeiro elemento sempre precede o último.
A fila pode “encher” se algum elemento for alocado na
última posição do vetor.
DEQUEUE
Apenas faz com que o valor da posição inicial da fila seja
incrementado de uma unidade, fazendo então a fila “andar”.
Como não há realocação de elementos, pode levar a
12/05/2015 46
Filas
Fila Circular
Fila
elementos inicio
fim
n
Filas
Fila circular
O primeiro elemento não necessariamente precederá o
último
Todas as células disponíveis podem ser utilizadas
Necessário saber a quantidade de elementos na fila, para
#define MAX 10
typedef struct strfila {
int elementos[MAX];
int inicio, fim, tamanho; } fila;
fila f;
Representando através de lista sequencial (vetor):
12/05/2015 48
Filas
1 2 3 4 5 6 7 8 ... MAX
Criando a fila:
void cria_fila(fila *f) {
f->inicio = 0; f->fim = -1;
f->tamanho = 0; }
Filas
f
elementos inicio
12/05/2015 50
Filas
ENQUEUE
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
fim
Filas
ENQUEUE
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
fim
12/05/2015 52
Filas
ENQUEUE
0 1 2 3 4 5 6 7 8 9
f
elementos inicio
fim
Filas
Enfileiramento (ENQUEUE): void enqueue(fila *f, int valor) {
if (f->tamanho == MAX) // A fila está cheia ? printf("A fila esta cheia !\n");
else {
f->fim =++(f->fim) % MAX; f->elementos[f->fim] = valor; (f->tamanho)++;
printf("Enfileiramento efetuado com sucesso !"); }
12/05/2015 54
Filas
Desenfileiramento (DEQUEUE): void dequeue(fila *f)
{
if (f->tamanho == 0) // A fila está vazia ? printf("Fila vazia !\n");
else {
f->inicio = ++(f->inicio) % MAX; (f->tamanho)--;
printf("Desenfileiramento efetuado com sucesso.\n"); }
Representando através de lista encadeada:
typedef struct strnode {
int valor;
struct *strnode proximo; } node;
typedef struct strfila {
node *inicio, *fim } fila;
fila f;
Filas
nó 1 nó 2 ... nó n
fila
Criando a fila:
void cria_fila(fila *f) {
f->inicio = NULL; f->fim = NULL; } ... int main() { fila f; ... cria_fila(&f); ... }
12/05/2015 56
Filas
início
f
Enfileiramento (ENQUEUE):
Filas
f
7
Enfileiramento (ENQUEUE):
12/05/2015 58
Filas
7 3
no f
Enfileiramento (ENQUEUE):
Filas
7 3 4
no f
Enfileiramento (ENQUEUE):
12/05/2015 60
Filas
7 3 4 1
no f
Enfileiramento (ENQUEUE):
Filas
7 3 4 1
f
12/05/2015 62
Filas
Enfileiramento (ENQUEUE):
void enqueue(fila *f, int valor) {
node *no = (node *) malloc(sizeof(node)); no->valor = valor;
no->proximo = NULL;
if (f->inicio == NULL) // A fila está vazia ? f->inicio = no;
else
f->fim->proximo = no; f->fim = no;
Filas
Exercício:
Implemente os procedimentos apresentados nas aulas de
Pilhas e Filas.
Implemente o procedimento DEQUEUE para uma fila