Você está na página 1de 10

Igor de Oliveira da Silva

PEDRO LUCAS DE LIMA KENOR


1) Faça uma função que remova um aluno dada a sua respectiva matricula. Sua função
deve reajustar os ponteiros ant e prox assim que remover o elemento, não esqueça de
verificar se a elemento que será removido está em uma célula que é a primeira ou a última
ou alguma célula do meio da lista, para cada posição o ajuste dos ponteiros é diferente.

nt remove_lista_mat(Lista* li, int mat) {


if(li == NULL)
return 0;
Elem *no = *li;
while(no != NULL && no->dados.matricula != mat) {
no = no->prox;
}
if(no == NULL) // Elemento não encontrado
return 0;

if(no->ant == NULL) { // Remove do início


*li = no->prox;
if(no->prox != NULL)
no->prox->ant = NULL;
} else {
if(no->prox != NULL) { // Remove do meio
no->ant->prox = no->prox;
no->prox->ant = no->ant;
} else { // Remove do final
no->ant->prox = NULL;
}
}
free(no);
return 1;
}

R: Esta função começa verificando se a lista está vazia ou não inicializada. Em seguida, ela
percorre a lista até encontrar o nó com a matrícula desejada. A função então verifica se o nó
é o primeiro, o último ou um nó do meio para ajustar os ponteiros ant e prox
adequadamente antes de liberar o nó.

2) Faça uma função que insira um novo elemento na lista de forma ordenada, lembrando
que essa inserção pode acontecer para o novo elemento no início, no fim e no meio da lista
dependendo da ordem da mesma. Utilize a função insere_lista_ordenada da lista
encadeada como base para criar essa função.

int insere_lista_ordenada(Lista* li, struct aluno al) {


if(li == NULL)
return 0;

Elem* no = (Elem*) malloc(sizeof(Elem));


if(no == NULL)
return 0;

no->dados = al;

if(lista_vazia(li)) { // Inserção quando a lista está vazia


no->prox = NULL;
no->ant = NULL;
*li = no;
return 1;
}
else {
Elem *ante, *atual = *li;
while(atual != NULL && atual->dados.matricula < al.matricula) {
ante = atual;
atual = atual->prox;
}

if(atual == *li) { // Inserção no início


no->ant = NULL;
(*li)->ant = no;
no->prox = (*li);
*li = no;
} else { // Inserção no meio ou no final
no->prox = ante->prox;
no->ant = ante;
ante->prox = no;
if(atual != NULL)
atual->ant = no;
}
}
return 1;
}

Esta função começa verificando se a lista existe e se a alocação de memória para o novo
elemento foi bem-sucedida. Em seguida, ela verifica se a lista está vazia. Se estiver, o novo
elemento é simplesmente inserido. Se não estiver, a função percorre a lista até encontrar a
posição correta para o novo elemento, atualizando os ponteiros ant e prox conforme
necessário.
3) Faça um função que conte quantos alunos tem uma nota qualquer n1 igual, com o
seguinte protótipo int conta_lista_nota(Lista* li, int n1). A função deve utilizar apenas o
ponteiro li passado como parâmetro, não pode ser criado nenhum outro ponteiro auxiliar. Ao
final além de informar a quantidade alunos com a mesma nota, o ponteiro li deve estar
apontado para a primeira célula “cabeça” da lista.

int conta_lista_nota(Lista* li, float nota) {

if (li == NULL || *li == NULL) {

return 0; // Retorna 0 se a lista ou a lista vazia forem nulas.

int cont = 0; // Inicializa o contador de ocorrências.

Elem* atual = *li; // Cria um ponteiro para percorrer a lista.

do {

if (atual->dados.n1 == nota) {

cont++; // Incrementa o contador se a nota coincidir.

atual = atual->prox; // Move para o próximo elemento.

} while (atual != *li); // Continua até retornar ao início da lista.

return cont; // Retorna o número de ocorrências da nota na lista.

4) Refaça as funções de inserir e remover no início e fim para que a lista comporte-se de
forma circular. No fim, faça uma função que para percorrer a lista inteira utilizando o
comportamento circular da mesma.

typedef Elem* Lista;


int insere_lista_final_circ(Lista* li, struct aluno al) {

if (li == NULL)

return 0;

Elem* no = (Elem*)malloc(sizeof(Elem));

if (no == NULL)

return 0;

no->dados = al;

no->prox = no;

if ((*li) == NULL) {

no->ant = no;

*li = no;

} else {

Elem* aux = *li;

while (aux->prox != (*li)) {

aux = aux->prox;

aux->prox = no;

no->ant = aux;

(*li)->ant = no;

no->prox = (*li);

}
return 1;

int insere_lista_inicio_circ(Lista* li, struct aluno al) {

if (li == NULL)

return 0;

Elem* no = (Elem*)malloc(sizeof(Elem));

if (no == NULL)

return 0;

no->dados = al;

no->prox = no;

no->ant = no;

if (*li != NULL) {

if ((*li)->prox == *li) {

(*li)->ant = no;

(*li)->prox = no;

no->ant = *li;

no->prox = *li;

} else {

(*li)->ant = no;

Elem* auxF = *li;

while (auxF->prox != *li) {

auxF = auxF->prox;

}
auxF->prox = no;

no->prox = (*li);

no->ant = auxF;

*li = no;

return 1;

void imprime_lista_circ(Lista* li) {

if (li == NULL)

return;

Elem* no = *li;

do {

printf("Matricula: %d\n", no->dados.matricula);

printf("Nome: %s\n", no->dados.nome);

printf("Notas: %f %f %f\n", no->dados.n1, no->dados.n2, no->dados.n3);

printf("-------------------------------\n");

no = no->prox;

} while (no != (*li));

int remove_lista_inicio_circ(Lista* li) {

if (li == NULL)

return 0;
if ((*li) == NULL)

return 0;

Elem* no = *li;

Elem* auxF = *li;

while (auxF->prox != (*li)) {

auxF = auxF->prox;

if (no->prox == (*li) && no->ant == (*li)) {

*li = NULL;

} else {

*li = no->prox;

(*li)->ant = auxF;

auxF->prox = *li;

free(no);

return 1;

int remove_lista_final_circ(Lista* li) {

if (li == NULL)

return 0;

if ((*li) == NULL)

return 0;
Elem* no = *li;

while (no->prox != (*li))

no = no->prox;

if (no->ant == (*li) && no->prox == (*li))

*li = NULL;

else {

no->ant->prox = *li;

(*li)->ant = no->ant;

free(no);

return 1;

int main() {

Lista lista = NULL;

struct aluno aluno1 = {1, "Aluno 1", 8.5, 9.0, 7.5};

struct aluno aluno2 = {2, "Aluno 2", 7.0, 8.0, 6.5};

insere_lista_final_circ(&lista, aluno1);

insere_lista_inicio_circ(&lista, aluno2);

imprime_lista_circ(&lista);
remove_lista_inicio_circ(&lista);

remove_lista_final_circ(&lista);

imprime_lista_circ(&lista);

return 0;

implementa uma lista circular duplamente encadeada para armazenar informações de


alunos. A lista tem funções para inserir alunos no início e no final, imprimir os alunos e
remover alunos do início e do final.

5) Faça uma estrutura do tipo Fila utilizando o conceito de lista duplamente ou


simplesmente encadeada, você pode escolher qual irá utilizar. É preciso criar as funções
Enfileirar e Desenfileirar. Essas funções devem utilizar o conceito de nó descritor (nodesc),
que é uma estrutura que controla onde está a célula inicial da lista e a célula final, a
inserção e remoção na fila deve utilizar apenas os nós que estão na estrutura do nó
descritor. Abaixo segue as duas estruturas que serão usadas, a função que inicializa o nó
descritor e o cabeçalho das funções.

int enfileirar(struct nodesc *no, int elem) {


struct fila *novo = (struct fila*) malloc(sizeof(struct fila));
if(novo == NULL)
return 0;

novo->info = elem;
novo->prox = NULL;
novo->ant = no->fim;

if(no->fim == NULL) { // Fila vazia


no->ini = novo;
} else {
no->fim->prox = novo;
}
no->fim = novo;
return 1;
}

Desenfileirar
A função desenfileirar remove um elemento do início da fila:

int desenfileirar(struct nodesc *no, int *elem) {


if(no->ini == NULL)
return 0;

struct fila *temp = no->ini;


*elem = temp->info;

no->ini = temp->prox;
if(no->ini != NULL) {
no->ini->ant = NULL;
} else {
no->fim = NULL;
}

free(temp);
return 1;
}

Neste código, a função enfileirar insere um novo elemento no final da fila, atualizando o nó
descritor conforme necessário. A função desenfileirar remove um elemento do início da fila
e também atualiza o nó descritor.

Você também pode gostar