11 pilhas, filas e listas duplamente encadeadas prof. kariston pereira adaptado de material...
TRANSCRIPT
11
Pilhas, Filas eListas Duplamente Encadeadas
Prof. Kariston Pereira
Adaptado de Material gentilmente fornecido pelo Prof. Rui Tramontin (DCC/UDESC)
UDESC – Prof. Kariston Pereira 22
Introdução Pilhas Encadeadas Filas Encadeadas Listas Duplamente Encadeadas
Modelagem Operações
Índice
UDESC – Prof. Kariston Pereira 3
Introdução O conceito geral de lista encadeada pode ser
especializado e estendido das mais variadas formas:
Lista Especializada: Pilhas encadeadas Filas encadeadas
Lista Estendida: Listas Duplamente Encadeadas Listas Circulares Simples e Duplas
UDESC – Prof. Kariston Pereira 4
Pilhas Encadeadas São pilhas onde os elementos são
encadeados. Não há estouro de pilha. Como o acesso aos dados da pilha é puramente
sequencial, não há perda de eficiência.
Implementação das operações da pilha: Empilhar: equivale a adicionar no início Desempilhar: equivale a retirar do início.
UDESC – Prof. Kariston Pereira 5
Pilhas Encadeadas
3
Cabeçalho Elementos
info próximo
tam. topo
Rui
Computação
3
Maria
Computação
5
Paulo
Medicina
6
Elementode Informação
UDESC – Prof. Kariston Pereira 6
Filas Encadeadas Elementos são encadeados.
Estrutura do cabeçalho é modificada: Referência para o último elemento. É preciso modificar os algoritmos da lista encadeada
geral para levar em conta tal referência.
Operações: Adiciona no fim; Remove do início.
UDESC – Prof. Kariston Pereira 7
Filas Encadeadas
3info próximo
tam. início
Rui
Computação
3
Maria
Computação
5
Paulo
Medicina
6
fim
typedef struct { int tamanho; Elemento *inicio; Elemento *fim;} FilaEnc;
UDESC – Prof. Kariston Pereira 8
Criação da Fila Alocar espaço para cabeçalho; Definir tamanho = 0; Definir inicio e fim = NULL; Retornar cabeçalho.
FilaEnc *criaFila(){ FilaEnc *fila = (FilaEnc *) malloc(sizeof(FilaEnc)); if(fila != NULL) { fila->tamanho = 0; fila->inicio = NULL; fila->fim = NULL; } return fila; }
UDESC – Prof. Kariston Pereira 9
Adiciona na Filaint adicionaNaFila(FilaEnc *fila, TipoInfo *dados){ Elemento *novo = (Elemento *) malloc(sizeof(Elemento)); if(novo != NULL) { if(estah_vazia(fila)) fila->inicio = novo; else fila->fim->proximo = novo; novo->proximo = NULL; fila->fim = novo; fila->tamanho++; novo->info = dados; return fila->tamanho; } else return 0;}
UDESC – Prof. Kariston Pereira 10
Remove da FilaTipoInfo *removeDaFila(FilaEnc *fila){ if(estah_vazia(fila)) return NULL; else { Elemento *e = fila->inicio; TipoInfo *info = e->info; fila->inicio = e->proximo; if(fila->tamanho == 1) fila->fim = NULL; fila->tamanho--; free(e); return info; }}
UDESC – Prof. Kariston Pereira 11
Listas Duplamente Encadeadas
UDESC – Prof. Kariston Pereira 12
Introdução a LDE Listas encadeadas possuem a desvantagem de
permitir o percurso apenas em uma direção. Para acessar um elemento já visitado, é preciso uma
variável auxiliar que aponta para o elemento anterior.
O único meio para acessar outros elementos ainda anteriores consiste em começar de novo o percurso.
Uma Lista Duplamente Encadeada é uma estrutura de lista que permite o percurso em ambos os sentidos.
UDESC – Prof. Kariston Pereira 13
Introdução a LDE Listas duplamente encadeadas são úteis
para representar conjuntos de eventos ou objetos a serem percorridos em dois sentidos.
Exemplo: Itinerários de ônibus, trem, avião.
Busca aproximada de dados, onde é preciso se mover para e frente e trás.
UDESC – Prof. Kariston Pereira 14
LDE: Modelagem
3
info sucessor
tam. cabeça
Rui
Computação
3
Maria
Computação
5
Paulo
Medicina
6
antecessor
“Elemento Duplo”
typedef struct elementoDuplo { TipoInfo *info; struct elementoDuplo *antecessor; struct elementoDuplo *sucessor;} ElementoDuplo;
UDESC – Prof. Kariston Pereira 15
LDE: Aspecto Funcional Operações de criação e teste para ver
se está vazia são idênticas às da lista encadeada simples.
A diferença está nas operações de manipulação (no início, no fim, na posição, em ordem): adiciona(lista,dado) remove(lista) apaga(lista)
UDESC – Prof. Kariston Pereira 16
Adicionar no início Alocar espaço para elemento;
Associar dados ao campo “info”;
Campo “sucessor” do novo elemento aponta para onde o “cabeça” da lista aponta;
“antecessor” aponta para nulo.
“antecessor” do “sucessor” aponta para o novo elemento.
“cabeça” da lista aponta para novo elemento;
Incrementar tamanho da lista.
UDESC – Prof. Kariston Pereira 17
Adicionar no inícioint adicionaNoInicioDuplo(ListaDupla *lista, TipoInfo *dados){ ElementoDuplo *novo = (ElementoDuplo *) malloc(sizeof(ElementoDuplo)); if(novo != NULL) { novo->info = dados; novo->sucessor = lista->cabeca; novo->antecessor = NULL; if(novo->sucessor != NULL) novo->sucessor->antecessor = novo; lista->cabeca = novo; lista->tamanho++; return lista->tamanho; } else return 0;}
UDESC – Prof. Kariston Pereira 18
Remover do início Testar se está vazia erro!; Obter referência do primeiro elemento
(cabeça); Obter referência da informação; Cabeça da lista aponta para o “sucessor”
do primeiro elemento; Se o elemento possuir sucessor, o
antecessor do sucessor será nulo. Decrementar tamanho da lista; Desaloca elemento; Retornar referência para a informação.
UDESC – Prof. Kariston Pereira 19
Remover do inícioTipoInfo *retiraDoInicioDuplo(ListaDupla *lista){ if(estah_vazia(lista)) return NULL; else { ElementoDuplo *e = lista->cabeca; TipoInfo *info = e->info; lista->cabeca = e->sucessor; if(e->sucessor != NULL) e->sucessor->antecessor = NULL; lista->tamanho--; free(e); return info; }}
UDESC – Prof. Kariston Pereira 20
Adicionar no fim Se lista vazia, adicionar no início.
Caso geral: Obter a referência do primeiro elemento; Percorrer a lista, enquanto o próximo do
elemento atual não for nulo; Quando chegar no último elemento, repetir o
procedimento feito em adicionaNoInicio, mas: “sucessor” do novo elemento é nulo; “sucessor” do elemento atual aponta para o novo. “antecessor”do novo elemento aponta para o
elemento atual.
UDESC – Prof. Kariston Pereira 21
Adicionar no fimint adicionaNoFimDuplo(ListaDupla *lista, TipoInfo *dados){ if(estah_vazia(lista)) return adicionaNoInicioDuplo(lista, dados); else { ElementoDuplo *aux = lista->cabeca; while(aux->sucessor != NULL) //for(i=0; i < lista->tamanho-1; i++) aux = aux->sucessor; ElementoDuplo *novo = (ElementoDuplo *) malloc(sizeof(ElementoDuplo)); if(novo != NULL) { novo->sucessor = NULL; novo->info = dados; aux->sucessor = novo; novo->antecessor = aux; lista->tamanho++; return lista->tamanho; } }}
UDESC – Prof. Kariston Pereira 22
Exercício Remover do fim
Testar se está vazia erro!; Testar se há um elemento remove do início; Senão, percorrer até o último elemento e remover no fim.
Adicionar na posição Se (posiçao < 0 ou posição > lista->tamanho): erro,
posição inválida! Se (posiçao == 0): adiciona no início Se (posiçao == lista->tamanho): adiciona no fim Senão:
Percorrer a lista até a posição. Alocar elemento e arrumar ponteiros. Adicionar os dados ao novo elemento. Incrementar tamanho da lista.
UDESC – Prof. Kariston Pereira 23
Lista de Exercícios Implementar o TAD ListaDupla.
Ou seja, além das operações apresentadas em aula, implementar as demais operações: removeDoFim(lista) adicionaNaPosicao(lista, dado, pos) removeDaPosicao(lista, pos) adicionaEmOrdem(lista, dado)