Março 2012
Panorâmica
Listas Lineares, Encadeadas e Duplamente Encadeadas
FILAS E PILHAS
Paulo Cesar Lopes Email: paulo_cesar_lopes@yahoo.com
•
Bibliografia
•
LISTAS
–
Conceitos e Recursos
–
Objetivos e Caracterísitcas
–
Operações
–
Definições e Implementações
•
LISTAS LINEARES
–
LISTA ENCADEADA
– Cacterísticas/Conceitos e Estrutura•
LISTA DUPLAMENTE ENCADEADA
–
Conceito e implementação
•
PILHAS (LIFO) E FILAS (FIFO).
Março 2012
Bibliografia
• MANZANO, José Augusto N. G.; OLIVEIRA, Jayr Figueiredo. Algoritmos: lógica
para desenvolvimento de programação de computadores. 17.ed. São Paulo: Érica, 2005.
• ASCENCIO, Ana Fernanda Gomes; VENERUCHI, Edilene Aparecida.
Fundamentos de programação de computadores: algoritmos, C/C++ e C/C++.
São Paulo: Prentice Hall, 2002.
• FERRARI, Fabricio; CECHINEL, Cristian; Apostila de Introdução a Algoritmos e
Estrutura de Dados. Universidade Federal do Pampa. Disponível em
http://www.dcc.ufam.edu.br/david/dmdocuments/Introducao-a-algoritmos.pdf
• Listas Encadeadas:
www.dep.ufmg.br/professores/miranda/InAlgol/Listas.pdf. • Listas encadeadas implementadas em C.
http://www.ime.usp.br/~pf/algoritmos/aulas/lista.html
• Programar em C/Listas encadeadas
http://pt.wikibooks.org/wiki/Programar_em_C/Listas_encadeadas
Conceitos e Recursos
Estruturas de dados armazena dados na memória do computador a fim de
permitir o acesso eficiente/eficaz aos mesmos.
A maioria das estruturas de dados consideram a memória primária (a chamada
RAM) como pilhas, filas, árvores binárias de busca, árvores AVL e árvores
rubro-negras.
Outras são especialmente projetadas e adequadas para serem armazenadas
em memórias secundárias como o disco rígido, e.g. B-árvores. Uma estrutura
de dado bem projetada permite a manipulação eficiente, em tempo e em
Março 2012
Lista lineares
Uma lista linear é um conjunto de n elementos (de informações)
x
1, x
2, ..., x
n,
cuja propriedade estrutural envolve as posições relativas de seus
elementos. Supondo n (numero de elementos) > 0, temos :
• x
1é o primeiro elemento
• para 1 < k < n, x
ké precedido por x
k−1e seguido por x
k+1• x
né o último elemento.
1
k n
Objetivos e Características
Operações Importantes com Listas Lineares
Algumas operações que podemos querer realizar sobre listas lineares:
• Ter acesso ao k-ésimo elemento, a fim de examinar ou alterar o conteúdo de
seus campos;
• Inserir um elemento novo antes ou depois de k-ésimo elemento;
• Remover o k-ésimo elemento;
• Ordenar uma lista em ordem crescente ou decrescente;
• Criar lista combinando 2 ou mais listas lineares;
• Dividir uma lista linear em duas ou mais;
• Copiar uma lista linear em um outro espaço.
Existem casos importantes em que as listas lineares recebem nomes
como pilha ou fila conforme a maneira que as operações são realizadas.
Março 2012
Operações
Operações Importantes com Listas Lineares
A maneira de implementar listas lineares depende da classe de
operações mais frequentes. Não existe, em geral, uma única
implementação para a qual todas as operações são eficientes.
Qual seria as estruturas mais eficientes para:
1. ter acesso fácil ao k-ésimo elemento;
Definições e Implementações
• Elemento: guarda as informações sobre cada
elemento.
Para isso define-se cada elemento como uma estrutura que
possui:
campos de informações
ponteiro para o próximo elemento
info
prox
Março 2012
Listas Lineares
Características
– Tamanho da lista não é pré-definido
– Cada elemento guarda quem é o próximo
– Elementos não estão contíguos na memória
info
info
prox
info
NULL
info
NULL
info
NULL
prox
prox
Características/Conceitos e Estrutura
Uma lista pode ter uma célula cabeça
info
prox
prox
info
prox
info
NULL
Uma lista pode ter um apontador para o último
elemento
Último
NULL
Cabeça
Último
CabeçaMarço 2012 Algoritmos e Estrutura de Dados I info prox prox info prox info NULL Último
Posições de onde pode incluir:
1ª. posição
última posição
elemento qualquer E
info
prox
prox
info
prox
info
NULL
Último
info
NULL
prox
Características/Conceitos e Estrutura
Inserindo
em posição
Intermediária.
Março 2012 Algoritmos e Estrutura de Dados I info prox prox info prox info NULL Último
Posições de onde pode retirar:
1ª. posição
última posição
elemento qualquer E
info
prox
prox
info
prox
info
NULL
Último
Anterior
NULL
Características/Conceitos e Estrutura
Eliminando o
último.
Março 2012
// Lista encadeada de inteiros // Autor : WEB #include <stdio.h> #include <stdlib.h> #include <malloc.h> struct lista { int info;
struct lista* prox; };
typedef struct lista Lista; Lista* inicializa (void); Lista* insere (Lista *l, int i); void imprime (Lista *l); int vazia (Lista *l);
Lista* busca (Lista *l, int v); void libera (Lista *l);
Lista* retira (Lista *l, int v);
Implementando em C – Lista Encadeada com manipulação dispersa
int main (void) {
Lista *l; /* declara uma lista não iniciada */ l = inicializa(); /* inicia lista vazia */
l = insere(l, 150); /* insere na lista o elemento 23 */ l = insere(l, 45); /* insere na lista o elemento 45 */ l = insere(l, 56); /* insere na lista o elemento 56 */ l = insere(l, 78); /* insere na lista o elemento 78 */ printf("Imprime a primeira vez...\n");
imprime(l); /* imprimirá: 78 56 45 23 */
printf("Imprime a segunda vez... apos retirar 78 ...\n"); l = retira(l, 78);
imprime(l); /* imprimirá: 56 45 23 */
printf("Imprime a segunda vez... apos retirar 45 ...\n"); l = retira(l, 45); imprime(l); /* imprimirá: 56 23 */ system("pause"); libera(l); return 0; }
Devemos notar que trata-se de uma estrutura
auto-referenciada, pois, além do campo que armazena a
informação (no caso, um número inteiro), há um campo
que é um ponteiro para uma próxima estrutura do
mesmo tipo. Embora não seja essencial, é uma
boa estratégia definirmos o tipo Lista como sinônimo de
struct lista, O tipo Lista representa um nó da lista e a
estrutura de lista encadeada é representada pelo
ponteiro para seu primeiro elemento (tipo Lista*).
Implementando em C – Lista Encadeada com manipulação dispersa
/* função de inicialização: retorna uma lista vazia */ Lista* inicializa (void)
{
return NULL; }
/* inserção no início: retorna a lista atualizada */ Lista* insere (Lista *l, int i)
{
Lista* novo = (Lista *) malloc(sizeof(Lista)); novo->info = i;
novo->prox = l; return novo; }
/* função imprime: imprime valores dos elementos */ void imprime (Lista *l)
{
Lista *p; /* variável auxiliar para percorrer a lista */ for (p = l; p != NULL; p = p->prox) {
/* função vazia: retorna 1 se vazia ou 0 se não vazia */
int vazia (Lista *l) { if (l == NULL) return 1; else return 0; }
void libera (Lista *l) {
Lista *p = l;
while (p != NULL) {
Lista *t = p->prox; /* guarda referência para o próximo elemento */
free(p); /* libera a memória apontada por p */
Março 2012
Implementando em C – Lista Encadeada com manipulação dispersa
/* função retira: retira elemento da lista */
Lista *retira (Lista *l, int v) {
Lista *ant = NULL; /* ponteiro para elemento anterior */
Lista *p = l; /* ponteiro para percorrer a lista*/ /* procura elemento na lista, guardando anterior */
while (p != NULL && p->info != v) { /* procura elemento */
ant = p; /* guardando anterior */
p = p->prox; }
if (p == NULL) /* verifica se achou elemento */
return l; /* não achou: retorna lista original */ /* retira elemento */
if (ant == NULL) {
/* retira elemento do inicio */
l = p->prox; }
else {
/* retira elemento do meio da lista */
ant->prox = p->prox; }
free(p); return l; }
/* função busca: busca um elemento na lista */
Lista* busca (Lista *l, int v) {
Lista *p;
for (p=l; p!=NULL; p=p->prox) if (p->info == v)
return p;
return NULL; /* não achou o elemento */
cabeça
P
X
Primeiro
Último
Março 2012
LISTA CIRCULAR
O último elemento que entrou na lista deverá possuir ponteiro para o
primeiro da lista. Veja exemplo no SITE.
LIFO – Last Input First Output - Pilha
O último elemento que entrou na pilha será o primeiro a sair da pilha, a
pilha é conhecida como uma estrutura do tipo LIFO (“Last In First Out”).
Exemplo Clássico:
Pilhas de pratos dentro do bojo da pia.
Exemplos na Computação:
chamada de procedimentos, para armazenar o endereço de retorno (e os
parâmetros reais). Notação polonesa de calculadoras ou pós-fixa.
Março 2012
LIFO – Last Input First Output - Pilha
// PILHA em VETOR #include <stdio.h> #include <stdlib.h> #include <malloc.h> #define MAX 50 struct pilha { int n; float vet[MAX]; };typedef pilha Pilha; // Prototipos
Pilha *cria (void);
void push (Pilha *p, float v); float pop (Pilha *p);
void libera (Pilha *p); int vazia (Pilha *p); void imprime (Pilha* p);
main() { float N; Pilha *P; P = cria(); N = 20; push(P,N); N = 30; push(P,N); N = 29; push(P,N); imprime(P); N = pop(P);
printf(" Tirou do topo o %.2f. O topo = %d\n", N,P->n); N = pop(P);
printf(" Tirou do topo o %f. O topo = %d\n", N,P->n); N = pop(P);
printf(" Tirou do topo o %f. O topo = %d\n", N,P->n); N = pop(P);
printf(" Tirou do topo o %f. O topo = %d\n", N,P->n); system("pause");
}
IMPLEMENTA PILHA UTILIZANDO
VETOR COM ALOCAÇÃO DINÂMICA DE MEMÓRIA
Março 2012
LIFO – Last Input First Output - Pilha
// A função que verifica se a pilha está vazia pode ser dada por: int vazia (Pilha* p)
{
return (p->n == 0); }
// Função para liberar a memória alocada pela pilha pode ser: void libera (Pilha* p)
{
free(p); }
/* imprime Pilha vetor */ void imprime (Pilha* p) {
int i;
for (i=p->n-1; i>=0; i--)
printf("Pilha %f\n",p->vet[i]); }
// Cria inicializado a PILHA
Pilha *cria (void)
{ // Aloca vetor na memória
Pilha *p = (Pilha*) malloc(sizeof(Pilha));
p->n = 0; /* inicializa com zero elementos */
return p;
LIFO – Last Input First Output - Pilha
float pop (Pilha* p)
{
float v;
if (vazia(p)) {
printf("Pilha vazia.\n");
system("pause");
exit(1); /* aborta programa */
}
/* retira elemento do topo */
v = p->vet[p->n-1];
p->n--;
return v;
}
// Coloca elemento no topo
void push (Pilha* p, float v)
{ // Insere na pilha
if (p->n == MAX) { /* capacidade esgotada */
printf("Capacidade da pilha estourou.\n");
exit(1); /* aborta programa */
}
/* insere elemento na próxima posição livre */
printf(“NO TOPO = %d o no. %f \n",p->n,v);
p->vet[p->n] = v;
p->n++;
}
Março 2012
FIFO – First Input First Output - Fila
Fila: A inserção de novos elementos são realizadas numa extremidade da
lista e todas as remoções são feitas na outra extremidade.
Exemplo Clássico: fila de banco.
Exemplo Computação: Num sistema operacional, os processos prontos
para entrar em execução (aguardando CPU) são geralmente mantidos
numa fila.
Existe um tipo de fila em que as retiradas de elementos da fila depende
de uma prioridade estabelecida para cada elemento. O elemento de maior
prioridade da fila é o próximo a ser retirado (fura fila). Tal fila recebe o
FIFO – First Input First Output - Fila
info prox prox info prox info NULL ÚltimoMarço 2012