Estruturas de Dados PROFESSOR DIÓGENES FURLAN
Estruturas de Dados (ED) Programas operam sobre dados Dados são relacionados e possuem estrutura Como representar e manipular dados num computador? ◦Devemos escolher a ED depois de analisar as operações que vamos realizar com os nossos dados
Exemplo – Cartas de Baralho Para representar um baralho precisamos: ◦Representar as cartas: naipe e valor struct carta { char naipe; char valor; }; ◦Representar o conjunto de cartas: ◦Ordem ◦Repetição Operações de manipulação: ◦Embaralhar as cartas ◦Comprar carta no topo do baralho ◦Colocar uma carta no fundo do baralho ◦Retirar uma carta aleatória do meio do baralho
Tipos de ED Linear ◦Listas ◦Filas ◦Pilhas Estrutural ◦Árvores ◦Grafos
Listas
Definição: ◦Em computação, lista é uma estrutura de dados abstrata que implementa uma coleção ordenada de objetos. ◦Numa lista, objetos podem aparecer repetidamente. ◦Para garantir ordem, precisa-se saber: ◦Quem é o primeiro ◦Quem é o próximo Exemplos: ◦Lista de compras do mercado ◦Lista telefônica ◦Dicionário
Listas - Operações Criar uma lista Verificar se uma lista está vazia Recuperar o tamanho da lista Inserir um elemento ◦No inicio ◦No fim ◦No meio Remover um elemento ◦No inicio ◦No fim ◦No meio Destruir uma lista
Listas – Implementação Em vetores Com nós encadeados
Listas em Vetores Prós: ◦Criar um vetor é muito simples ◦Não é necessário compreender ponteiros ou referencias Contras: ◦Limitações no tamanho da memória ◦Movimentação de memória aumenta custo computacional
struct Lista { int elementos[MAXTAM]; int last; };
struct Lista { int elementos[MAXTAM]; int last; }; //Detalhe de implementação: last aponta para a próxima posição a ser inserida void create(Lista &L) { L.last = 0; }
struct Lista { int elementos[MAXTAM]; int last; }; //Detalhe de implementação: last aponta para a próxima posição a ser inserida void create(Lista &L) { L.last = 0; } bool vazia(Lista &L) { return L.last == 0; }
struct Lista { int elementos[MAXTAM]; int last; }; //Detalhe de implementação: last aponta para a próxima posição a ser inserida void create(Lista &L) { L.last = 0; } bool vazia(Lista &L) { return L.last == 0; } int tamanho(Lista &L) { return L.last; }
struct Lista { int elementos[MAXTAM]; int last; }; //Detalhe de implementação: last aponta para a próxima posição a ser inserida void create(Lista &L) { L.last = 0; } bool vazia(Lista &L) { return L.last == 0; } int tamanho(Lista &L) { return L.last; } bool cheia(Lista &L) { return L.last >= MAXTAM; }
Operações Inserir o 3 (no inicio) Inserir o 20 (no fim) Inserir o 8 (no meio) Remover o 3 (do inicio) Remover o 20 (do fim) Remover o 10 (do meio) last
Inserir o 20 (no fim) O mais simples. void inserir_fim(Lista &L, int elem) { if(not(cheia(L))) { elementos[last] = elem; last++; } else Erro(); } last
Inserir o 20 (no fim) O mais simples. void inserir_fim(Lista &L, int elem) { if(not(cheia(L))) { elementos[last] = elem; last++; } else Erro(); } last
Inserir o 20 (no fim) O mais simples. void inserir_fim(Lista &L, int elem) { if(not(cheia(L))) { elementos[last] = elem; last++; } else Erro(); } last
Inserir o 3 (no inicio) O mais complexo: void inserir_inicio(Lista &L, int elem) { if(not(cheia(L))) { SobeUm(0, last-1); elementos[0] = elem; last++; } else Erro(); } last
Inserir o 3 (no inicio) O mais complexo: void inserir_inicio(Lista &L, int elem) { if(not(cheia(L))) { SobeUm(0, last-1); elementos[0] = elem; last++; } else Erro(); } last
Inserir o 3 (no inicio) O mais complexo: void inserir_inicio(Lista &L, int elem) { if(not(cheia(L))) { SobeUm(0, last-1); elementos[0] = elem; last++; } else Erro(); } last
Inserir o 3 (no inicio) O mais complexo: void inserir_inicio(Lista &L, int elem) { if(not(cheia(L))) { SobeUm(0, last-1); elementos[0] = elem; last++; } else Erro(); } last
Inserir o 8 (no meio) Inserir_meio(L1, 2, 8); void inserir_meio(Lista &L, int pos, int elem) { if(not(cheia(L))) { SobeUm(pos, last-1); elementos[pos] = elem; last++; } else Erro(); } last
Inserir o 8 (no meio) Inserir_meio(L1, 2, 8); void inserir_meio(Lista &L, int pos, int elem) { if(not(cheia(L))) { SobeUm(pos, last-1); elementos[pos] = elem; last++; } else Erro(); } last
Inserir o 8 (no meio) Inserir_meio(L1, 2, 8); void inserir_meio(Lista &L, int pos, int elem) { if(not(cheia(L))) { SobeUm(pos, last-1); elementos[pos] = elem; last++; } else Erro(); } last
Inserir o 8 (no meio) Inserir_meio(L1, 2, 8); void inserir_meio(Lista &L, int pos, int elem) { if(not(cheia(L))) { SobeUm(pos, last-1); elementos[pos] = elem; last++; } else Erro(); } last
Remover do fim X = remover_fim(L1); int remover_fim(Lista &L) { if(not(vazia(L))) { last--; return elementos[last]; } else Erro(); } last
Remover do fim X = remover_fim(L1); int remover_fim(Lista &L) { if(not(vazia(L))) { last--; return elementos[last]; } else Erro(); } last
Remover do fim X = remover_fim(L1); int remover_fim(Lista &L) { if(not(vazia(L))) { last--; return elementos[last]; } else Erro(); } last
Remover do inicio X = remover_inicio(L1); int remover_inicio(Lista &L) { if(not(vazia(L))) { int x = elementos[0]; DesceUm(0, last-1); last--; return x; } else Erro(); } last
Remover do inicio X = remover_inicio(L1); int remover_inicio(Lista &L) { if(not(vazia(L))) { int x = elementos[0]; DesceUm(0, last-1); last--; return x; } else Erro(); } last
Remover do inicio X = remover_inicio(L1); int remover_inicio(Lista &L) { if(not(vazia(L))) { int x = elementos[0]; DesceUm(0, last-1); last--; return x; } else Erro(); } last
Remover do inicio X = remover_inicio(L1); int remover_inicio(Lista &L) { if(not(vazia(L))) { int x = elementos[0]; DesceUm(0, last-1); last--; return x; } else Erro(); } last
Remover do meio X = remover_meio(L1, 1); int remover_meio(Lista &L, int pos) { if(not(vazia(L))) { int x = elementos[pos]; DesceUm(pos, last-1); last--; return x; } else Erro(); } last
Remover do meio X = remover_meio(L1, 1); int remover_meio(Lista &L, int pos) { if(not(vazia(L))) { int x = elementos[pos]; DesceUm(pos, last-1); last--; return x; } else Erro(); } last
Remover do meio X = remover_meio(L1, 1); int remover_meio(Lista &L, int pos) { if(not(vazia(L))) { int x = elementos[pos]; DesceUm(pos, last-1); last--; return x; } else Erro(); } last
Remover do meio X = remover_meio(L1, 1); int remover_meio(Lista &L, int pos) { if(not(vazia(L))) { int x = elementos[pos]; DesceUm(pos, last-1); last--; return x; } else Erro(); } last
Listas Encadeadas Prós: ◦Eficientes no custo de memória e processamento ◦Nunca acarreta em movimentar todos os elementos Contras: ◦Envolve conceitos mais avançados de programação ◦Ponteiros
struct Node { int elemento; struct Node *prox; }; struct Lista { Node *first; Node *last; };
struct Node { int elemento; struct Node *prox; }; struct Lista { Node *first; Node *last; }; void create(Lista &L) { L->first = L->last = NULL; } bool vazia(Lista &L) { return L->first == NULL; }
struct Node { int elemento; struct Node *prox; }; struct Lista { Node *first; Node *last; }; int tamanho(Lista &L) { int cont; Node *it; if(vazia(L)) return 0; for(cont=1, it=L->first; it!=L->last; cont++, it=it->prox); return cont; } void create(Lista &L) { L->first = L->last = NULL; } bool vazia(Lista &L) { return L->first == NULL; }
Inserir se Vazia (vale para todos) void inserir(Lista &L, int elem) { if(vazia(L)) { Node *node = new Node(); node->elemento = elem; node->prox = NULL; L->first = node; L->last = node; } last 5 first NULL
Operações Inserir o 3 (no inicio) Inserir o 20 (no fim) Inserir o 8 (no meio) Remover o 3 (do inicio) Remover o 20 (do fim) Remover o 10 (do meio) last first NULL
Inserir o 20 (no fim) void inserir_fim(Lista &L, int elem) { Node *node = new Node(); node->elemento = elem; node->prox = NULL; last->prox = node; last = node; } last first NULL20
Inserir o 20 (no fim) void inserir_fim(Lista &L, int elem) { Node *node = new Node(); node->elemento = elem; node->prox = NULL; last->prox = node; last = node; } last first NULL 20
Inserir o 20 (no fim) void inserir_fim(Lista &L, int elem) { Node *node = new Node(); node->elemento = elem; node->prox = NULL; last->prox = node; last = node; } last first NULL 20
Inserir o 3 (no inicio) void inserir_inicio(Lista &L, int elem) { Node *node = new Node(); node->elemento = elem; node>prox = first; first = node; } last first NULL 20 3
Inserir o 3 (no inicio) void inserir_inicio(Lista &L, int elem) { Node *node = new Node(); node->elemento = elem; node>prox = first; first = node; } last first NULL 20 3
Inserir o 3 (no inicio) void inserir_inicio(Lista &L, int elem) { Node *node = new Node(); node->elemento = elem; node>prox = first; first = node; } last first NULL 15 20
Inserir o 8 (no meio) void inserir_meio(Lista &L, int pos, int elem) { Node *node = new Node(); node->elemento = elem; ante = L->first; for(int cont=1; cont<pos; cont++) ante = ante->prox; node>prox = ante->prox; ante->prox = node; } first NULL last
Inserir o 8 (no meio) void inserir_meio(Lista &L, int pos, int elem) { Node *node = new Node(); node->elemento = elem; ante = L->first; for(int cont=1; cont<pos; cont++) ante = ante->prox; node>prox = ante->prox; ante->prox = node; } first NULL last ante
Inserir o 8 (no meio) void inserir_meio(Lista &L, int pos, int elem) { Node *node = new Node(); node->elemento = elem; ante = L->first; for(int cont=1; cont<pos; cont++) ante = ante->prox; node>prox = ante->prox; ante->prox = node; } 3 5 first 8 ante last NULL
Inserir o 8 (no meio) void inserir_meio(Lista &L, int pos, int elem) { Node *node = new Node(); node->elemento = elem; ante = L->first; for(int cont=1; cont<pos; cont++) ante = ante->prox; node>prox = ante->prox; ante->prox = node; } 3 5 first 8 ante last NULL
Inserir o 8 (no meio) void inserir_meio(Lista &L, int pos, int elem) { Node *node = new Node(); node->elemento = elem; ante = L->first; for(int cont=1; cont<pos; cont++) ante = ante->prox; node>prox = ante->prox; ante->prox = node; } last first NULL
Remover o 3 (do inicio) int remover_inicio(Lista &L) { Node *node = first; first = first->prox; return node->elem; } last first NULL node
Remover o 3 (do inicio) int remover_inicio(Lista &L) { Node *node = first; first = first->prox; return node->elem; } last first NULL node
Remover o 3 (do inicio) int remover_inicio(Lista &L) { Node *node = first; first = first->prox; return node->elem; } last first NULL node
Remover o 20 (do fim) int remover_fim(Lista &L) { ante = first; for(; ante->prox!=last; ) ante=ante->prox; Node *node = last; last = ante; last->prox = NULL; return node->elem; } last 5 8 first NULL ante
Remover o 20 (do fim) int remover_fim(Lista &L) { ante = first; for(; ante->prox!=last; ) ante=ante->prox; Node *node = last; last = ante; last->prox = NULL; return node->elem; } node 5 8 first NULL last
Remover o 20 (do fim) int remover_fim(Lista &L) { ante = first; for(; ante->prox!=last; ) ante=ante->prox; Node *node = last; last = ante; last->prox = NULL; return node->elem; } 5 8 first NULL last 20 node
Remover o 10 (do meio) int remover_meio(Lista &L, int pos) { ante = first; for(cont=1; cont<pos; cont++) ante=ante->prox; Node *node = ante->prox; ante->prox = node->prox; return node->elem; } 5 8 first NULL last ante
Remover o 10 (do meio) int remover_meio(Lista &L, int pos) { ante = first; for(cont=1; cont<pos; cont++) ante=ante->prox; Node *node = ante->prox; ante->prox = node->prox; return node->elem; } 5 8 first NULL last ante node
Remover o 10 (do meio) int remover_meio(Lista &L, int pos) { ante = first; for(cont=1; cont<pos; cont++) ante=ante->prox; Node *node = ante->prox; ante->prox = node->prox; return node->elem; } 5 8 first NULL 15 last ante 10 node
Variantes de Listas Listas FIFO (First In First Out), ou Filas Listas LIFO (Last In First Out), ou Pilhas Listas Duplamente Encadeadas
Filas
Definição: ◦Tipo de lista onde os elementos entram pelo fim e saem pelo começo (ou entram pelo inicio e saem pelo fim). ◦Os elementos são inseridos por uma extremidade e removidos pela outra. ◦Segue uma ordem de chegada. Usos: ◦No banco ◦Na lotérica ◦No ponto de ônibus ◦Nos órgãos públicos ◦Na entrada do estacionamento ◦... ◦Fila de processos
Filas - Operações Criar uma fila Verificar se uma fila está vazia Recuperar o tamanho da fila Inserir um elemento ◦No inicio Remover um elemento ◦No fim Destruir uma fila
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover fim inicio
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover fim inicio
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover fim inicio
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover fim inicio
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover fim inicio 5
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover fim inicio 10
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover fim inicio 15
Pilhas
Definição: ◦Tipo de lista onde os elementos entram e saem pelo topo. Usos: ◦Solução de expressões matemáticas ◦Guardar variáveis locais em chamadas recursivas de funções
Pilhas - Operações Criar uma pilha Verificar se uma pilha está vazia Recuperar o tamanho da pilha Inserir um elemento ◦No topo Remover um elemento ◦No topo Destruir uma pilha
Testando Inserir o 3 Inserir o 20 Inserir o 8 Remover topo
Testando Inserir o 3 (push) Inserir o 20 Inserir o 8 Remover topo
Testando Inserir o 3 Inserir o 20 (push) Inserir o 8 Remover topo
Testando Inserir o 3 Inserir o 20 Inserir o 8 (push) Remover topo
Testando Inserir o 3 Inserir o 20 Inserir o 8 (push) Remover (pop) Remover topo 8
Testando Inserir o 3 Inserir o 20 Inserir o 8 (push) Remover Remover (pop) Remover topo 20
Testando Inserir o 3 Inserir o 20 Inserir o 8 (push) Remover Remover (pop) topo 3
Vamos às Aplicações Práticas