Open JayCesar opened 1 year ago
Código da aula:
// Aula do dia 14/09 - Quinta-feira
// Listas Ligadas Dinâmicas
#include <malloc.h>
# include <stdbool.h>
typedef struct estrutura {
int chave;
int info;
struct estrutura *prox;
} NO;
typedef struct {
NO* inicio;
} LISTA;
// BUSCA
NO* busca(LISTA *l, int ch, NO* *ant){ // busca ....... &ant (ficaria assim a implementação)
*ant = NULL;
NO* p = l->inicio;
while (p){
if(p->chave = ch) return p;
if(p->chave > ch) return NULL; // Só funciona em uma lista ordenada por chave
*ant = p;
p = p->prox;
}
return NULL; // Isso é caso não funcione em nenhum dos casos acima
}
// TODO: Colocar lado a lado (busca diâmica e Busca sequencial)
// TODO: Por que ' NO* *ant)';
// Eu posso modificar ele - NO* *ant (Eu posso fazer o que precisar com isso)
// EXCLUSÃO
bool excluir(LISTA *l, int ch){
NO* ant;
NO* atual = busca(l, ch, &ant);
if (atual == NULL) return false; // Ou if (!atual)
if (ant) ant->prox = atual->prox; // se existe um anterior
else l->inicio = atual->prox; // Caso seja o primeiro item e não haja algo antes
// Depois preciso fazer o free (liberar o espaço);
free(atual);
return true;
}
// INSERÇÃO (ela insere na ordem);
bool inserir(LISTA *l, int ch){
NO* ant;
NO* atual = busca(l, ch, &ant);
if(atual) return false; // Já existe
NO* novo = (NO*) malloc(sizeof(NO)); // Aqui o NO sem asteriscos é a estrutura, o tipo!
novo->chave = ch;
// Agora preciso tratar os casos de inserção
// Caso haja um anterior
// Agora verifico se a lista está vazia (se não existe início) e já aplico os dois casos
if(ant) {
novo->prox = ant->prox;
ant->prox = novo;
}
else{
novo->prox = l->inicio; // Lista vazia é quando o iníccio é null
l->inicio = novo;
}
return true;
}
// (1) MOVER Ch para frente da lista (versão 1);
// (2) MOVER P para frente da lista (versão 2);
// (Versão 1);
void moverChParaInicio(LISTA *l, int ch){ // Aqui é um caso especial
NO* ant;
if(l->inicio && l->inicio->chave == ch) return; // Passo 1: preciso mover?
NO* p = busca(l, ch, &ant); // Passo 2: Busca
if(ant) ant->prox = p->prox; // Passo 3: Recortar o elemento
else l->inicio = p->prox;
// Agora movo para o início da lista
p->prox = l->inicio; // Passo 4: Colocar no início
l->inicio = p;
}
// Obs: A (versão 2) ele fez na lousa mas não consegui anotar
// Destruir a lista
void destruir(LISTA* l){
NO* p = l->inicio;
while(p){
NO* aux = p->prox;
free(p);
p = aux;
}
l->inicio = NULL;
}
// Seja uma lista que aceita chaves repetidas, sem ordem;
// Problema: eliminar todas ocorrências de uma chave ch
// Seja uma lista que aceita chaves repetidas, sem ordem;
// Problema: eliminar todas ocorrências de uma chave ch
CH = 5
Código da aula A cada elemento novo a gente aloca memória e quando não usamos mais a gente libera ela. A lista é ligada porque cada elemento aponta pra seu próximo. Antes a implementação era estática, ou seja, envolvia a criação de um arranjo;
Alocaremos e desalocaremos a memória para os elementos sob demanda Vantagens: Não precisamos gastar memória que não estamos usando e não precisamos gerenciar uma lista de elementos disponíveis.
#include <stdio.h>
#include <malloc.h>
typedef int bool;
typedef int TIPOCHAVE;
typedef struct {
TIPOCHAVE chave;
// outros campos..
} REGISTRO;
typedef struct aux{
REGISTRO reg;
struct aux* prox;
} ELEMENTO;
typedef ELEMENTO* PONT;
typedef struct {
PONT inicio;
} LISTA;
int tamanho(LISTA* l){
PONT end = l->inicio;
int tam = 0;
while(end != NULL){
tam++;
end = end->prox;
}
return tam;
}
void exibirLista(LISTA* l){
PONT end = l->inicio;
printf("Lista: \" ");
printf("%i ", end->reg.chave);
end = end->prox;
printf("\"\"n");
}
// Buscar por um elemento na estrutura
// (1) Sem estar ordenanda:
PONT buscaSequencial(LISTA* l, TIPOCHAVE ch){
PONT pos = l->inicio;
while(pos != NULL){
if (pos->reg.chave == ch) return pos;
pos = pos->prox;
}
return NULL;
}
// (2) Lista ordenada pelos valores das cahves dos registros (Ordenada)
PONT buscaSeqOrd(LISTA* l, TIPOCHAVE ch){
PONT pos = l->inicio;
while(pos != NULL && pos->reg.chave < ch) pos = pos->prox;
if (pos != NULL & pos->reg.chave == ch) return pos;
return NULL;
}
Precisaremos de uma função auxiliar!
Obs: ou seja, eu retorno um valor e salvo também outro valor num espaço de memória que vem como parâmetro.;
// Inserir elementos na estrutura
// (1) Função auxiliar que vai verificar se o elemento que quero inserir já existe:
PONT buscaSequencialEx(LISTA* l, TIPOCHAVE ch, PONT* ant){
*ant = NULL;
PONT atual = l->inicio;
while((atual != NULL) && (atual->reg.chave<ch)){
*ant = atual;
atual = atual->prox;
}
if((atual != NULL) && (atual->reg.chave == ch)) return atual;
return NULL;
// IMPORTANTE: Independente se encontrar ou não, a variável ant terá o endereço do elemento anterior ao que deve ser inserido
}
// (2) Insersão ordenada:
bool inserirElemListaOrd(LISTA* l, REGISTRO reg){
TIPOCHAVE ch = reg.chave;
PONT ant, i;
i = buscaSequencialEx(l, ch, &ant);
if(i != NULL) return false; // Ou seja, já existe
i = (PONT) malloc(sizeof(ELEMENTO)); // Senão ele aloca memória para esse elemento
i->reg = reg;
if(ant == NULL){ // Caso seja o primeiro
i->prox = l->inicio;
l->inicio = i;
} else{ // Caso não saja o primeiro
i->prox = ant->prox;
ant->prox = i;
}
return true;
}
// Exclusão de um elemento
bool excluirElmLista(LISTA* l, TIPOCHAVE ch){
PONT ant, i;
i = buscaSequencialEx(l,ch,&ant);
if (i == NULL) return false;
if (ant == NULL) l->inicio = i->prox; // Caso seja o primeiro
else ant->prox = i->prox; // Caso não seja o primeiro
free(i); // Libero o i
}
// Reinicialização da lista
// Precisamos liberar/excluir todos os elementos dentro da lista (não basta só dizer que início é NULL)
void reinicializarLista(LISTA* l){
PONT end = l->inicio;
// Eu preciso de uma auxiliar porque preciso saber quem é o próximo elemento. Ela se chama apagar
while (end != NULL){
PONT apagar = end; // Essa é a variável auxiliar
end = end->prox;
free(apagar);
}
l->inicio = NULL;
}
Excluindo um elemento:
Isso cria uma bolinha perdida no espaço da memória e cheia de lixo;