Download - LISTAS

Transcript
Page 1: LISTAS

LISTASDilvan Moreira, parcialmente baseado em material do prof. Ricardo Campello

Page 2: LISTAS

Lista Linear

Estrutura de representação de informação em que os elementos são mantidos de forma linear, ou seja, dispostos um após o outro Ex. listas de nomes, de valores, de pessoas, etc.

Pode ser ordenada ou não Estruturação de informação em listas ocorre em vários domínios P. ex. lista telefônica

Page 3: LISTAS

Lista Linear

Operação Básica em Listas: Busca

por um elemento através de uma “chave” Ex. busca na lista telefônica: dado um nome, buscamos o telefone

Inserção e Remoção de elementos: Implementação depende da organização da lista manipulação distinta de listas ordenadas e não ordenadas

Page 4: LISTAS

TAD para Lista

Inicializar lista (p. ex. vazia): void Definir(Lista *L);

Inserir elemento: void Inserir(tipo_elem e, Lista *L);

Localizar a posição (na lista) de um elemento dado: int Localizar(tipo_elem e, Lista *L); retorna a posição do elemento na lista retorna um valor inválido caso ele não esteja na lista

Page 5: LISTAS

TAD para Lista

Acessar elemento em posição dada: tipo_elem Buscar(intp, Lista *L);

retorna o elemento da lista na posição fornecida sem alterá-la

se posição não existir, retorna um valor inválido

Eliminar elemento na posição dada: int Remover(intp, Lista *L);

Retorna 1 (true) se bem sucedida Retorna 0 (false) se posição dada é inválida

Obter número de elementos na lista: int Tamanho(Lista *L);

Page 6: LISTAS

TAD para Lista

Apagar a lista: void Apagar(Lista *L);

Destruir a lista: void Destruir(Lista *L);

lista não é mais acessível (só para implementações dinâmicas)

Obter posição seguinte à do último elemento: int Fim(Lista *L);

Verificar se lista está vazia, verificar se está cheia...

...

Page 7: LISTAS

EDs Estáticas para Listas Realizações Estáticas (vetores):

Seqüencial: seqüência de elementos disponíveis de forma consecutiva

Encadeada: seqüência de elementos disponíveis de forma não consecutiva

Page 8: LISTAS

EDs Dinâmicas para Listas Realizações Dinâmicas (ponteiros e memória): Simplesmente Encadeada:

Encadeamento de ponteiros unidirecional

Duplamente Encadeada: Encadeamento de ponteiros bidirecional

Cada realização possui vantagens e desvantagens

Page 9: LISTAS

Lista Estática Sequencial Implementação a Seguir:

Exemplo de Lista Estática Seqüencial em C

Projetada para Lista Não Ordenada Adaptação para lista ordenada como exercício no final

Page 10: LISTAS

Lista Estática Sequencial#define MAX 100 /* Max. Tamanho da Lista */#define TRUE 1#define FALSE 0#define bool int

typedef struct{ Tipo_1 chave; /* P. ex. int chave; */Tipo_2 info; /* P. ex. char info[50] */

} elem; /* Tipo do Elemento */

typedef struct{ int nelem;elem A[MAX+1];

} Lista; /* Tipo da Lista */

Lista L; /* Exemplo de Declaração*/

Page 11: LISTAS

Lista Estática Sequencialvoid Definir(Lista *L){ /* O(1) */

/* Define uma lista vazia */L->nelem= 0;L->A[0].chave = 0; /* Célula não utilizada */L->A[0].info[0] = '\0'; /* Célula não utilizada */

}

int Tamanho(Lista *L){ /* O(1) */

/* Retorna o tamanho da Lista (0 caso vazia) */ return L->nelem;

}

Page 12: LISTAS

Lista Estática Sequencialint Fim(Lista *L){ /* O(1) */

/* Retorna a posição após o último elemento da lista */return (L->nelem + 1);

}

bool Lista_vazia(Lista *L){ /* O(1) *//* Retorna true se lista vazia, false caso contrário */return (L->nelem == 0);

}

bool Lista_cheia(Lista *L){ /* O(1) */ /* Retorna true se lista cheia, false caso contrário */return (L->nelem == MAX);

}

Page 13: LISTAS

Lista Estática Sequencialbool Inserir(elem* x, int p, Lista *L){/* Insere elemento x na posição p da Lista L. Se a lista é tal que L=a1,a2,...,ap,...,an então L=a1,a2,...,ap-1,x,ap+1,...,an. Se p=Fim(L) então L=a1,a2,...,an,x. Devolve true se sucesso, false c.c. (L cheia ou não tem posição p). L não ordenada! */

int atual;if (Lista_cheia(L))

return FALSE; /* lista cheia */else if (p > Fim(L) || p < 1)

return FALSE; /* posição não existe */else {

for(atual = L->nelem; atual >= p; atual--)L->A[atual+1] = L->A[atual];

L->A[p]= *x;L->nelem++; return TRUE; /* inserção com sucesso */

} } /* O(L.nelem) no pior caso. Qual o pior caso? */

Page 14: LISTAS

Lista Estática Sequencialint Localizar(elem* x, Lista *L){ /* Retorna a posição de x na Lista. Se x ocorre mais de uma vez, retorna posição da 1a ocorrência. Se x não ocorre, retorna 0 */

int atual = 1;if (!Lista_vazia(L)){

while(atual <= L->nelem){if(igual(&A[atual], x)) /* iguais ?*/

return atual; /* retorno sucesso */

else atual++;}

}return 0; /* retorno em insucesso ou lista vazia */

} /* O(L.nelem) no pior caso. Qual o pior caso? */

Page 15: LISTAS

Lista Estática Sequencialbool igual(elem* a, elem* b) { /* Testa igualdade entre elementos por algum critério particular */

return (a->chave==b->chave);} /* O(1) */

elem* Buscar(int p, Lista *L){/* Retorna elem. da posição p, ou elem. inválido se p é inválida */

if (p >= Fim(L) || p < 1 || Lista_vazia(L))return x; /* retorna elemento inválido */

else return &(L->A[p]);} /* O(1) */

Page 16: LISTAS

Lista Estática Sequencialbool Remover(int p, Lista *L){/* Remove o elemento da posição p da Lista. Se L = a1,a2,...,an então tem-se a1,a2,...,ap-1,ap+1,...,an. Devolve true se sucesso, false c.c. (L não tem posição p, inclusive se p = Fim(L)) */

int atual;if(p >= Fim(L) || p < 1 || Lista_vazia(L)) return

FALSE;else {

for (atual = p+1; atual <= L->nelem; atual++) L->A[atual-1] = L->A[atual];

L->nelem--; } return TRUE;

} /* O(L.nelem) no pior caso. Qual o pior caso? */

.

Page 17: LISTAS

Lista Estática Sequencial em C++ Como ficaria essa implementação em C++?

Seria muito diferente?

Page 18: LISTAS

Lista Estática Sequencial Orig.#define MAX 100 /* Max. Tamanho da Lista */#define TRUE 1#define FALSE 0#define bool int

typedef struct{ char info[50]; /* P. ex. char info[50] */

} elem; /* Tipo do Elemento */

typedef struct{ int nelem;tipo_elem A[MAX+1];

} Lista; /* Tipo da Lista */

Lista L; /* Exemplo de Declaração*/

Page 19: LISTAS

Lista Estática Sequencial em C++#define MAX 100 /* Max. Tamanho da Lista */#define TRUE 1#define FALSE 0#define bool int

class Elem { char info[50]; /* P. ex. char info[50] */

…} /* Tipo do Elemento */ class List {

int nelem;tipo_elem A[MAX+1];

…} /* Tipo da Lista */

Page 20: LISTAS

Lista Estática Sequencial Orig.void Definir(Lista *L){ /* O(1) */

/* Define uma lista vazia */L->nelem= 0;L->A[0].info[0] = '\0'; /* Célula não utilizada */

}

int Tamanho(Lista *L){ /* O(1) */

/* Retorna o tamanho da Lista (0 caso vazia) */ return L->nelem;

}

Page 21: LISTAS

Lista Estática Sequencial em C++void Lista::Lista(){ /* O(1) */

/* Define uma lista vazia */nelem= 0;A[0].info[0] = '\0'; /* Célula não utilizada */

}

int Lista::Tamanho(){ /* O(1) */

/* Retorna o tamanho da Lista (0 caso vazia) */ return nelem;

}

Page 22: LISTAS

Lista Estática Sequencial Orig.int Fim(Lista *L){ /* O(1) */

/* Retorna a posição após o último elemento da lista */return (L->nelem + 1);

}

bool Lista_vazia(Lista *L){ /* O(1) *//* Retorna true se lista vazia, false caso contrário */return (L->nelem == 0);

}

bool Lista_cheia(Lista *L){ /* O(1) */ /* Retorna true se lista cheia, false caso contrário */return (L->nelem == MAX);

}

Page 23: LISTAS

Lista Estática Sequencial C++int List::Fim(){ /* O(1) */

/* Retorna a posição após o último elemento da lista */return (nelem + 1);

}

bool List::Lista_vazia(){ /* O(1) *//* Retorna true se lista vazia, false caso contrário */return (nelem == 0);

}

bool List::Lista_cheia(){ /* O(1) */ /* Retorna true se lista cheia, false caso contrário */return (nelem == MAX);

}

Page 24: LISTAS

Lista Estática Sequencial Orig.bool Inserir(elem* x, int p, Lista *L){/* Insere elemento x na posição p da Lista L. Se a lista é tal que L=a1,a2,...,ap,...,an então L=a1,a2,...,ap-1,x,ap+1,...,an. Se p=Fim(L) então L=a1,a2,...,an,x. Devolve true se sucesso, false c.c. (L cheia ou não tem posição p). L não ordenada! */

int atual;if (Lista_cheia(L))

return FALSE; /* lista cheia */else if (p > Fim(L) || p < 1)

return FALSE; /* posição não existe */else {

for(atual = L->nelem; atual >= p; atual--)L->A[atual+1] = L->A[atual];

L->A[p] = *x;L->nelem++; return TRUE; /* inserção com sucesso */

} } /* O(L.nelem) no pior caso. Qual o pior caso? */

Page 25: LISTAS

Lista Estática Sequencial C++bool List::Inserir(Elem* x, int p){/* Insere elemento x na posição p da Lista L. Se a lista é tal que L=a1,a2,...,ap,...,an então L=a1,a2,...,ap-1,x,ap+1,...,an. Se p=Fim(L) então L=a1,a2,...,an,x. Devolve true se sucesso, false c.c. (L cheia ou não tem posição p). L não ordenada! */

int atual;if (Lista_cheia())

return FALSE; /* lista cheia */else if (p > Fim() || p < 1)

return FALSE; /* posição não existe */else {

for(atual = nelem; atual >= p; atual--)A[atual+1] = A[atual];

A[p] = *x;nelem++; return TRUE; /* inserção com sucesso */

} } /* O(L.nelem) no pior caso. Qual o pior caso? */

Page 26: LISTAS

Lista Estática Sequencial Origint Localizar(elem* x, Lista *L){ /* Retorna a posição de x na Lista. Se x ocorre mais de uma vez, retorna posição da 1a ocorrência. Se x não ocorre, retorna 0 */

int atual = 1;if (!Lista_vazia(L)){

while(atual <= L->nelem){if(igual(&L->A[atual], x))

return atual; /* retorno em sucesso */

else atual++;}

}return 0; /* retorno em insucesso ou lista vazia */

} /* O(L.nelem) no pior caso. Qual o pior caso? */

Page 27: LISTAS

Lista Estática Sequencial C++int List::Localizar(Elem* x){ /* Retorna a posição de x na Lista. Se x ocorre mais de uma vez, retorna posição da 1a ocorrência. Se x não ocorre, retorna 0 */

int atual = 1;if (!Lista_vazia()){

while(atual <= nelem){if(A[atual].Igual(x))

return atual; /* retorno em sucesso */

else atual++;}

}return 0; /* retorno em insucesso ou lista vazia */

} /* O(L.nelem) no pior caso. Qual o pior caso? */

Page 28: LISTAS

Lista Estática Sequencial Origbool igual(elem* a, elem* b) { /* Testa igualdade entre elementos por algum critério particular */

return (strcmp(a->chave,b->chave)==0);} /* O(1) */

elem* Buscar(int p, Lista *L){/* Retorna elem. da posição p, ou elem. inválido se p é inválida */

if (p >= Fim(L) || p < 1 || Lista_vazia(L))return x; /* retorna elemento inválido */

else return L->A[p];} /* O(1) */

Page 29: LISTAS

Lista Estática Sequencial C++bool Elem::igual(elem* b) { /* Testa igualdade entre elementos por algum critério particular */

return (strcmp(info,b->info)==0);} /* O(1) */

Elem* List::Buscar(int p){/* Retorna elem. da posição p, ou elem. inválido se p é inválida */

if (p >= Fim() || p < 1 || Lista_vazia())return null; /* retorna inválido */

else return &A[p];} /* O(1) */

Page 30: LISTAS

Lista Estática Sequencial Origbool Remover(int p, Lista *L){/* Remove o elemento da posição p da Lista. Se L = a1,a2,...,an então tem-se a1,a2,...,ap-1,ap+1,...,an. Devolve true se sucesso, false c.c. (L não tem posição p, inclusive se p = Fim(L)) */

int atual;if(p >= Fim(L) || p < 1 || Lista_vazia(L)) return

FALSE;else {

for (atual = p+1; atual <= L->nelem; atual++) L->A[atual-1] = L->A[atual];

L->nelem--; } return TRUE;

} /* O(L.nelem) no pior caso. Qual o pior caso? */

.

Page 31: LISTAS

Lista Estática Sequencial C++bool List::Remover(int p){/* Remove o elemento da posição p da Lista. Se L = a1,a2,...,an então tem-se a1,a2,...,ap-1,ap+1,...,an. Devolve true se sucesso, false c.c. (L não tem posição p, inclusive se p = Fim(L)) */

int atual;if(p >= Fim() || p < 1 || Lista_vazia()) return

FALSE;else {

for (atual = p+1; atual <= nelem; atual++) A[atual-1] = A[atual];

nelem--; } return TRUE;

} /* O(L.nelem) no pior caso. Qual o pior caso? */

.

Page 32: LISTAS

Checando

1. Modifique a operação Remover do TAD Lista Estática Seqüencial para que esta retorne o elemento removido e não um valor lógico.

2. Modifique a operação Localizar do TAD Lista Estática Seqüencial para que esta receba apenas a chave do elemento procurado e não o elemento todo.

3. Modifique a operação Localizar do TAD Lista Estática Seqüencial para que esta retorne um ponteiro para uma cópia do elemento localizado, cópia esta alocada dinamicamente em memória. Retorne NULL se o elemento não existir na lista.

4. Implemente o TAD Lista Estática Seqüencial em C, de forma modular, com módulos separados de interface (arquivo .h) e implementação (arquivo .c), e faça alguns testes.aula

Page 33: LISTAS

Checando

5. Modifique a oImplemente uma nova operação de inserção para o TAD Lista Estática Seqüencial para substituir aquela que foi apresentada anteriormente nesses slides (Inserir). Essa nova operação deve inserir o novo elemento de forma a manter sempre a lista ordenadapelas chaves dos seus elementos.

5. OBS: Como a lista deve ser mantida ordenada, essa operação deve determinar a posição de inserção automaticamente, não recebê-la como parâmetro. Nesse exercício, faça isso percorrendo um a um os elementos da lista a partir do início (depois vide exercício 7).

Page 34: LISTAS

Checando

6. Considerando que a operação de inserção utilizada no TAD Lista Estática Seqüencial é aquela implementada no exercício 5, reimplemente também a operação Localizar do TAD para que esta faça uso do fato da lista estar ordenada para realizar uma busca muito mais eficiente (binária) pelo elemento desejado.

6. Qual o tempo de execução assintótico (BIG-O) de pior caso da operação acima ? Qual o pior caso? Justifique.

7. Estando a nova operação de localização via busca binária do exercício 6 disponível, é possível utilizá-la para simplificar a implementação da operação de inserção ordenada do exercício 5? Explique.

Page 35: LISTAS

Bibliografia

N. Ziviani, Projeto de Algoritmos, Thomson, 2a. Edição, 2004

A. M. Tenembaum et al., Data Structures Using C, Prentice-Hall, 1990

J. L. Szwarcfiter & L. Markenzon, Estruturas de Dados e seus Algoritmos, LTC, 1994

Page 36: LISTAS

Perguntas?