Skip to content

Instantly share code, notes, and snippets.

@danielsource
Last active May 11, 2025 14:12
Show Gist options
  • Save danielsource/082a0200038081ee6061bf034d3a79aa to your computer and use it in GitHub Desktop.
Save danielsource/082a0200038081ee6061bf034d3a79aa to your computer and use it in GitHub Desktop.
Random crappy code, please ignore.
Algoritmos e Estruturas de Dados 1
Atividade Avaliativa 1
Pilhas, Filas e Lista
Questão 1 (1.0 ponto): Supondo as operações básicas de pilha (LIFO
- Last In, First Out) e fila (FIFO - First In, First Out), você
precisa simular a sequência de operações dada e determinar o estado
final de cada estrutura de dados utilizada. Para isso, considere as
seguintes operações sendo realizadas em uma estrutura de dados
inicialmente vazia:
1. Empilhar(5) 6. Enfileirar(15)
2. Enfileirar(10) 7. Desenfileirar()
3. Empilhar(3) 8. Empilhar(8)
4. Enfileirar(20) 9. Desenfileirar()
5. Desempilhar() 10. Desempilhar()
Após a execução de todas essas operações, descreva o estado final
da(s) estrutura(s) de dados envolvida(s). Se mais de uma estrutura
for usada, deixe claro qual estado pertence a qual estrutura.
==== RESPOSTA =====================================================
ESTADOS:
1. Pilha: [5]; é empilhado 5 no topo da pilha.
2. Fila: [10]; é enfileirado 10 no final da fila.
3. Pilha: [3,5]; é empilhado 3 no topo da pilha.
4. Fila: [10,20]; é enfileirado 20 no final da fila.
5. Pilha: [5]; é desempilhado 3 do topo da pilha.
6. Fila: [10,20,15]; é enfileirado 15 no final da fila.
7. Fila: [20,15]; é desenfileirado 10 do início da fila.
8. Pilha: [8,5]; é empilhado 8 no topo da pilha.
9. Fila: [15]; é desenfileirado 20 do início da fila.
10. Pilha: [5]; é desempilhado 3 do topo da pilha.
No estado final, a pilha contém o elemento 5 e a fila contém o elemento 15.
/*
Algoritmos e Estruturas de Dados 1
Atividade Avaliativa 1
Pilhas, Filas e Lista
Questão 2 (2.0 pontos): Implemente em C uma função chamada
'inverterFilaComPilhas' que recebe uma fila F e retorna uma nova
fila com os elementos de F em ordem reversa, utilizando uma ou mais
pilhas como estrutura auxiliar. A fila original F não deve ser
modificada ao final da execução da função.
*/
#include <stdio.h>
#include <stdlib.h>
/**** CÓDIGO DA FILA ****/
typedef struct NodeFila NodeFila;
struct NodeFila {
int data;
NodeFila *next;
};
typedef struct {
NodeFila *front;
} Fila;
Fila *criarFila(void) {
Fila *f;
f = malloc(sizeof(Fila));
f->front = NULL;
return f;
}
void enfileirar(Fila *f, int data) {
NodeFila *n, *new;
new = malloc(sizeof(NodeFila));
new->data = data;
new->next = NULL;
if (!f->front) {
f->front = new;
return;
}
for (n = f->front; n->next; n = n->next);
n->next = new;
}
int desenfileirar(Fila *f) {
NodeFila *n;
int data;
data = f->front->data;
n = f->front->next;
free(f->front);
f->front = n;
return data;
}
int filaVazia(Fila *f) {
return !f->front;
}
void imprimirFila(Fila *f) { /* (omitido na prova) */
NodeFila *n;
if (filaVazia(f)) {
puts("NULL");
return;
}
for (n = f->front; n->next; n = n->next)
printf("%d -> ", n->data);
printf("%d -> NULL\n", n->data);
}
/**** CÓDIGO DA PILHA ****/
typedef struct NodePilha NodePilha;
struct NodePilha {
int data;
NodePilha *next;
};
typedef struct {
NodePilha *top;
} Pilha;
Pilha *criarPilha(void) {
Pilha *p;
p = malloc(sizeof(Pilha));
p->top = NULL;
return p;
}
void empilhar(Pilha *p, int data) {
NodePilha *n;
n = malloc(sizeof(NodePilha));
n->data = data;
n->next = p->top;
p->top = n;
}
int desempilhar(Pilha *p) {
NodePilha *n;
int data;
data = p->top->data;
n = p->top->next;
free(p->top);
p->top = n;
return data;
}
int pilhaVazia(Pilha *p) {
return !p->top;
}
/**** IMPLEMENTAÇÃO DE 'inverterFilaComPilhas' ****/
Fila *inverterFilaComPilhas(Fila F) {
NodeFila *n;
Fila *inv;
Pilha *aux;
inv = criarFila();
aux = criarPilha();
for (n = F.front; n; n = n->next)
empilhar(aux, n->data);
while (!pilhaVazia(aux))
enfileirar(inv, desempilhar(aux));
free(aux);
return inv;
}
int main(void) {
Fila *filaOriginal, *filaInvertida;
NodeFila *atual, *temp;
filaOriginal = criarFila();
enfileirar(filaOriginal, 1);
enfileirar(filaOriginal, 2);
enfileirar(filaOriginal, 3);
enfileirar(filaOriginal, 4);
printf("Fila original: ");
imprimirFila(filaOriginal);
filaInvertida = inverterFilaComPilhas(*filaOriginal);
printf("Fila invertida: ");
imprimirFila(filaInvertida);
atual = filaInvertida->front;
while (atual != NULL) {
temp = atual;
atual = atual->next;
free(temp);
}
free(filaInvertida);
atual = filaOriginal->front;
while (atual != NULL) {
temp = atual;
atual = atual->next;
free(temp);
}
free(filaOriginal);
return 0;
}
/* Exemplo de compilação: cc -std=c89 -O0 -g -fsanitize=address,leak,undefined -Wall -Wextra -Wpedantic -Werror -Wno-unused-parameter aed1-1-q02.c && ./a.out */
/*
Algoritmos e Estruturas de Dados 1
Atividade Avaliativa 1
Pilhas, Filas e Listas
Questão 3 (2.5 pontos): Suponha uma lista simplesmente encadeada
de números inteiros. Escreva um algoritmo em C para verificar se
essa lista é uma palíndromo. Um palíndromo é uma sequência que é
lida da mesma forma da esquerda para a direita e da direita para
a esquerda (ex: 1 -> 2 -> 2 -> 1). Utilize uma pilha como
estrutura auxiliar.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/**** CÓDIGO DA LISTA ENCADEADA ****/
typedef struct Node Node;
struct Node {
int valor;
Node *next;
};
typedef struct {
Node *head;
} LinkedList;
LinkedList *criarLista(void) {
LinkedList *lista;
lista = malloc(sizeof(LinkedList));
lista->head = NULL;
return lista;
}
void inserirFinal(LinkedList *lista, int valor) {
Node *n, *new;
new = malloc(sizeof(Node));
new->valor = valor;
new->next = NULL;
if (!lista->head) {
lista->head = new;
return;
}
for (n = lista->head; n->next; n = n->next);
n->next = new;
}
void liberarLista(LinkedList *lista) {
Node *n, *next;
for (n = lista->head; n; n = next) {
next = n->next;
free(n);
}
free(lista);
}
void imprimirLista(LinkedList *lista) { /* (omitida da prova) */
Node *n;
if (!lista->head) {
puts("NULL");
return;
}
for (n = lista->head; n->next; n = n->next)
printf("%d -> ", n->valor);
printf("%d -> NULL\n", n->valor);
}
/**** CÓDIGO DA PILHA ****/
typedef struct StackNode StackNode;
struct StackNode {
int valor;
StackNode *next;
};
typedef struct {
StackNode *top;
} Stack;
Stack *criarPilha(void) {
Stack *pilha;
pilha = malloc(sizeof(Stack));
pilha->top = NULL;
return pilha;
}
void empilhar(Stack *pilha, int valor) {
StackNode *n;
n = malloc(sizeof(StackNode));
n->valor = valor;
n->next = pilha->top;
pilha->top = n;
}
int desempilhar(Stack *pilha) {
StackNode *n;
int valor;
valor = pilha->top->valor;
n = pilha->top->next;
free(pilha->top);
pilha->top = n;
return valor;
}
bool pilhaVazia(Stack *pilha) {
return !pilha->top;
}
void liberarPilha(Stack *pilha) {
while (!pilhaVazia(pilha))
desempilhar(pilha);
free(pilha);
}
/**** CÓDIGO DO PALÍNDROMO ****/
bool ehPalindromoLista(LinkedList *lista) {
Stack *pilha;
Node *n;
pilha = criarPilha();
for (n = lista->head; n; n = n->next)
empilhar(pilha, n->valor);
for (n = lista->head; n; n = n->next) {
if (n->valor != desempilhar(pilha)) {
liberarPilha(pilha);
return false;
}
}
liberarPilha(pilha);
return true;
}
int main(void) {
LinkedList *lista1, *lista2, *lista3, *lista4, *lista5;
/* Teste 1: palíndromo */
lista1 = criarLista();
inserirFinal(lista1, 1);
inserirFinal(lista1, 2);
inserirFinal(lista1, 2);
inserirFinal(lista1, 1);
printf("Lista 1 é palíndromo? %s\n",
ehPalindromoLista(lista1) ? "Sim" : "Não");
liberarLista(lista1);
/* Teste 2: não palíndromo */
lista2 = criarLista();
inserirFinal(lista2, 1);
inserirFinal(lista2, 2);
inserirFinal(lista2, 3);
printf("Lista 2 é palíndromo? %s\n",
ehPalindromoLista(lista2) ? "Sim" : "Não");
liberarLista(lista2);
/* Teste 3: palíndromo com comprimento ímpar */
lista3 = criarLista();
inserirFinal(lista3, 1);
inserirFinal(lista3, 2);
inserirFinal(lista3, 1);
printf("Lista 3 é palíndromo? %s\n",
ehPalindromoLista(lista3) ? "Sim" : "Não");
liberarLista(lista3);
/* Teste 4: lista vazia */
lista4 = criarLista();
printf("Lista 4 é palíndromo? %s\n",
ehPalindromoLista(lista4) ? "Sim" : "Não");
liberarLista(lista4);
/* Teste 5: lista com um elemento */
lista5 = criarLista();
inserirFinal(lista5, 5);
printf("Lista 5 é palíndromo? %s\n",
ehPalindromoLista(lista5) ? "Sim" : "Não");
liberarLista(lista5);
return 0;
}
/* (Isso é um código auxiliar para o arquivo aed1-1-q04.c) */
/**** CÓDIGO DA FILA DA Q2 ADAPTADO PARA Q4 ****/
typedef struct NodeFila NodeFila;
struct NodeFila {
Tarefa *t;
NodeFila *next;
};
typedef struct {
NodeFila *front;
} Fila;
Fila *criarFila(void) {
Fila *f;
f = malloc(sizeof(Fila));
f->front = NULL;
return f;
}
void enfileirar(Fila *f, Tarefa *t) {
NodeFila *n, *new;
new = malloc(sizeof(NodeFila));
new->t = t;
new->next = NULL;
if (!f->front) {
f->front = new;
return;
}
for (n = f->front; n->next; n = n->next);
n->next = new;
}
Tarefa *desenfileirar(Fila *f) {
NodeFila *n;
Tarefa *t;
t = f->front->t;
n = f->front->next;
free(f->front);
f->front = n;
return t;
}
int filaVazia(Fila *f) {
return !f->front;
}
/*
Algoritmos e Estruturas de Dados 1
Atividade Avaliativa 1
Pilhas, Filas e Listas
Questão 4 (4.5 pontos): Imagine que você precisa processar uma
série de tarefas. Algumas tarefas precisam ser processadas na
ordem em que chegam (como em uma fila), enquanto outras têm
prioridade e precisam ser processadas imediatamente (como em uma
pilha de interrupções).
É necessário utilizar uma estruturas de dados (ou uma combinação
de estruturas que possa lidar eficientemente com essa situação,
permitindo adicionar tarefas comuns e tarefas prioritárias, e
também remover a próxima tarefa a ser processada (dando
prioridade às tarefas prioritárias). Utilize a proposta abaixo
para a implementação.
Proposta de Estrutura de Dados:
- Use duas filas separadas:
1. Fila de prioridade: Para as tarefas com alta prioridade.
Novas tarefas prioritárias são adicionadas ao final desta fila
(comportamento de fila dentro da prioridade).
2. Fila comum: Para as tarefas regulares, adicionadas e
removidas em ordem FIFO.
- Funcionamento:
* Adicionar tarefa comum: A tarefa é enfileirada na fila comum.
* Adicionar tarefa prioritária: A tarefa é enfileirada na fila
de prioridade.
* Remover próxima tarefa:
1. Primeiro, verificamos se a fila de prioridade não está
vazia. Se não estiver, desenfileiramos e retornamos a tarefa
da frente desta fila (FIFO dentro da prioridade).
2. Se a fila de prioridade estiver vazia, então
desenfileiramos e retornamos a tarefa da frente da fila
comum.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
/**** CÓDIGO DA FILA DE TAREFAS ****/
typedef struct Tarefa Tarefa;
/* Definições da estrutura de 'Fila' (reutilizando da Q2) */
#include "aed1-1-q04-fila.c"
struct Tarefa {
char *descricao;
};
Fila *criarFilaTarefa(void) {
return criarFila();
}
void enfileirarTarefa(Fila *f, char *descricao) {
Tarefa *t;
t = malloc(sizeof(Tarefa));
t->descricao = malloc(strlen(descricao) + 1);
strcpy(t->descricao, descricao);
enfileirar(f, t);
}
Tarefa *desenfileirarTarefa(Fila *f) {
return desenfileirar(f);
}
bool filaTarefaVazia(Fila *f) {
return filaVazia(f);
}
/**** CÓDIGO DO GERENCIADOR ****/
typedef struct {
Fila *com, *pri;
} GerenciadorTarefas;
GerenciadorTarefas *criarGerenciador(void) {
GerenciadorTarefas *g;
g = malloc(sizeof(GerenciadorTarefas));
g->com = criarFilaTarefa();
g->pri = criarFilaTarefa();
return g;
}
void adicionarTarefaComum(GerenciadorTarefas *g, char *descricao) {
enfileirarTarefa(g->com, descricao);
}
void adicionarTarefaPrioritaria(GerenciadorTarefas *g, char *descricao) {
enfileirarTarefa(g->pri, descricao);
}
Tarefa *proximaTarefa(GerenciadorTarefas *g) {
Tarefa *t = NULL;
if (!filaTarefaVazia(g->pri)) {
t = desenfileirarTarefa(g->pri);
} else if (!filaTarefaVazia(g->com)) {
t = desenfileirarTarefa(g->com);
}
return t;
}
void liberarGerenciador(GerenciadorTarefas *g) {
Tarefa *tarefa;
while ((tarefa = proximaTarefa(g)) != NULL) {
free(tarefa->descricao);
free(tarefa);
}
free(g->com);
free(g->pri);
free(g);
}
int main(void) {
GerenciadorTarefas *gerenciador;
Tarefa *tarefa;
gerenciador = criarGerenciador();
adicionarTarefaComum(gerenciador, "Atualizar relatório");
adicionarTarefaPrioritaria(gerenciador, "Corrigir bug crítico");
adicionarTarefaComum(gerenciador, "Enviar e-mails");
adicionarTarefaPrioritaria(gerenciador, "Deploy da nova versão");
while ((tarefa = proximaTarefa(gerenciador)) != NULL) {
printf("%s\n", tarefa->descricao);
free(tarefa->descricao);
free(tarefa);
}
liberarGerenciador(gerenciador);
return 0;
}
/* SOMA DE INTEIROS POSITIVOS LONGOS USANDO LISTAS CIRCULARES
Exemplo: ./big-sum-circular 18446744073709551616 81553255926290448384
*/
#include <inttypes.h> /* para PRIu32 */
#include <stdint.h> /* para uint32_t e UINT32_MAX */
#include <stdio.h> /* para printf() */
#include <stdlib.h> /* para malloc() e free() */
#define BIGINT_DATA_HEADER (UINT32_MAX) /* Valor usado para distinguir
o cabeçalho dos outros nós. */
#define BIGINT_DATA_MAX (999999999) /* Valor máximo inteiro sem sinal
que cada nó pode manter. */
typedef uint32_t u32;
typedef struct BigInt BigInt;
struct BigInt {
u32 data;
BigInt *next;
};
BigInt *bigint_new(void) {
BigInt *x;
x = malloc(sizeof(*x));
x->data = BIGINT_DATA_HEADER;
x->next = x;
return x;
}
void bigint_prepend(BigInt *a, u32 data) {
BigInt *x;
x = bigint_new();
x->data = data;
x->next = a->next;
a->next = x;
}
void bigint_append(BigInt *a, u32 data) {
BigInt *x;
if (a->next == a) {
bigint_prepend(a, data);
return;
}
for (x = a->next; x->next != a; x = x->next)
;
x->next = bigint_new();
x->next->data = data;
x->next->next = a;
}
void bigint_delete(BigInt *a) {
if (a->next->data != BIGINT_DATA_HEADER)
bigint_delete(a->next);
free(a);
}
u32 bigint_strlen(const char *s) {
u32 len = 0;
while (*s++)
++len;
return len;
}
BigInt *bigint_from_str(const char *s) {
BigInt *x;
u32 len, val, unit, c;
x = bigint_new();
len = bigint_strlen(s);
while (len > 0) {
val = 0;
for (unit = 1; unit < BIGINT_DATA_MAX && len > 0; unit *= 10, --len) {
c = s[len-1];
if (c < '0' || c > '9') {
bigint_delete(x);
return NULL;
}
val += unit * (c-'0');
}
bigint_append(x, val);
}
return x;
}
BigInt *bigint_add(BigInt *a, BigInt *b) {
BigInt *x;
u32 carry, total;
x = bigint_new();
a = a->next;
b = b->next;
carry = 0;
while (a->data != BIGINT_DATA_HEADER &&
b->data != BIGINT_DATA_HEADER) {
total = a->data + b->data + carry;
bigint_prepend(x, total % (BIGINT_DATA_MAX+1));
x = x->next;
a = a->next;
b = b->next;
carry = total / (BIGINT_DATA_MAX+1);
}
while (a->data != BIGINT_DATA_HEADER) {
total = a->data + carry;
bigint_prepend(x, total % (BIGINT_DATA_MAX+1));
x = x->next;
a = a->next;
carry = total / (BIGINT_DATA_MAX+1);
}
while (b->data != BIGINT_DATA_HEADER) {
total = b->data + carry;
bigint_prepend(x, total % (BIGINT_DATA_MAX+1));
x = x->next;
b = b->next;
carry = total / (BIGINT_DATA_MAX+1);
}
if (carry > 0) {
bigint_prepend(x, carry);
x = x->next;
}
return x->next;
}
#define bigint_print(a) bigint_print_(a->next)
void bigint_print_(BigInt *a) {
if (a->next->data != BIGINT_DATA_HEADER)
bigint_print_(a->next);
printf("%09"PRIu32" ", a->data);
}
int main(int argc, char **argv) {
BigInt *a, *b, *sum;
if (argc != 3) {
printf("Utilização: %s <NÚMERO-A> <NÚMERO-B>\n", argv[0]);
return 1;
}
a = bigint_from_str(argv[1]);
b = bigint_from_str(argv[2]);
if (!a || !b) {
printf("ERRO: Número inválido, certifique-se de que contém apenas dígitos decimais.\n");
return 2;
}
sum = bigint_add(a, b);
printf("a = ");
bigint_print(a);
printf("\nb = ");
bigint_print(b);
printf("\na+b = ");
bigint_print(sum);
printf("\n");
bigint_delete(a);
bigint_delete(b);
bigint_delete(sum);
return 0;
}
#include <stdio.h>
int main(void)
{
printf("hello, world!\n");
return 0;
}
/*
C operator precedence (RL is right-to-left associativity instead of LR)
+------------+---------------------------------------+
| precedence | operator |
+------------+---------------------------------------+
| 1 | x++ x-- x() x[] . -> (type){list} |
| 2 (RL) | ++x --x +x -x ! ~ (type) *x &x sizeof |
| 3 | * / % |
| 4 | + - |
| 5 | << >> |
| 6 | < <= > >= |
| 7 | == != |
| 8 | & |
| 9 | ^ |
| 10 | | |
| 11 | && |
| 12 | || |
| 13 (RL) | ?: |
| 14 (RL) | = += -= *= /= %= <<= >>= &= ^= |= |
| 15 | , |
+----------------------------------------------------+
Floating-point numbers rules of thumb:
- 'float' is generally 32 bits and can precisely hold approximately 7 decimal digits.
- 'double' is generally 64 bits and can precisely hold approximately 15 decimal digits.
- If you need exact decimal precision (e.g., for money), use integers or decimal libraries.
- Floating-point is great for scientific calculations where small errors are acceptable.
*/
#include <stddef.h>
int printf(const char *fmt, ...);
void *malloc(size_t size);
void free(void *p);
typedef struct {
int *items;
unsigned int rear, capacity;
} Queue;
void newq(Queue *q, unsigned int capacity) {
q->rear = 0;
q->capacity = capacity;
q->items = malloc(capacity * sizeof(q->items[0]));
}
void delq(Queue *q) {
free(q->items);
}
void enqueue(Queue *q, int val) {
q->items[q->rear++] = val;
}
int dequeue(Queue *q) {
unsigned int i;
int val;
val = q->items[0];
for (i = 0; i < q->rear-1; ++i) {
q->items[i] = q->items[i+1];
}
--q->rear;
return val;
}
unsigned int lengthq(Queue *q) {
return q->rear;
}
int emptyq(Queue *q) {
return lengthq(q) == 0;
}
void printq(Queue *q) {
unsigned int i;
printf("[");
if (!emptyq(q)) {
for (i = 0; i < q->rear-1; ++i) {
printf("%d,", q->items[i]);
}
printf("%d", q->items[i]);
}
printf("] (%u/%u)\n", lengthq(q), q->capacity);
}
int main(void) {
Queue q;
int i;
newq(&q, 10);
printq(&q);
enqueue(&q, 0);
printq(&q);
enqueue(&q, 1);
printq(&q);
for (i = 2; i < 8; ++i)
enqueue(&q, i);
printq(&q);
printf("-> %d\n", dequeue(&q));
printf("-> %d\n", dequeue(&q));
printq(&q);
enqueue(&q, 8);
enqueue(&q, 9);
enqueue(&q, 10);
enqueue(&q, 11);
printq(&q);
delq(&q);
return 0;
}
/*
Local Variables:
compile-command: "cc -std=c89 -O0 -g\
-fsanitize=address,leak,undefined\
-Wall -Wextra -Wpedantic -Werror\
queue-simple-moving.c && ASAN_OPTIONS='color=never' ./a.out"
End:
*/
#include <stddef.h>
int printf(const char *fmt, ...);
void *malloc(size_t size);
void free(void *p);
typedef struct {
int *items;
unsigned int front, rear, capacity;
} Queue;
void newq(Queue *q, unsigned int capacity) {
q->front = q->rear = 0;
q->capacity = capacity;
q->items = malloc(capacity * sizeof(q->items[0]));
}
void delq(Queue *q) {
free(q->items);
}
void enqueue(Queue *q, int val) {
q->items[q->rear++] = val;
}
int dequeue(Queue *q) {
return q->items[q->front++];
}
unsigned int lengthq(Queue *q) {
return q->rear - q->front;
}
int emptyq(Queue *q) {
return lengthq(q) == 0;
}
void printq(Queue *q) {
unsigned int i;
printf("[");
if (!emptyq(q)) {
for (i = q->front; i < q->rear-1; ++i) {
printf("%d,", q->items[i]);
}
printf("%d", q->items[i]);
}
printf("] (%u/%u)\n", lengthq(q), q->capacity);
}
int main(void) {
Queue q;
int i;
newq(&q, 10);
printq(&q);
enqueue(&q, 0);
printq(&q);
enqueue(&q, 1);
printq(&q);
for (i = 2; i < 8; ++i)
enqueue(&q, i);
printq(&q);
printf("-> %d\n", dequeue(&q));
printf("-> %d\n", dequeue(&q));
printq(&q);
enqueue(&q, 8);
enqueue(&q, 9);
printq(&q);
delq(&q);
return 0;
}
/*
Local Variables:
compile-command: "cc -std=c89 -O0 -g\
-fsanitize=address,leak,undefined\
-Wall -Wextra -Wpedantic -Werror\
queue-simple.c && ASAN_OPTIONS='color=never' ./a.out"
End:
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment