├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── filas ├── dinamica │ ├── README.md │ └── main.c └── estatica │ ├── main.c │ └── README.md ├── pilhas ├── dinamica │ ├── README.md │ └── main.c └── estatica │ ├── README.md │ └── main.c ├── deques ├── dinamico │ └── README.md └── estatico │ ├── README.md │ └── main.c ├── listas ├── estatica │ ├── README.md │ └── main.c ├── encadeada │ ├── README.md │ └── main.c ├── encadeada-ordenada │ ├── README.md │ └── main.c └── duplamente-encadeada │ └── README.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | draft.c 2 | 3 | # Executáveis compilados 4 | programa 5 | **/programa 6 | 7 | # Arquivos objeto 8 | *.o 9 | *.obj 10 | 11 | # Arquivos temporários do sistema 12 | .DS_Store 13 | Thumbs.db 14 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "C Debug", 6 | "type": "cppdbg", 7 | "request": "launch", 8 | "program": "${workspaceFolder}/main", 9 | "args": [], 10 | "stopAtEntry": false, 11 | "cwd": "${workspaceFolder}", 12 | "environment": [], 13 | "externalConsole": true, 14 | "MIMode": "lldb", 15 | "preLaunchTask": "C/C++: Compile Active File to Root Executable" 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "cppbuild", 6 | "label": "C/C++: Compile Active File to Root Executable", 7 | "command": "/usr/bin/gcc", 8 | "args": [ 9 | "-fdiagnostics-color=always", 10 | "-g", 11 | "${file}", 12 | "-o", 13 | "${workspaceFolder}/main" 14 | 15 | ], 16 | "options": { 17 | "cwd": "${workspaceFolder}" 18 | }, 19 | "problemMatcher": ["$gcc"], 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "detail": "Compila o arquivo C ativo e gera o executável 'main' na raiz do projeto." 25 | } 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /filas/dinamica/README.md: -------------------------------------------------------------------------------- 1 | # Fila Dinâmica 2 | 3 | ## Descrição 4 | Implementação de uma **Fila Dinâmica** (Dynamic Queue) em C, utilizando lista encadeada simples com alocação dinâmica de memória. Esta estrutura segue o princípio **FIFO** (First In, First Out) - o primeiro elemento inserido é o primeiro a ser removido. 5 | 6 | ## Características da Implementação 7 | 8 | ### Estruturas de Dados 9 | ```c 10 | typedef struct { 11 | int prioridade; 12 | char tarefa[100]; 13 | } Ticket; 14 | 15 | typedef struct NoFila { 16 | Ticket dados; 17 | struct NoFila *proximo; 18 | } NoFila; 19 | ``` 20 | 21 | ### Declaração no main() 22 | ```c 23 | NoFila *fila; 24 | inicializarFila(&fila); 25 | ``` 26 | 27 | ### Funções Principais 28 | - `void inicializarFila(NoFila **fila)` - Inicializa a fila como vazia 29 | - `int filaVazia(NoFila **fila)` - Verifica se a fila está vazia 30 | - `int enqueue(NoFila **fila, Ticket elemento)` - Insere elemento no fim da fila 31 | - `Ticket dequeue(NoFila **fila)` - Remove elemento do início da fila 32 | - `Ticket consultarProximo(NoFila **fila)` - Consulta o próximo elemento sem remover 33 | - `void liberarFila(NoFila **fila)` - Libera toda a memória alocada 34 | 35 | ## Vantagens da Implementação Dinâmica 36 | 37 | ### ✅ Pontos Positivos 38 | - **Tamanho flexível**: Cresce e diminui conforme necessário 39 | - **Uso eficiente de memória**: Aloca apenas o necessário 40 | - **Sem limite pré-definido**: Limitado apenas pela memória disponível 41 | - **Inserção/remoção O(1)**: Operações em tempo constante 42 | 43 | ### ⚠️ Pontos de Atenção 44 | - **Overhead de ponteiros**: Cada nó requer espaço adicional para ponteiros 45 | - **Fragmentação de memória**: Nós podem estar espalhados na memória 46 | - **Gerenciamento manual**: Necessário controlar alocação/liberação 47 | 48 | ## Complexidade das Operações 49 | 50 | | Operação | Complexidade | Descrição | 51 | |----------|--------------|-----------| 52 | | Enqueue | O(1) | Inserção no fim da fila | 53 | | Dequeue | O(1) | Remoção do início da fila | 54 | | Consultar | O(1) | Acesso ao primeiro elemento | 55 | | Busca | O(n) | Busca por elemento específico | 56 | | Espaço | O(n) | Proporcional ao número de elementos | 57 | 58 | ## Funcionalidades do Menu 59 | 60 | 1. **Exibir fila** - Mostra todos os tickets na fila com posições 61 | 2. **Enqueue (inserir)** - Adiciona novo ticket no fim da fila 62 | 3. **Dequeue (remover)** - Remove e retorna o primeiro ticket 63 | 4. **Consultar próximo** - Visualiza o próximo ticket sem remover 64 | 5. **Limpar fila** - Remove todos os tickets da fila 65 | 6. **Estatísticas** - Exibe informações detalhadas sobre a fila 66 | 67 | ## Aplicações Práticas 68 | 69 | ### Sistemas de Atendimento 70 | - **Call centers**: Gerenciamento de chamadas em espera 71 | - **Suporte técnico**: Fila de tickets por ordem de chegada 72 | - **Atendimento médico**: Fila de pacientes por chegada 73 | 74 | ### Processamento de Dados 75 | - **Sistemas operacionais**: Fila de processos para execução 76 | - **Impressão**: Fila de documentos para impressora 77 | - **Redes**: Buffer de pacotes de dados 78 | 79 | ### Simulações 80 | - **Filas de banco**: Modelagem de atendimento bancário 81 | - **Tráfego**: Simulação de semáforos e congestionamentos 82 | - **Produção**: Linha de montagem e processamento 83 | 84 | ## Exemplo de Uso 85 | 86 | ```c 87 | #include 88 | #include 89 | 90 | int main() { 91 | NoFila *fila; 92 | Ticket ticket1 = {1, "Resolver bug crítico"}; 93 | Ticket ticket2 = {2, "Implementar nova feature"}; 94 | 95 | // Inicializar fila 96 | inicializarFila(&fila); 97 | 98 | // Inserir tickets 99 | enqueue(&fila, ticket1); 100 | enqueue(&fila, ticket2); 101 | 102 | // Processar tickets 103 | while (!filaVazia(&fila)) { 104 | Ticket atual = dequeue(&fila); 105 | printf("Processando: %s\n", atual.tarefa); 106 | } 107 | 108 | // Liberar memória 109 | liberarFila(&fila); 110 | 111 | return 0; 112 | } 113 | ``` 114 | 115 | ## Comparação: Fila Estática vs Dinâmica 116 | 117 | | Aspecto | Fila Estática | Fila Dinâmica | 118 | |---------|---------------|---------------| 119 | | **Tamanho** | Fixo (definido em tempo de compilação) | Flexível (cresce/diminui dinamicamente) | 120 | | **Memória** | Alocada no stack | Alocada no heap | 121 | | **Performance** | Acesso mais rápido | Overhead de alocação | 122 | | **Flexibilidade** | Limitada pelo tamanho máximo | Limitada apenas pela memória disponível | 123 | | **Complexidade** | Implementação mais simples | Gerenciamento de ponteiros | 124 | | **Uso de memória** | Pode desperdiçar espaço | Usa apenas o necessário | 125 | 126 | ## Detalhes Técnicos 127 | 128 | ### Gerenciamento de Memória 129 | - Cada nó é alocado individualmente com `malloc()` 130 | - Liberação automática com `free()` durante remoção 131 | - Função `liberarFila()` garante limpeza completa 132 | 133 | ### Tratamento de Erros 134 | - Verificação de falha na alocação de memória 135 | - Retorno de valores especiais para operações inválidas 136 | - Validação de fila vazia antes das operações 137 | 138 | ### Interface do Usuário 139 | - Menu interativo com navegação intuitiva 140 | - Exibição formatada com bordas ASCII 141 | - Feedback visual para todas as operações 142 | - Estatísticas detalhadas da fila 143 | 144 | ## Compilação e Execução 145 | 146 | ```bash 147 | # Compilar 148 | gcc -o programa main.c 149 | 150 | # Executar 151 | ./programa 152 | ``` 153 | 154 | ## Estrutura do Código 155 | 156 | - **Estruturas de dados**: Definição de Ticket e NoFila 157 | - **Funções principais**: Operações básicas da fila 158 | - **Interface**: Funções de menu e interação 159 | - **Utilitários**: Funções auxiliares para formatação 160 | 161 | Esta implementação demonstra os conceitos fundamentais de filas dinâmicas, oferecendo uma base sólida para compreensão e extensão da estrutura de dados. -------------------------------------------------------------------------------- /pilhas/dinamica/README.md: -------------------------------------------------------------------------------- 1 | # Pilha Dinâmica 2 | 3 | ## Descrição 4 | Implementação de uma **Pilha Dinâmica** (Dynamic Stack) em C, utilizando lista encadeada simples com alocação dinâmica de memória. Esta estrutura segue o princípio **LIFO** (Last In, First Out) - o último elemento inserido é o primeiro a ser removido. 5 | 6 | ## Características da Implementação 7 | 8 | ### Estruturas de Dados 9 | ```c 10 | typedef struct { 11 | int isbn; 12 | char titulo[100]; 13 | char autor[50]; 14 | int paginas; 15 | } Livro; 16 | 17 | typedef struct no { 18 | Livro info; 19 | struct no *proximo; 20 | } No; 21 | ``` 22 | 23 | ### Declaração no main() 24 | ```c 25 | No *pilha; 26 | inicializarPilha(&pilha); 27 | ``` 28 | 29 | ### Funções Principais 30 | - `void inicializarPilha(No **pilha)` - Inicializa a pilha como vazia 31 | - `int pilhaVazia(No **pilha)` - Verifica se a pilha está vazia 32 | - `int push(No **pilha, Livro elemento)` - Empilha elemento no topo 33 | - `Livro pop(No **pilha)` - Desempilha elemento do topo 34 | - `Livro top(No **pilha)` - Consulta o elemento do topo sem remover 35 | - `void liberarPilha(No **pilha)` - Libera toda a memória alocada 36 | 37 | ## Vantagens da Implementação Dinâmica 38 | 39 | ### ✅ Pontos Positivos 40 | - **Tamanho flexível**: Cresce e diminui conforme necessário 41 | - **Uso eficiente de memória**: Aloca apenas o necessário 42 | - **Sem limite pré-definido**: Limitado apenas pela memória disponível 43 | - **Operações O(1)**: Push, pop e top em tempo constante 44 | 45 | ### ⚠️ Pontos de Atenção 46 | - **Overhead de ponteiros**: Cada nó requer espaço adicional para ponteiros 47 | - **Fragmentação de memória**: Nós podem estar espalhados na memória 48 | - **Gerenciamento manual**: Necessário controlar alocação/liberação 49 | 50 | ## Complexidade das Operações 51 | 52 | | Operação | Complexidade | Descrição | 53 | |----------|--------------|-----------| 54 | | Push | O(1) | Inserção no topo da pilha | 55 | | Pop | O(1) | Remoção do topo da pilha | 56 | | Top | O(1) | Acesso ao elemento do topo | 57 | | Busca | O(n) | Busca por elemento específico | 58 | | Espaço | O(n) | Proporcional ao número de elementos | 59 | 60 | ## Funcionalidades do Menu 61 | 62 | 1. **Exibir pilha** - Mostra todos os livros empilhados (topo → base) 63 | 2. **Empilhar (Push)** - Adiciona novo livro no topo da pilha 64 | 3. **Desempilhar (Pop)** - Remove e retorna o livro do topo 65 | 4. **Consultar topo** - Visualiza o livro do topo sem remover 66 | 5. **Verificar se está vazia** - Verifica o status da pilha 67 | 6. **Consultar tamanho** - Exibe estatísticas detalhadas 68 | 7. **Liberar pilha** - Remove todos os livros da pilha 69 | 70 | ## Aplicações Práticas 71 | 72 | ### Sistemas de Controle 73 | - **Undo/Redo**: Histórico de operações em editores 74 | - **Navegação**: Histórico de páginas em navegadores 75 | - **Chamadas de função**: Stack de execução em programas 76 | 77 | ### Processamento de Dados 78 | - **Parsing**: Análise de expressões matemáticas 79 | - **Compiladores**: Análise sintática e semântica 80 | - **Algoritmos**: Busca em profundidade (DFS) 81 | 82 | ### Estruturas Auxiliares 83 | - **Validação**: Verificação de parênteses balanceados 84 | - **Conversão**: Notação infixa para pós-fixa 85 | - **Recursão**: Simulação de chamadas recursivas 86 | 87 | ## Exemplo de Uso 88 | 89 | ```c 90 | #include 91 | #include 92 | 93 | int main() { 94 | No *pilha; 95 | Livro livro1 = {123, "Estruturas de Dados", "Cormen", 1200}; 96 | Livro livro2 = {456, "Algoritmos", "Sedgewick", 800}; 97 | 98 | // Inicializar pilha 99 | inicializarPilha(&pilha); 100 | 101 | // Empilhar livros 102 | push(&pilha, livro1); 103 | push(&pilha, livro2); 104 | 105 | // Processar livros (LIFO) 106 | while (!pilhaVazia(&pilha)) { 107 | Livro atual = pop(&pilha); 108 | printf("Processando: %s\n", atual.titulo); 109 | } 110 | 111 | // Liberar memória 112 | liberarPilha(&pilha); 113 | 114 | return 0; 115 | } 116 | ``` 117 | 118 | ## Comparação: Pilha Estática vs Dinâmica 119 | 120 | | Aspecto | Pilha Estática | Pilha Dinâmica | 121 | |---------|----------------|----------------| 122 | | **Tamanho** | Fixo (definido em tempo de compilação) | Flexível (cresce/diminui dinamicamente) | 123 | | **Memória** | Alocada no stack | Alocada no heap | 124 | | **Performance** | Acesso mais rápido | Overhead de alocação | 125 | | **Flexibilidade** | Limitada pelo tamanho máximo | Limitada apenas pela memória disponível | 126 | | **Complexidade** | Implementação mais simples | Gerenciamento de ponteiros | 127 | | **Uso de memória** | Pode desperdiçar espaço | Usa apenas o necessário | 128 | 129 | ## Detalhes Técnicos 130 | 131 | ### Gerenciamento de Memória 132 | - Cada nó é alocado individualmente com `malloc()` 133 | - Liberação automática com `free()` durante pop 134 | - Função `liberarPilha()` garante limpeza completa 135 | 136 | ### Tratamento de Erros 137 | - Verificação de falha na alocação de memória 138 | - Retorno de valores especiais para operações inválidas 139 | - Validação de pilha vazia antes das operações 140 | 141 | ### Interface do Usuário 142 | - Menu interativo com navegação intuitiva 143 | - Exibição formatada com bordas ASCII 144 | - Feedback visual para todas as operações 145 | - Estatísticas detalhadas da pilha 146 | 147 | ## Funcionamento Visual 148 | 149 | ``` 150 | Estado Inicial: pilha = NULL 151 | 152 | Após push(A): 153 | [A] -> NULL 154 | ↑ 155 | topo 156 | 157 | Após push(B): 158 | [B] -> [A] -> NULL 159 | ↑ 160 | topo 161 | 162 | Após push(C): 163 | [C] -> [B] -> [A] -> NULL 164 | ↑ 165 | topo 166 | 167 | Após pop(): 168 | [B] -> [A] -> NULL 169 | ↑ 170 | topo 171 | ``` 172 | 173 | ## Compilação e Execução 174 | 175 | ```bash 176 | # Compilar 177 | gcc -o programa main.c 178 | 179 | # Executar 180 | ./programa 181 | ``` 182 | 183 | ## Estrutura do Código 184 | 185 | - **Estruturas de dados**: Definição de Livro e No 186 | - **Funções principais**: Operações básicas da pilha 187 | - **Interface**: Funções de menu e interação 188 | - **Utilitários**: Funções auxiliares para formatação 189 | 190 | Esta implementação demonstra os conceitos fundamentais de pilhas dinâmicas, oferecendo uma base sólida para compreensão e extensão da estrutura de dados. -------------------------------------------------------------------------------- /deques/dinamico/README.md: -------------------------------------------------------------------------------- 1 | # Deque Dinâmico 2 | 3 | ## Descrição 4 | Implementação de um **Deque Dinâmico** (Double-ended Queue) em C, utilizando lista duplamente encadeada com alocação dinâmica de memória. Esta estrutura permite inserção e remoção eficiente em ambas as extremidades (início e fim). 5 | 6 | ## Características da Implementação 7 | 8 | ### Estruturas de Dados 9 | ```c 10 | typedef struct { 11 | int numero; 12 | char descricao[80]; 13 | } Tarefa; 14 | 15 | typedef struct NoDeque { 16 | Tarefa dados; 17 | struct NoDeque *anterior; 18 | struct NoDeque *proximo; 19 | } NoDeque; 20 | ``` 21 | 22 | ### Declaração no main() 23 | ```c 24 | NoDeque *inicio, *fim; 25 | inicializarDeque(&inicio, &fim); 26 | ``` 27 | 28 | ### Funções Principais 29 | - `void inicializarDeque(NoDeque **inicio, NoDeque **fim)` - Inicializa o deque como vazio 30 | - `int dequeVazio(NoDeque **inicio)` - Verifica se o deque está vazio 31 | - `int inserirInicio(NoDeque **inicio, NoDeque **fim, Tarefa elemento)` - Insere no início 32 | - `int inserirFim(NoDeque **inicio, NoDeque **fim, Tarefa elemento)` - Insere no fim 33 | - `Tarefa removerInicio(NoDeque **inicio, NoDeque **fim)` - Remove do início 34 | - `Tarefa removerFim(NoDeque **inicio, NoDeque **fim)` - Remove do fim 35 | - `Tarefa consultarInicio(NoDeque **inicio)` - Consulta o primeiro elemento 36 | - `Tarefa consultarFim(NoDeque **fim)` - Consulta o último elemento 37 | - `void liberarDeque(NoDeque **inicio, NoDeque **fim)` - Libera toda a memória 38 | 39 | ## Vantagens da Implementação Dinâmica 40 | 41 | ### ✅ Pontos Positivos 42 | - **Flexibilidade total**: Inserção/remoção eficiente em ambas as extremidades 43 | - **Tamanho dinâmico**: Cresce e diminui conforme necessário 44 | - **Navegação bidirecional**: Permite percorrer em ambas as direções 45 | - **Operações O(1)**: Todas as operações básicas em tempo constante 46 | 47 | ### ⚠️ Pontos de Atenção 48 | - **Overhead de ponteiros**: Cada nó requer dois ponteiros (anterior e próximo) 49 | - **Complexidade de implementação**: Mais complexo que estruturas simples 50 | - **Gerenciamento de memória**: Necessário controlar alocação/liberação 51 | 52 | ## Complexidade das Operações 53 | 54 | | Operação | Complexidade | Descrição | 55 | |----------|--------------|-----------| 56 | | Inserir Início | O(1) | Inserção no início do deque | 57 | | Inserir Fim | O(1) | Inserção no fim do deque | 58 | | Remover Início | O(1) | Remoção do início do deque | 59 | | Remover Fim | O(1) | Remoção do fim do deque | 60 | | Consultar Extremos | O(1) | Acesso aos elementos das extremidades | 61 | | Busca | O(n) | Busca por elemento específico | 62 | | Espaço | O(n) | Proporcional ao número de elementos | 63 | 64 | ## Funcionalidades do Menu 65 | 66 | 1. **Exibir deque** - Mostra todas as tarefas do início ao fim 67 | 2. **Inserir no início** - Adiciona nova tarefa no início do deque 68 | 3. **Inserir no fim** - Adiciona nova tarefa no fim do deque 69 | 4. **Remover do início** - Remove e retorna a primeira tarefa 70 | 5. **Remover do fim** - Remove e retorna a última tarefa 71 | 6. **Consultar início** - Visualiza a primeira tarefa sem remover 72 | 7. **Consultar fim** - Visualiza a última tarefa sem remover 73 | 8. **Navegar pelo deque** - Navegação bidirecional interativa 74 | 9. **Limpar deque** - Remove todas as tarefas do deque 75 | 76 | ## Aplicações Práticas 77 | 78 | ### Sistemas de Processamento 79 | - **Fila de prioridade dupla**: Processamento por ambas as extremidades 80 | - **Buffer circular**: Implementação eficiente de buffers 81 | - **Undo/Redo avançado**: Navegação bidirecional no histórico 82 | 83 | ### Algoritmos 84 | - **Busca bidirecional**: Algoritmos que exploram ambas as direções 85 | - **Sliding window**: Janela deslizante para análise de dados 86 | - **Palindrome checking**: Verificação de palíndromos 87 | 88 | ### Estruturas de Dados Avançadas 89 | - **Implementação de outras estruturas**: Base para filas de prioridade 90 | - **Cache LRU**: Least Recently Used com acesso rápido 91 | - **Simulações**: Modelagem de sistemas com entrada/saída dupla 92 | 93 | ## Exemplo de Uso 94 | 95 | ```c 96 | #include 97 | #include 98 | 99 | int main() { 100 | NoDeque *inicio, *fim; 101 | Tarefa tarefa1 = {1, "Primeira tarefa"}; 102 | Tarefa tarefa2 = {2, "Segunda tarefa"}; 103 | 104 | // Inicializar deque 105 | inicializarDeque(&inicio, &fim); 106 | 107 | // Inserir tarefas 108 | inserirInicio(&inicio, &fim, tarefa1); 109 | inserirFim(&inicio, &fim, tarefa2); 110 | 111 | // Processar tarefas 112 | while (!dequeVazio(&inicio)) { 113 | Tarefa atual = removerInicio(&inicio, &fim); 114 | printf("Processando: %s\n", atual.descricao); 115 | } 116 | 117 | // Liberar memória 118 | liberarDeque(&inicio, &fim); 119 | 120 | return 0; 121 | } 122 | ``` 123 | 124 | ## Comparação com Outras Estruturas 125 | 126 | | Aspecto | Fila Simples | Pilha | Deque | 127 | |---------|--------------|-------|-------| 128 | | **Inserção** | Apenas no fim | Apenas no topo | Início e fim | 129 | | **Remoção** | Apenas do início | Apenas do topo | Início e fim | 130 | | **Flexibilidade** | Limitada (FIFO) | Limitada (LIFO) | Máxima | 131 | | **Complexidade** | Simples | Simples | Moderada | 132 | | **Uso de memória** | Menor overhead | Menor overhead | Maior overhead | 133 | | **Aplicações** | Processamento sequencial | Recursão, parsing | Algoritmos avançados | 134 | 135 | ## Detalhes Técnicos 136 | 137 | ### Gerenciamento de Memória 138 | - Cada nó é alocado individualmente com `malloc()` 139 | - Liberação automática com `free()` durante remoção 140 | - Função `liberarDeque()` garante limpeza completa 141 | - Manutenção de ponteiros `anterior` e `proximo` 142 | 143 | ### Tratamento de Erros 144 | - Verificação de falha na alocação de memória 145 | - Retorno de valores especiais para operações inválidas 146 | - Validação de deque vazio antes das operações 147 | - Manutenção consistente dos ponteiros de extremidade 148 | 149 | ### Interface do Usuário 150 | - Menu interativo com navegação intuitiva 151 | - Exibição formatada com bordas ASCII 152 | - Feedback visual para todas as operações 153 | - Navegação bidirecional única entre as estruturas 154 | 155 | ## Funcionamento Visual 156 | 157 | ``` 158 | Estado Inicial: inicio = NULL, fim = NULL 159 | 160 | Após inserirInicio(A): 161 | [A] <-> NULL 162 | ↑ 163 | inicio/fim 164 | 165 | Após inserirFim(B): 166 | [A] <-> [B] <-> NULL 167 | ↑ ↑ 168 | inicio fim 169 | 170 | Após inserirInicio(C): 171 | [C] <-> [A] <-> [B] <-> NULL 172 | ↑ ↑ 173 | inicio fim 174 | 175 | Navegação bidirecional: 176 | [C] ←→ [A] ←→ [B] 177 | ``` 178 | 179 | ## Funcionalidade Especial: Navegação Bidirecional 180 | 181 | O deque dinâmico oferece uma funcionalidade única de navegação interativa: 182 | 183 | - **Próximo (→)**: Move para o próximo elemento 184 | - **Anterior (←)**: Move para o elemento anterior 185 | - **Ir para o início**: Salta diretamente para o primeiro elemento 186 | - **Ir para o fim**: Salta diretamente para o último elemento 187 | 188 | Esta funcionalidade demonstra a capacidade bidirecional da estrutura, permitindo explorar os dados em ambas as direções de forma intuitiva. 189 | 190 | ## Compilação e Execução 191 | 192 | ```bash 193 | # Compilar 194 | gcc -o programa main.c 195 | 196 | # Executar 197 | ./programa 198 | ``` 199 | 200 | ## Estrutura do Código 201 | 202 | - **Estruturas de dados**: Definição de Tarefa e NoDeque 203 | - **Funções principais**: Operações básicas do deque 204 | - **Interface**: Funções de menu e interação 205 | - **Navegação**: Sistema único de navegação bidirecional 206 | - **Utilitários**: Funções auxiliares para formatação 207 | 208 | Esta implementação demonstra os conceitos fundamentais de deques dinâmicos, oferecendo uma base sólida para compreensão de estruturas de dados bidirecionais e suas aplicações avançadas. -------------------------------------------------------------------------------- /listas/estatica/README.md: -------------------------------------------------------------------------------- 1 | # Lista Estática em C 2 | 3 | ## Conceito 4 | 5 | Uma **Lista Estática** é uma estrutura de dados linear que armazena elementos em posições contíguas de memória, utilizando um array de tamanho fixo. Diferentemente das listas dinâmicas, o tamanho máximo da lista é definido em tempo de compilação e não pode ser alterado durante a execução do programa. 6 | 7 | ### Características Principais 8 | 9 | - **Tamanho Fixo**: O número máximo de elementos é definido por uma constante 10 | - **Acesso Sequencial**: Os elementos são acessados através de índices 11 | - **Inserção Ordenada**: Novos elementos podem ser inseridos em qualquer posição válida 12 | - **Memória Contígua**: Todos os elementos ficam armazenados em posições consecutivas 13 | 14 | ### Vantagens 15 | 16 | - **Simplicidade**: Fácil implementação e compreensão 17 | - **Eficiência de Acesso**: Acesso direto aos elementos por índice 18 | - **Controle de Memória**: Não há necessidade de alocação dinâmica 19 | - **Cache Friendly**: Elementos contíguos melhoram a performance do cache 20 | 21 | ### Desvantagens 22 | 23 | - **Tamanho Limitado**: Não pode exceder o tamanho pré-definido 24 | - **Desperdício de Memória**: Pode reservar mais espaço do que necessário 25 | - **Inserção/Remoção Custosa**: Operações no meio da lista requerem deslocamento de elementos 26 | 27 | ## Estrutura de Dados 28 | 29 | ### Definição do Elemento (Aluno) 30 | ```c 31 | typedef struct { 32 | int matricula; 33 | char nome[50]; 34 | } Aluno; 35 | ``` 36 | 37 | ### Definição da Lista Estática 38 | ```c 39 | typedef struct { 40 | Aluno elementos[MAX_ELEMENTOS]; 41 | int ultimo; 42 | } ListaEstatica; 43 | ``` 44 | 45 | - `elementos[]`: Array que armazena os dados 46 | - `ultimo`: Índice do último elemento válido (-1 quando vazia) 47 | 48 | ## Funções Implementadas 49 | 50 | ### Funções Auxiliares 51 | 52 | #### `void limparBuffer()` 53 | Remove caracteres residuais do buffer de entrada, evitando problemas na leitura de dados. 54 | 55 | #### `void removerQuebraLinha(char *str)` 56 | Remove o caractere de quebra de linha ('\n') de uma string, normalmente após usar `fgets()`. 57 | 58 | #### `void limparTela()` 59 | Limpa a tela do terminal de forma compatível com Windows e sistemas Unix. 60 | 61 | #### `void pausar()` 62 | Pausa a execução e aguarda o usuário pressionar ENTER para continuar. 63 | 64 | #### `void exibirCabecalho(ListaEstatica *lista)` 65 | Exibe o cabeçalho do sistema com informações sobre o status atual da lista: 66 | - Status: VAZIA, PARCIAL ou CHEIA 67 | - Contador de elementos (atual/máximo) 68 | 69 | ### Funções de Manipulação da Lista 70 | 71 | #### `void inicializarLista(ListaEstatica *lista)` 72 | **Descrição**: Inicializa uma lista estática, preparando-a para uso. 73 | 74 | **Parâmetros**: 75 | - `lista`: Ponteiro para a estrutura da lista 76 | 77 | **Funcionamento**: Define o campo `ultimo` como -1, indicando que a lista está vazia. 78 | 79 | **Complexidade**: O(1) 80 | 81 | --- 82 | 83 | #### `int listaVazia(ListaEstatica *lista)` 84 | **Descrição**: Verifica se a lista está vazia. 85 | 86 | **Parâmetros**: 87 | - `lista`: Ponteiro para a estrutura da lista 88 | 89 | **Retorno**: 90 | - `1` se a lista estiver vazia 91 | - `0` se a lista contiver elementos 92 | 93 | **Funcionamento**: Verifica se `ultimo == -1`. 94 | 95 | **Complexidade**: O(1) 96 | 97 | --- 98 | 99 | #### `int listaCheia(ListaEstatica *lista)` 100 | **Descrição**: Verifica se a lista atingiu sua capacidade máxima. 101 | 102 | **Parâmetros**: 103 | - `lista`: Ponteiro para a estrutura da lista 104 | 105 | **Retorno**: 106 | - `1` se a lista estiver cheia 107 | - `0` se ainda houver espaço 108 | 109 | **Funcionamento**: Verifica se `ultimo == (MAX_ELEMENTOS - 1)`. 110 | 111 | **Complexidade**: O(1) 112 | 113 | --- 114 | 115 | #### `int inserirFim(ListaEstatica *lista, Aluno elemento)` 116 | **Descrição**: Insere um novo elemento no final da lista. 117 | 118 | **Parâmetros**: 119 | - `lista`: Ponteiro para a estrutura da lista 120 | - `elemento`: Estrutura Aluno a ser inserida 121 | 122 | **Retorno**: 123 | - `1` se a inserção foi bem-sucedida 124 | - `0` se a lista estiver cheia 125 | 126 | **Funcionamento**: 127 | 1. Verifica se a lista está cheia 128 | 2. Insere o elemento na posição `ultimo + 1` 129 | 3. Incrementa o valor de `ultimo` 130 | 131 | **Complexidade**: O(1) 132 | 133 | --- 134 | 135 | #### `int inserirPosicao(ListaEstatica *lista, int posicao, Aluno elemento)` 136 | **Descrição**: Insere um elemento em uma posição específica da lista. 137 | 138 | **Parâmetros**: 139 | - `lista`: Ponteiro para a estrutura da lista 140 | - `posicao`: Índice onde o elemento será inserido (0 a ultimo+1) 141 | - `elemento`: Estrutura Aluno a ser inserida 142 | 143 | **Retorno**: 144 | - `1` se a inserção foi bem-sucedida 145 | - `0` se houve erro (lista cheia ou posição inválida) 146 | 147 | **Funcionamento**: 148 | 1. Verifica se a lista está cheia 149 | 2. Valida se a posição está no intervalo [0, ultimo+1] 150 | 3. Desloca todos os elementos da posição até o final uma posição à direita 151 | 4. Insere o novo elemento na posição especificada 152 | 5. Incrementa o valor de `ultimo` 153 | 154 | **Complexidade**: O(n) no pior caso (inserção no início) 155 | 156 | --- 157 | 158 | #### `int removerPosicao(ListaEstatica *lista, int posicao)` 159 | **Descrição**: Remove um elemento de uma posição específica da lista. 160 | 161 | **Parâmetros**: 162 | - `lista`: Ponteiro para a estrutura da lista 163 | - `posicao`: Índice do elemento a ser removido (0 a ultimo) 164 | 165 | **Retorno**: 166 | - `1` se a remoção foi bem-sucedida 167 | - `0` se houve erro (lista vazia ou posição inválida) 168 | 169 | **Funcionamento**: 170 | 1. Verifica se a lista está vazia 171 | 2. Valida se a posição está no intervalo [0, ultimo] 172 | 3. Desloca todos os elementos após a posição uma posição à esquerda 173 | 4. Decrementa o valor de `ultimo` 174 | 175 | **Complexidade**: O(n) no pior caso (remoção no início) 176 | 177 | --- 178 | 179 | #### `int modificarElemento(ListaEstatica *lista, int posicao, Aluno elemento)` 180 | **Descrição**: Modifica um elemento existente em uma posição específica. 181 | 182 | **Parâmetros**: 183 | - `lista`: Ponteiro para a estrutura da lista 184 | - `posicao`: Índice do elemento a ser modificado (0 a ultimo) 185 | - `elemento`: Nova estrutura Aluno para substituir a existente 186 | 187 | **Retorno**: 188 | - `1` se a modificação foi bem-sucedida 189 | - `0` se houve erro (lista vazia ou posição inválida) 190 | 191 | **Funcionamento**: 192 | 1. Verifica se a lista está vazia 193 | 2. Valida se a posição está no intervalo [0, ultimo] 194 | 3. Substitui o elemento na posição especificada 195 | 196 | **Complexidade**: O(1) 197 | 198 | --- 199 | 200 | #### `int pesquisarElemento(ListaEstatica *lista, int matricula)` 201 | **Descrição**: Busca um elemento na lista pela matrícula. 202 | 203 | **Parâmetros**: 204 | - `lista`: Ponteiro para a estrutura da lista 205 | - `matricula`: Matrícula do aluno a ser encontrado 206 | 207 | **Retorno**: 208 | - Índice do elemento encontrado (0 a ultimo) 209 | - `-1` se o elemento não foi encontrado ou lista vazia 210 | 211 | **Funcionamento**: 212 | 1. Verifica se a lista está vazia 213 | 2. Percorre sequencialmente a lista comparando matrículas 214 | 3. Retorna o índice do primeiro elemento encontrado 215 | 216 | **Complexidade**: O(n) no pior caso (elemento no final ou não encontrado) 217 | 218 | ## Funções de Interface 219 | 220 | ### `void exibirMenu(ListaEstatica *lista, int *opcao)` 221 | Exibe o menu principal com opções disponíveis e captura a escolha do usuário. 222 | 223 | ### `void menuExibirElementos(ListaEstatica *lista)` 224 | Exibe todos os elementos da lista em formato de tabela, incluindo contador de elementos. 225 | 226 | ### `void menuInserirPosicao(ListaEstatica *lista)` 227 | Interface para inserção de elemento em posição específica com validações. 228 | 229 | ### `void menuInserirFim(ListaEstatica *lista)` 230 | Interface para inserção de elemento no final da lista. 231 | 232 | ### `void menuRemoverPosicao(ListaEstatica *lista)` 233 | Interface para remoção de elemento, exibindo lista atual antes da operação. 234 | 235 | ### `void menuModificarElemento(ListaEstatica *lista)` 236 | Interface para modificação de elemento existente, com exibição da lista atual. 237 | 238 | ### `void menuPesquisarElemento(ListaEstatica *lista)` 239 | Interface para busca de elemento por matrícula, exibindo resultado formatado. 240 | 241 | ## Compilação e Execução 242 | 243 | ```bash 244 | gcc -o programa main.c 245 | ./programa 246 | ``` 247 | 248 | ## Considerações de Implementação 249 | 250 | 1. **Validação de Entrada**: Todas as operações incluem verificações de estado da lista 251 | 2. **Interface Amigável**: Menus formatados com bordas ASCII para melhor visualização 252 | 3. **Tratamento de Strings**: Remoção automática de quebras de linha em nomes 253 | 4. **Feedback Visual**: Mensagens claras de sucesso e erro para cada operação 254 | 5. **Portabilidade**: Código compatível com diferentes sistemas operacionais 255 | -------------------------------------------------------------------------------- /filas/estatica/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_ELEMENTOS 5 6 | 7 | typedef struct 8 | { 9 | int id; 10 | char descricao[50]; 11 | } Processo; 12 | 13 | typedef struct 14 | { 15 | Processo elementos[MAX_ELEMENTOS]; 16 | int inicio; 17 | int fim; 18 | int tamanho; 19 | } FilaEstatica; 20 | 21 | void limparBuffer() 22 | { 23 | int c; 24 | while ((c = getchar()) != '\n' && c != EOF) 25 | ; 26 | } 27 | 28 | void removerQuebraLinha(char *str) { 29 | str[strcspn(str, "\n")] = 0; 30 | } 31 | 32 | // FUNÇÕES DA FILA ESTÁTICA 33 | void inicializarFila(FilaEstatica *fila) 34 | { 35 | fila->inicio = 0; 36 | fila->fim = -1; 37 | fila->tamanho = 0; 38 | } 39 | 40 | int filaVazia(FilaEstatica *fila) 41 | { 42 | return fila->tamanho == 0; 43 | } 44 | 45 | int filaCheia(FilaEstatica *fila) 46 | { 47 | return fila->tamanho == MAX_ELEMENTOS; 48 | } 49 | 50 | // FUNÇÕES AUXILIARES PARA INTERFACE 51 | void limparTela() { 52 | #ifdef _WIN32 53 | system("cls"); 54 | #else 55 | system("clear"); 56 | #endif 57 | } 58 | 59 | void pausar() { 60 | printf("\nPressione ENTER para continuar..."); 61 | limparBuffer(); 62 | getchar(); 63 | } 64 | 65 | void exibirCabecalho(FilaEstatica *fila) { 66 | int total = fila->tamanho; 67 | char status[20]; 68 | 69 | if (filaVazia(fila)) { 70 | strcpy(status, "VAZIA"); 71 | } else if (filaCheia(fila)) { 72 | strcpy(status, "CHEIA"); 73 | } else { 74 | strcpy(status, "PARCIAL"); 75 | } 76 | 77 | printf("╔══════════════════════════════════════╗\n"); 78 | printf("║ FILA ESTATICA ║\n"); 79 | printf("║ Sistema de Processos ║\n"); 80 | printf("╠══════════════════════════════════════╣\n"); 81 | printf("║ Status: %-8s | Processos: %d/%d ║\n", status, total, MAX_ELEMENTOS); 82 | printf("╚══════════════════════════════════════╝\n\n"); 83 | } 84 | 85 | int enqueue(FilaEstatica *fila, Processo elemento) 86 | { 87 | if (filaCheia(fila)) 88 | return 0; 89 | 90 | fila->fim = (fila->fim + 1) % MAX_ELEMENTOS; 91 | fila->elementos[fila->fim] = elemento; 92 | fila->tamanho++; 93 | 94 | return 1; 95 | } 96 | 97 | Processo dequeue(FilaEstatica *fila) 98 | { 99 | Processo vazio = {-1, ""}; 100 | 101 | if (filaVazia(fila)) 102 | return vazio; 103 | 104 | Processo removido = fila->elementos[fila->inicio]; 105 | fila->inicio = (fila->inicio + 1) % MAX_ELEMENTOS; 106 | fila->tamanho--; 107 | 108 | return removido; 109 | } 110 | 111 | Processo consultarProximo(FilaEstatica *fila) 112 | { 113 | Processo vazio = {-1, ""}; 114 | 115 | if (filaVazia(fila)) 116 | return vazio; 117 | 118 | return fila->elementos[fila->inicio]; 119 | } 120 | 121 | // FUNÇÕES UTILIZADAS PELO MENU 122 | void exibirMenu(FilaEstatica *fila, int *opcao) 123 | { 124 | limparTela(); 125 | exibirCabecalho(fila); 126 | 127 | printf("┌──────────────────────────────────────┐\n"); 128 | printf("│ MENU │\n"); 129 | printf("├──────────────────────────────────────┤\n"); 130 | printf("│ 1 - Exibir fila │\n"); 131 | printf("│ 2 - Enqueue (inserir) │\n"); 132 | printf("│ 3 - Dequeue (remover) │\n"); 133 | printf("│ 4 - Consultar proximo │\n"); 134 | printf("│ 5 - Limpar fila │\n"); 135 | printf("│ 0 - Sair │\n"); 136 | printf("└──────────────────────────────────────┘\n\n"); 137 | printf("Escolha uma opcao: "); 138 | scanf("%d", opcao); 139 | } 140 | 141 | void menuExibirFila(FilaEstatica *fila) { 142 | limparTela(); 143 | printf("╔══════════════════════════════════════╗\n"); 144 | printf("║ FILA DE PROCESSOS ║\n"); 145 | printf("╚══════════════════════════════════════╝\n\n"); 146 | 147 | if (filaVazia(fila)) { 148 | printf("Fila vazia! Nenhum processo na fila.\n"); 149 | } else { 150 | printf("┌─────────┬────────────────────────────┐\n"); 151 | printf("│ Posicao │ ID - Descricao │\n"); 152 | printf("├─────────┼────────────────────────────┤\n"); 153 | 154 | int atual = fila->inicio; 155 | for (int i = 0; i < fila->tamanho; i++) { 156 | int posicao = i + 1; 157 | printf("│ %7d │ %3d - %-18s │\n", posicao, 158 | fila->elementos[atual].id, 159 | fila->elementos[atual].descricao); 160 | atual = (atual + 1) % MAX_ELEMENTOS; 161 | } 162 | printf("└─────────┴────────────────────────────┘\n"); 163 | printf("\nTotal na fila: %d/%d processos\n", fila->tamanho, MAX_ELEMENTOS); 164 | printf("Proximo a ser atendido: %d - %s\n", 165 | fila->elementos[fila->inicio].id, 166 | fila->elementos[fila->inicio].descricao); 167 | } 168 | 169 | pausar(); 170 | } 171 | 172 | void menuEnqueue(FilaEstatica *fila) 173 | { 174 | int sucesso; 175 | Processo novoProcesso; 176 | 177 | limparTela(); 178 | printf("╔══════════════════════════════════════╗\n"); 179 | printf("║ ENQUEUE (INSERIR) ║\n"); 180 | printf("╚══════════════════════════════════════╝\n\n"); 181 | 182 | if (filaCheia(fila)) { 183 | printf("Fila cheia! Nao e possivel inserir novos processos.\n"); 184 | pausar(); 185 | return; 186 | } 187 | 188 | printf("Digite o ID do processo: "); 189 | scanf("%d", &novoProcesso.id); 190 | 191 | limparBuffer(); 192 | 193 | printf("Digite a descricao do processo: "); 194 | fgets(novoProcesso.descricao, 50, stdin); 195 | 196 | removerQuebraLinha(novoProcesso.descricao); 197 | 198 | sucesso = enqueue(fila, novoProcesso); 199 | 200 | printf("\n"); 201 | if (sucesso) 202 | printf("Processo inserido na fila com sucesso!\n"); 203 | else 204 | printf("Erro ao inserir processo na fila!\n"); 205 | 206 | pausar(); 207 | } 208 | 209 | void menuDequeue(FilaEstatica *fila) { 210 | Processo removido; 211 | 212 | limparTela(); 213 | printf("╔══════════════════════════════════════╗\n"); 214 | printf("║ DEQUEUE (REMOVER) ║\n"); 215 | printf("╚══════════════════════════════════════╝\n\n"); 216 | 217 | if (filaVazia(fila)) { 218 | printf("Fila vazia! Nada para remover.\n"); 219 | pausar(); 220 | return; 221 | } 222 | 223 | printf("Processo a ser removido:\n"); 224 | printf("ID: %d - %s\n\n", fila->elementos[fila->inicio].id, 225 | fila->elementos[fila->inicio].descricao); 226 | 227 | removido = dequeue(fila); 228 | 229 | printf("Processo removido da fila: %d - %s\n", removido.id, removido.descricao); 230 | 231 | if (!filaVazia(fila)) { 232 | printf("Proximo da fila: %d - %s\n", 233 | fila->elementos[fila->inicio].id, 234 | fila->elementos[fila->inicio].descricao); 235 | } else { 236 | printf("Fila agora esta vazia.\n"); 237 | } 238 | 239 | pausar(); 240 | } 241 | 242 | void menuConsultarProximo(FilaEstatica *fila) { 243 | Processo proximo; 244 | 245 | limparTela(); 246 | printf("╔══════════════════════════════════════╗\n"); 247 | printf("║ CONSULTAR PROXIMO ║\n"); 248 | printf("╚══════════════════════════════════════╝\n\n"); 249 | 250 | if (filaVazia(fila)) { 251 | printf("Fila vazia! Nenhum processo para consultar.\n"); 252 | pausar(); 253 | return; 254 | } 255 | 256 | proximo = consultarProximo(fila); 257 | 258 | printf("Proximo processo a ser atendido:\n"); 259 | printf("┌─────────────┬────────────────────────┐\n"); 260 | printf("│ ID │ %-22d │\n", proximo.id); 261 | printf("│ Descricao │ %-22s │\n", proximo.descricao); 262 | printf("│ Posicao │ Primeiro da fila │\n"); 263 | printf("└─────────────┴────────────────────────┘\n"); 264 | 265 | pausar(); 266 | } 267 | 268 | void menuLimparFila(FilaEstatica *fila) { 269 | char confirmacao; 270 | 271 | limparTela(); 272 | printf("╔══════════════════════════════════════╗\n"); 273 | printf("║ LIMPAR FILA ║\n"); 274 | printf("╚══════════════════════════════════════╝\n\n"); 275 | 276 | if (filaVazia(fila)) { 277 | printf("Fila ja esta vazia!\n"); 278 | pausar(); 279 | return; 280 | } 281 | 282 | printf("ATENCAO: Esta operacao ira remover TODOS os processos da fila!\n"); 283 | printf("Processos na fila: %d\n\n", fila->tamanho); 284 | 285 | printf("Tem certeza? (s/N): "); 286 | limparBuffer(); 287 | scanf("%c", &confirmacao); 288 | 289 | if (confirmacao == 's' || confirmacao == 'S') { 290 | inicializarFila(fila); 291 | printf("\nFila limpa com sucesso! Todos os processos foram removidos.\n"); 292 | } else { 293 | printf("\nOperacao cancelada. Fila mantida inalterada.\n"); 294 | } 295 | 296 | pausar(); 297 | } 298 | 299 | int main() 300 | { 301 | FilaEstatica fila; 302 | int opcao; 303 | 304 | inicializarFila(&fila); 305 | 306 | do 307 | { 308 | exibirMenu(&fila, &opcao); 309 | 310 | switch (opcao) 311 | { 312 | case 1: 313 | menuExibirFila(&fila); 314 | break; 315 | 316 | case 2: 317 | menuEnqueue(&fila); 318 | break; 319 | 320 | case 3: 321 | menuDequeue(&fila); 322 | break; 323 | 324 | case 4: 325 | menuConsultarProximo(&fila); 326 | break; 327 | 328 | case 5: 329 | menuLimparFila(&fila); 330 | break; 331 | 332 | case 0: 333 | limparTela(); 334 | printf("╔══════════════════════════════════════╗\n"); 335 | printf("║ ATE A PROXIMA! ║\n"); 336 | printf("║ ║\n"); 337 | printf("║ Obrigado por usar o sistema! ║\n"); 338 | printf("╚══════════════════════════════════════╝\n\n"); 339 | break; 340 | 341 | default: 342 | limparTela(); 343 | printf("╔══════════════════════════════════════╗\n"); 344 | printf("║ OPCAO INVALIDA! ║\n"); 345 | printf("╚══════════════════════════════════════╝\n\n"); 346 | printf("Por favor, escolha uma opcao valida (0-5).\n"); 347 | pausar(); 348 | break; 349 | } 350 | } while (opcao != 0); 351 | 352 | return 0; 353 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tutoriais - Estruturas de Dados em C 2 | 3 | Este repositório contém implementações completas e didáticas de estruturas de dados fundamentais em linguagem C. Cada estrutura possui interface de usuário amigável, documentação detalhada e código bem comentado. 4 | 5 | ## Estruturas Implementadas 6 | 7 | ### 1. Lista Estática 8 | Uma estrutura de dados de tamanho fixo que armazena elementos em posições contíguas de memória. 9 | 10 | **Características:** 11 | - Tamanho fixo definido em tempo de compilação 12 | - Acesso direto por índice 13 | - Inserção e remoção com deslocamento de elementos 14 | - Sistema de gerenciamento de alunos 15 | 16 | **Documentação:** [Lista Estática](listas/estatica/README.md) 17 | 18 | **Arquivo:** `listas/estatica/main.c` 19 | 20 | --- 21 | 22 | ### 2. Lista Encadeada 23 | Uma estrutura dinâmica onde elementos são conectados através de ponteiros. 24 | 25 | **Características:** 26 | - Tamanho dinâmico (limitado apenas pela memória) 27 | - Alocação dinâmica com malloc/free 28 | - Inserção eficiente no início e fim 29 | - Sistema de gerenciamento de jogadores 30 | 31 | **Documentação:** [Lista Encadeada](listas/encadeada/README.md) 32 | 33 | **Arquivo:** `listas/encadeada/main.c` 34 | 35 | --- 36 | 37 | ### 3. Lista Encadeada Ordenada 38 | Variação da lista encadeada que mantém elementos automaticamente ordenados. 39 | 40 | **Características:** 41 | - Inserção automática na posição correta 42 | - Sempre mantém elementos em ordem alfabética 43 | - Otimizações de busca aproveitando a ordenação 44 | - Sistema de gerenciamento de jogadores ordenados 45 | 46 | **Documentação:** [Lista Encadeada Ordenada](listas/encadeada-ordenada/README.md) 47 | 48 | **Arquivo:** `listas/encadeada-ordenada/main.c` 49 | 50 | --- 51 | 52 | ### 4. Lista Duplamente Encadeada 53 | Uma estrutura dinâmica onde cada elemento possui ponteiros para o próximo e para o anterior. 54 | 55 | **Características:** 56 | - Navegação bidirecional (frente e trás) 57 | - Dois ponteiros por nó (ante e prox) 58 | - Operações simétricas de inserção/remoção 59 | - Remoção mais eficiente (não precisa buscar anterior) 60 | - Sistema de gerenciamento de jogadores 61 | 62 | **Documentação:** [Lista Duplamente Encadeada](listas/duplamente-encadeada/README.md) 63 | 64 | **Arquivo:** `listas/duplamente-encadeada/main.c` 65 | 66 | --- 67 | 68 | ## Filas (Queues) 69 | 70 | ### 5. Fila Estática 71 | Uma estrutura de dados FIFO (First In, First Out) implementada com array circular. 72 | 73 | **Características:** 74 | - Princípio FIFO: primeiro a entrar, primeiro a sair 75 | - Implementação circular para otimizar uso do array 76 | - Tamanho fixo definido em tempo de compilação 77 | - Operações de enqueue (inserir) e dequeue (remover) 78 | - Sistema de gerenciamento de processos 79 | 80 | **Documentação:** [Fila Estática](filas/estatica/README.md) 81 | 82 | **Arquivo:** `filas/estatica/main.c` 83 | 84 | --- 85 | 86 | ### 6. Fila Dinâmica 87 | Uma estrutura FIFO implementada com lista encadeada, sem limitação de tamanho. 88 | 89 | **Características:** 90 | - Crescimento dinâmico conforme demanda 91 | - Gestão automática de memória 92 | - Ponteiros para início e fim para operações O(1) 93 | - Estatísticas de uso de memória 94 | - Sistema de gerenciamento de tickets 95 | 96 | **Documentação:** [Fila Dinâmica](filas/dinamica/README.md) 97 | 98 | **Arquivo:** `filas/dinamica/main.c` 99 | 100 | --- 101 | 102 | ## Funcionalidades Comuns 103 | 104 | Todas as implementações incluem: 105 | 106 | ### Interface de Usuario 107 | - Menu interativo com navegação clara 108 | - Limpeza de tela automática 109 | - Status da estrutura no cabeçalho 110 | - Pausas para visualização de resultados 111 | - Tratamento de entrada com validações 112 | 113 | ### Operações Básicas 114 | - Inserção de elementos 115 | - Remoção de elementos 116 | - Busca/Pesquisa 117 | - Exibição formatada 118 | - Contagem de elementos 119 | 120 | ### Qualidade de Código 121 | - Código bem estruturado e comentado 122 | - Funções auxiliares para interface 123 | - Tratamento de erros 124 | - Gerenciamento adequado de memória 125 | - Portabilidade entre sistemas 126 | 127 | ## Como Compilar e Executar 128 | 129 | ### Pré-requisitos 130 | - Compilador GCC 131 | - Sistema operacional compatível (Windows, Linux, macOS) 132 | 133 | ### Compilação Individual 134 | Para compilar qualquer uma das estruturas: 135 | 136 | ```bash 137 | # Lista Estática 138 | cd listas/estatica 139 | gcc -o programa main.c 140 | ./programa 141 | 142 | # Lista Encadeada 143 | cd listas/encadeada 144 | gcc -o programa main.c 145 | ./programa 146 | 147 | # Lista Encadeada Ordenada 148 | cd listas/encadeada-ordenada 149 | gcc -o programa main.c 150 | ./programa 151 | 152 | # Lista Duplamente Encadeada 153 | cd listas/duplamente-encadeada 154 | gcc -o programa main.c 155 | ./programa 156 | 157 | # Fila Estática 158 | cd filas/estatica 159 | gcc -o programa main.c 160 | ./programa 161 | 162 | # Fila Dinâmica 163 | cd filas/dinamica 164 | gcc -o programa main.c 165 | ./programa 166 | ``` 167 | 168 | ### Compilação com Make (Opcional) 169 | ```bash 170 | # Para criar um Makefile personalizado 171 | make lista-estatica 172 | make lista-encadeada 173 | make lista-ordenada 174 | make lista-duplamente 175 | ``` 176 | 177 | ## Estrutura do Projeto 178 | 179 | ``` 180 | tutores-estruturas-de-dados/ 181 | ├── README.md # Este arquivo 182 | ├── listas/ 183 | │ ├── estatica/ 184 | │ │ ├── main.c # Implementação da lista estática 185 | │ │ └── README.md # Documentação detalhada 186 | │ ├── encadeada/ 187 | │ │ ├── main.c # Implementação da lista encadeada 188 | │ │ └── README.md # Documentação detalhada 189 | │ ├── encadeada-ordenada/ 190 | │ │ ├── main.c # Implementação da lista ordenada 191 | │ │ └── README.md # Documentação detalhada 192 | │ └── duplamente-encadeada/ 193 | │ ├── main.c # Implementação da lista duplamente encadeada 194 | │ └── README.md # Documentação detalhada 195 | ├── filas/ 196 | │ ├── estatica/ 197 | │ │ ├── main.c # Implementação da fila estática 198 | │ │ └── README.md # Documentação detalhada 199 | │ └── dinamica/ 200 | │ ├── main.c # Implementação da fila dinâmica 201 | │ └── README.md # Documentação detalhada 202 | ``` 203 | 204 | ## Características Técnicas 205 | 206 | ### Lista Estática 207 | - **Elemento:** Aluno (matrícula + nome) 208 | - **Tamanho:** 3 elementos (configurável) 209 | - **Operações:** Inserir por posição/fim, remover por posição, modificar, pesquisar 210 | 211 | ### Lista Encadeada 212 | - **Elemento:** Jogador (número da camisa + nome) 213 | - **Tamanho:** Dinâmico 214 | - **Operações:** Inserir início/fim, remover início/fim, pesquisar, remover específico 215 | 216 | ### Lista Encadeada Ordenada 217 | - **Elemento:** Jogador (número da camisa + nome) 218 | - **Ordenação:** Alfabética por nome 219 | - **Operações:** Inserir ordenado, remover início/fim, pesquisar, remover específico 220 | 221 | ### Lista Duplamente Encadeada 222 | - **Elemento:** Jogador (número da camisa + nome) 223 | - **Navegação:** Bidirecional (ante + prox) 224 | - **Operações:** Inserir início/fim, remover início/fim, pesquisar, remover específico 225 | 226 | ### Fila Estática 227 | - **Elemento:** Processo (ID + descrição) 228 | - **Princípio:** FIFO (First In, First Out) 229 | - **Implementação:** Array circular 230 | - **Operações:** Enqueue (inserir fim), dequeue (remover início), consultar próximo 231 | 232 | ### Fila Dinâmica 233 | - **Elemento:** Ticket (prioridade + tarefa) 234 | - **Princípio:** FIFO (First In, First Out) 235 | - **Implementação:** Lista encadeada 236 | - **Operações:** Enqueue (inserir fim), dequeue (remover início), estatísticas 237 | 238 | ## Conceitos Abordados 239 | 240 | ### Gerenciamento de Memória 241 | - Alocação estática (lista estática) 242 | - Alocação dinâmica (listas encadeadas) 243 | - Liberação adequada de memória 244 | - Prevenção de vazamentos 245 | 246 | ### Algoritmos 247 | - Inserção com deslocamento 248 | - Inserção ordenada 249 | - Busca linear 250 | - Remoção com reorganização 251 | 252 | ### Estruturas de Dados 253 | - Arrays e ponteiros 254 | - Estruturas (structs) 255 | - Ponteiros para estruturas 256 | - Encadeamento de nós 257 | - Filas e princípio FIFO 258 | - Arrays circulares 259 | 260 | ## Objetivos Educacionais 261 | 262 | Este projeto foi desenvolvido para: 263 | 264 | 1. **Ensinar conceitos fundamentais** de estruturas de dados 265 | 2. **Demonstrar diferentes abordagens** para o mesmo problema 266 | 3. **Mostrar trade-offs** entre diferentes implementações 267 | 4. **Fornecer código limpo e bem documentado** para estudo 268 | 5. **Incluir interface prática** para teste das implementações 269 | 270 | ## Comparação entre Estruturas 271 | 272 | | Aspecto | Lista Estática | Lista Encadeada | Lista Ordenada | Lista Dupla | Fila Estática | Fila Dinâmica | 273 | |---------|---------------|-----------------|----------------|-------------|---------------|---------------| 274 | | **Tamanho** | Fixo | Dinâmico | Dinâmico | Dinâmico | Fixo | Dinâmico | 275 | | **Memória** | Contígua | Fragmentada | Fragmentada | Fragmentada | Contígua | Fragmentada | 276 | | **Navegação** | Índice | Unidirecional | Unidirecional | Bidirecional | FIFO apenas | FIFO apenas | 277 | | **Inserção** | O(n) | O(1)/O(n) | O(n) | O(1)/O(n) | O(1) | O(1) | 278 | | **Remoção** | O(n) | O(1)/O(n) | O(1)/O(n) | O(1)/O(n) | O(1) | O(1) | 279 | | **Busca** | O(n) | O(n) | O(n)* | O(n) | N/A | N/A | 280 | | **Ordenação** | Manual | Manual | Automática | Manual | N/A | N/A | 281 | | **Acesso** | Qualquer | Sequencial | Sequencial | Sequencial | Extremidades | Extremidades | 282 | | **Complexidade** | Baixa | Média | Alta | Alta | Baixa | Média | 283 | 284 | *Pode terminar antes devido à ordenação 285 | N/A = Não aplicável (filas permitem acesso apenas às extremidades) 286 | 287 | ## Contribuições 288 | 289 | Este projeto é educacional e pode ser usado como: 290 | - Material de estudo para estruturas de dados 291 | - Base para projetos mais complexos 292 | - Referência para implementações em C 293 | - Exercícios práticos de programação 294 | 295 | ## Licença 296 | 297 | Este projeto é de domínio público e pode ser usado livremente para fins educacionais. 298 | 299 | --- 300 | 301 | **Desenvolvido como material didático para ensino de Estruturas de Dados em C** -------------------------------------------------------------------------------- /filas/estatica/README.md: -------------------------------------------------------------------------------- 1 | # Fila Estática em C 2 | 3 | ## Conceito 4 | 5 | Uma **Fila Estática** é uma estrutura de dados linear que segue o princípio FIFO (First In, First Out - Primeiro a Entrar, Primeiro a Sair). Os elementos são inseridos em uma extremidade (final da fila) e removidos da outra extremidade (início da fila), simulando uma fila do mundo real. A implementação estática utiliza um array de tamanho fixo com ponteiros para controlar o início e fim da fila. 6 | 7 | ### Características Principais 8 | 9 | - **FIFO (First In, First Out)**: O primeiro elemento inserido é o primeiro a ser removido 10 | - **Tamanho Fixo**: O número máximo de elementos é definido em tempo de compilação 11 | - **Fila Circular**: Utiliza aritmética modular para reutilizar posições do array 12 | - **Dois Ponteiros**: `inicio` (para remoção) e `fim` (para inserção) 13 | - **Controle de Tamanho**: Campo adicional para rastrear número de elementos 14 | 15 | ### Vantagens 16 | 17 | - **Simplicidade**: Implementação direta com array 18 | - **Eficiência**: Operações de inserção e remoção são O(1) 19 | - **Controle de Memória**: Não há alocação dinâmica 20 | - **Previsibilidade**: Comportamento determinístico de memória 21 | - **Baixo Overhead**: Não requer ponteiros extras por elemento 22 | 23 | ### Desvantagens 24 | 25 | - **Tamanho Limitado**: Não pode exceder o tamanho pré-definido 26 | - **Desperdício de Memória**: Pode reservar mais espaço do que necessário 27 | - **Rigidez**: Tamanho não pode ser alterado durante execução 28 | 29 | ## Estrutura de Dados 30 | 31 | ### Definição do Elemento (Processo) 32 | ```c 33 | typedef struct { 34 | int id; 35 | char descricao[50]; 36 | } Processo; 37 | ``` 38 | 39 | ### Definição da Fila Estática 40 | ```c 41 | typedef struct { 42 | Processo elementos[MAX_ELEMENTOS]; 43 | int inicio; 44 | int fim; 45 | int tamanho; 46 | } FilaEstatica; 47 | ``` 48 | 49 | - `elementos[]`: Array que armazena os dados 50 | - `inicio`: Índice do primeiro elemento (próximo a ser removido) 51 | - `fim`: Índice do último elemento inserido 52 | - `tamanho`: Número atual de elementos na fila 53 | 54 | ## Funcionamento da Fila Circular 55 | 56 | A implementação utiliza **fila circular** para otimizar o uso do array: 57 | 58 | ``` 59 | Estado Inicial: [_, _, _, _, _] inicio=0, fim=-1, tamanho=0 60 | 61 | Após inserir A: [A, _, _, _, _] inicio=0, fim=0, tamanho=1 62 | Após inserir B: [A, B, _, _, _] inicio=0, fim=1, tamanho=2 63 | Após inserir C: [A, B, C, _, _] inicio=0, fim=2, tamanho=3 64 | 65 | Após remover A: [_, B, C, _, _] inicio=1, fim=2, tamanho=2 66 | Após inserir D: [_, B, C, D, _] inicio=1, fim=3, tamanho=3 67 | Após inserir E: [_, B, C, D, E] inicio=1, fim=4, tamanho=4 68 | 69 | Após remover B: [_, _, C, D, E] inicio=2, fim=4, tamanho=3 70 | Após inserir F: [F, _, C, D, E] inicio=2, fim=0, tamanho=4 (circular!) 71 | ``` 72 | 73 | ## Funções Implementadas 74 | 75 | ### Funções Auxiliares 76 | 77 | #### `void limparBuffer()` 78 | Remove caracteres residuais do buffer de entrada, evitando problemas na leitura de dados. 79 | 80 | #### `void removerQuebraLinha(char *str)` 81 | Remove o caractere de quebra de linha ('\n') de uma string, normalmente após usar `fgets()`. 82 | 83 | #### `void limparTela()` 84 | Limpa a tela do terminal de forma compatível com Windows e sistemas Unix. 85 | 86 | #### `void pausar()` 87 | Pausa a execução e aguarda o usuário pressionar ENTER para continuar. 88 | 89 | #### `void exibirCabecalho(FilaEstatica *fila)` 90 | Exibe o cabeçalho do sistema com informações sobre o status atual da fila: 91 | - Status: VAZIA, PARCIAL ou CHEIA 92 | - Contador de processos (atual/máximo) 93 | 94 | ### Funções de Manipulação da Fila 95 | 96 | #### `void inicializarFila(FilaEstatica *fila)` 97 | **Descrição**: Inicializa uma fila estática vazia. 98 | 99 | **Parâmetros**: 100 | - `fila`: Ponteiro para a estrutura da fila 101 | 102 | **Funcionamento**: 103 | - Define `inicio = 0` 104 | - Define `fim = -1` 105 | - Define `tamanho = 0` 106 | 107 | **Complexidade**: O(1) 108 | 109 | --- 110 | 111 | #### `int filaVazia(FilaEstatica *fila)` 112 | **Descrição**: Verifica se a fila está vazia. 113 | 114 | **Parâmetros**: 115 | - `fila`: Ponteiro para a estrutura da fila 116 | 117 | **Retorno**: 118 | - `1` se a fila estiver vazia 119 | - `0` se a fila contiver elementos 120 | 121 | **Funcionamento**: Verifica se `tamanho == 0`. 122 | 123 | **Complexidade**: O(1) 124 | 125 | --- 126 | 127 | #### `int filaCheia(FilaEstatica *fila)` 128 | **Descrição**: Verifica se a fila atingiu sua capacidade máxima. 129 | 130 | **Parâmetros**: 131 | - `fila`: Ponteiro para a estrutura da fila 132 | 133 | **Retorno**: 134 | - `1` se a fila estiver cheia 135 | - `0` se ainda houver espaço 136 | 137 | **Funcionamento**: Verifica se `tamanho == MAX_ELEMENTOS`. 138 | 139 | **Complexidade**: O(1) 140 | 141 | --- 142 | 143 | #### `int enqueue(FilaEstatica *fila, Processo elemento)` 144 | **Descrição**: Insere um novo elemento no final da fila (operação de enfileiramento). 145 | 146 | **Parâmetros**: 147 | - `fila`: Ponteiro para a estrutura da fila 148 | - `elemento`: Estrutura Processo a ser inserida 149 | 150 | **Retorno**: 151 | - `1` se a inserção foi bem-sucedida 152 | - `0` se a fila estiver cheia 153 | 154 | **Funcionamento**: 155 | 1. Verifica se a fila está cheia 156 | 2. Calcula nova posição do fim usando aritmética modular: `(fim + 1) % MAX_ELEMENTOS` 157 | 3. Insere o elemento na nova posição do fim 158 | 4. Incrementa o tamanho 159 | 160 | **Complexidade**: O(1) 161 | 162 | **Exemplo**: 163 | ```c 164 | Processo p = {101, "Processo de Sistema"}; 165 | if (enqueue(&fila, p)) { 166 | printf("Processo inserido com sucesso!\n"); 167 | } 168 | ``` 169 | 170 | --- 171 | 172 | #### `Processo dequeue(FilaEstatica *fila)` 173 | **Descrição**: Remove o primeiro elemento da fila (operação de desenfileiramento). 174 | 175 | **Parâmetros**: 176 | - `fila`: Ponteiro para a estrutura da fila 177 | 178 | **Retorno**: 179 | - Estrutura Processo removida 180 | - Processo com id = -1 se a fila estiver vazia 181 | 182 | **Funcionamento**: 183 | 1. Verifica se a fila está vazia 184 | 2. Salva o elemento do início da fila 185 | 3. Atualiza o início usando aritmética modular: `(inicio + 1) % MAX_ELEMENTOS` 186 | 4. Decrementa o tamanho 187 | 5. Retorna o elemento removido 188 | 189 | **Complexidade**: O(1) 190 | 191 | **Exemplo**: 192 | ```c 193 | Processo removido = dequeue(&fila); 194 | if (removido.id != -1) { 195 | printf("Removido: %d - %s\n", removido.id, removido.descricao); 196 | } 197 | ``` 198 | 199 | --- 200 | 201 | #### `Processo consultarProximo(FilaEstatica *fila)` 202 | **Descrição**: Consulta o próximo elemento a ser removido sem removê-lo da fila. 203 | 204 | **Parâmetros**: 205 | - `fila`: Ponteiro para a estrutura da fila 206 | 207 | **Retorno**: 208 | - Estrutura Processo do início da fila 209 | - Processo com id = -1 se a fila estiver vazia 210 | 211 | **Funcionamento**: 212 | 1. Verifica se a fila está vazia 213 | 2. Retorna o elemento na posição `inicio` sem modificar a fila 214 | 215 | **Complexidade**: O(1) 216 | 217 | **Exemplo**: 218 | ```c 219 | Processo proximo = consultarProximo(&fila); 220 | if (proximo.id != -1) { 221 | printf("Próximo: %d - %s\n", proximo.id, proximo.descricao); 222 | } 223 | ``` 224 | 225 | ## Funções de Interface 226 | 227 | ### `void exibirMenu(FilaEstatica *fila, int *opcao)` 228 | Exibe o menu principal com opções específicas para fila e captura a escolha do usuário. 229 | 230 | ### `void menuExibirFila(FilaEstatica *fila)` 231 | Exibe todos os elementos da fila em ordem FIFO, mostrando: 232 | - Posição na fila (1 = próximo a ser atendido) 233 | - ID e descrição do processo 234 | - Total de processos na fila 235 | - Próximo processo a ser atendido 236 | 237 | ### `void menuEnqueue(FilaEstatica *fila)` 238 | Interface para inserção de novo processo no final da fila, com validação de fila cheia. 239 | 240 | ### `void menuDequeue(FilaEstatica *fila)` 241 | Interface para remoção do primeiro processo da fila, mostrando: 242 | - Processo que será removido 243 | - Processo removido 244 | - Próximo processo da fila (se houver) 245 | 246 | ### `void menuConsultarProximo(FilaEstatica *fila)` 247 | Interface para consultar o próximo processo sem removê-lo, exibindo detalhes formatados. 248 | 249 | ### `void menuLimparFila(FilaEstatica *fila)` 250 | Interface para limpar toda a fila com confirmação do usuário, incluindo aviso sobre a operação destrutiva. 251 | 252 | ## Aplicações Práticas 253 | 254 | ### Sistemas Operacionais 255 | - **Escalonamento de Processos**: Fila de processos prontos para execução 256 | - **Gerenciamento de Impressão**: Fila de documentos para impressora 257 | - **Buffer de Entrada/Saída**: Fila de dados aguardando processamento 258 | 259 | ### Simulações 260 | - **Atendimento em Bancos**: Fila de clientes 261 | - **Controle de Tráfego**: Fila de veículos em semáforo 262 | - **Sistemas de Chamadas**: Fila de chamadas telefônicas 263 | 264 | ### Algoritmos 265 | - **Busca em Largura (BFS)**: Fila de vértices a serem visitados 266 | - **Algoritmos de Grafos**: Processamento de nós em ordem específica 267 | 268 | ## Compilação e Execução 269 | 270 | ```bash 271 | gcc -o programa main.c 272 | ./programa 273 | ``` 274 | 275 | ## Análise de Complexidade 276 | 277 | | Operação | Complexidade Temporal | Complexidade Espacial | 278 | |----------|----------------------|----------------------| 279 | | **Inicializar** | O(1) | O(1) | 280 | | **Enqueue** | O(1) | O(1) | 281 | | **Dequeue** | O(1) | O(1) | 282 | | **Consultar** | O(1) | O(1) | 283 | | **Verificar Vazia/Cheia** | O(1) | O(1) | 284 | | **Exibir Fila** | O(n) | O(1) | 285 | 286 | ## Vantagens da Implementação Circular 287 | 288 | 1. **Reutilização de Espaço**: Posições liberadas podem ser reutilizadas 289 | 2. **Eficiência**: Não há necessidade de deslocar elementos 290 | 3. **Simplicidade**: Operações O(1) para inserção e remoção 291 | 4. **Otimização de Memória**: Aproveita todo o espaço do array 292 | 293 | ## Considerações de Implementação 294 | 295 | 1. **Aritmética Modular**: Uso de `%` para implementar comportamento circular 296 | 2. **Campo Tamanho**: Essencial para distinguir fila vazia de fila cheia 297 | 3. **Validações**: Verificações em todas as operações críticas 298 | 4. **Estado Consistente**: Manutenção de invariantes da estrutura 299 | 5. **Interface Robusta**: Tratamento de casos excepcionais 300 | 301 | ## Comparação: Fila vs Lista 302 | 303 | | Aspecto | Fila | Lista | 304 | |---------|------|-------| 305 | | **Acesso** | Apenas início e fim | Qualquer posição | 306 | | **Inserção** | Apenas no fim | Qualquer posição | 307 | | **Remoção** | Apenas do início | Qualquer posição | 308 | | **Uso Típico** | Escalonamento, buffering | Armazenamento geral | 309 | | **Complexidade** | O(1) para operações básicas | O(n) para busca/inserção | 310 | 311 | --- 312 | 313 | **Desenvolvido como material didático para ensino de Estruturas de Dados em C** -------------------------------------------------------------------------------- /listas/encadeada/README.md: -------------------------------------------------------------------------------- 1 | # Lista Encadeada em C 2 | 3 | ## Conceito 4 | 5 | Uma **Lista Encadeada** é uma estrutura de dados linear e dinâmica onde os elementos não são armazenados em posições contíguas de memória. Cada elemento (nó) contém dados e um ponteiro para o próximo elemento da sequência. Esta estrutura permite inserção e remoção eficientes em qualquer posição, com tamanho limitado apenas pela memória disponível. 6 | 7 | ### Características Principais 8 | 9 | - **Tamanho Dinâmico**: Cresce e diminui conforme necessário durante a execução 10 | - **Alocação Dinâmica**: Usa `malloc()` e `free()` para gerenciar memória 11 | - **Acesso Sequencial**: Para acessar um elemento, deve percorrer desde o início 12 | - **Ponteiros**: Cada nó aponta para o próximo elemento da lista 13 | 14 | ### Vantagens 15 | 16 | - **Flexibilidade de Tamanho**: Não tem limite pré-definido de elementos 17 | - **Eficiência de Inserção/Remoção**: Operações O(1) quando se tem o ponteiro do nó 18 | - **Uso Eficiente de Memória**: Aloca apenas o necessário 19 | - **Inserção em Qualquer Posição**: Facilita reorganização dos dados 20 | 21 | ### Desvantagens 22 | 23 | - **Overhead de Memória**: Cada nó precisa armazenar um ponteiro adicional 24 | - **Acesso Sequencial**: Não permite acesso direto por índice como arrays 25 | - **Fragmentação de Memória**: Nós podem estar espalhados pela memória 26 | - **Complexidade**: Mais complexa de implementar que arrays 27 | 28 | ## Estrutura de Dados 29 | 30 | ### Definição do Elemento (Jogador) 31 | ```c 32 | typedef struct { 33 | int numCamisa; 34 | char nome[50]; 35 | } Jogador; 36 | ``` 37 | 38 | ### Definição da Célula (Nó) 39 | ```c 40 | typedef struct celula { 41 | Jogador info; 42 | struct celula *prox; 43 | } Celula; 44 | ``` 45 | 46 | - `info`: Dados armazenados no nó 47 | - `prox`: Ponteiro para o próximo nó (NULL se for o último) 48 | 49 | ## Funções Implementadas 50 | 51 | ### Funções Auxiliares 52 | 53 | #### `void limparBuffer()` 54 | Remove caracteres residuais do buffer de entrada, evitando problemas na leitura de dados. 55 | 56 | #### `void removerQuebraLinha(char *str)` 57 | Remove o caractere de quebra de linha ('\n') de uma string, normalmente após usar `fgets()`. 58 | 59 | #### `void limparTela()` 60 | Limpa a tela do terminal de forma compatível com Windows e sistemas Unix. 61 | 62 | #### `void pausar()` 63 | Pausa a execução e aguarda o usuário pressionar ENTER para continuar. 64 | 65 | #### `int contarElementos(Celula **lista)` 66 | Percorre a lista e retorna o número total de elementos armazenados. 67 | 68 | #### `void exibirCabecalho(Celula **lista)` 69 | Exibe o cabeçalho do sistema com informações sobre o status atual da lista: 70 | - Status: VAZIA ou COM DADOS 71 | - Contador de jogadores 72 | 73 | ### Funções de Manipulação da Lista 74 | 75 | #### `void inicializarLista(Celula **lista)` 76 | **Descrição**: Inicializa uma lista encadeada vazia. 77 | 78 | **Parâmetros**: 79 | - `lista`: Ponteiro duplo para o primeiro nó da lista 80 | 81 | **Funcionamento**: Define o ponteiro da lista como NULL, indicando lista vazia. 82 | 83 | **Complexidade**: O(1) 84 | 85 | --- 86 | 87 | #### `int listaVazia(Celula **lista)` 88 | **Descrição**: Verifica se a lista está vazia. 89 | 90 | **Parâmetros**: 91 | - `lista`: Ponteiro duplo para o primeiro nó da lista 92 | 93 | **Retorno**: 94 | - `1` se a lista estiver vazia 95 | - `0` se a lista contiver elementos 96 | 97 | **Funcionamento**: Verifica se o ponteiro da lista é NULL. 98 | 99 | **Complexidade**: O(1) 100 | 101 | --- 102 | 103 | #### `Celula * criarCelula()` 104 | **Descrição**: Aloca dinamicamente memória para um novo nó. 105 | 106 | **Retorno**: 107 | - Ponteiro para a nova célula alocada 108 | - NULL se não conseguir alocar memória 109 | 110 | **Funcionamento**: Usa `malloc()` para alocar memória do tamanho de uma Celula. 111 | 112 | **Complexidade**: O(1) 113 | 114 | --- 115 | 116 | #### `int inserirInicio(Celula **lista, Jogador elemento)` 117 | **Descrição**: Insere um novo elemento no início da lista. 118 | 119 | **Parâmetros**: 120 | - `lista`: Ponteiro duplo para o primeiro nó da lista 121 | - `elemento`: Estrutura Jogador a ser inserida 122 | 123 | **Retorno**: 124 | - `1` se a inserção foi bem-sucedida 125 | - `0` se houve erro de alocação de memória 126 | 127 | **Funcionamento**: 128 | 1. Cria uma nova célula 129 | 2. Define o conteúdo da célula 130 | 3. Faz a nova célula apontar para o antigo primeiro elemento 131 | 4. Atualiza o ponteiro da lista para a nova célula 132 | 133 | **Complexidade**: O(1) 134 | 135 | --- 136 | 137 | #### `int inserirFim(Celula **lista, Jogador elemento)` 138 | **Descrição**: Insere um novo elemento no final da lista. 139 | 140 | **Parâmetros**: 141 | - `lista`: Ponteiro duplo para o primeiro nó da lista 142 | - `elemento`: Estrutura Jogador a ser inserida 143 | 144 | **Retorno**: 145 | - `1` se a inserção foi bem-sucedida 146 | - `0` se houve erro de alocação de memória 147 | 148 | **Funcionamento**: 149 | 1. Cria uma nova célula 150 | 2. Se a lista estiver vazia, insere como primeiro elemento 151 | 3. Caso contrário, percorre até o último nó 152 | 4. Faz o último nó apontar para a nova célula 153 | 154 | **Complexidade**: O(n) para encontrar o final da lista 155 | 156 | --- 157 | 158 | #### `Jogador removerInicio(Celula **lista)` 159 | **Descrição**: Remove o primeiro elemento da lista. 160 | 161 | **Parâmetros**: 162 | - `lista`: Ponteiro duplo para o primeiro nó da lista 163 | 164 | **Retorno**: 165 | - Estrutura Jogador removida 166 | - Jogador com numCamisa = -1 se a lista estiver vazia 167 | 168 | **Funcionamento**: 169 | 1. Verifica se a lista não está vazia 170 | 2. Salva os dados do primeiro elemento 171 | 3. Atualiza o ponteiro da lista para o segundo elemento 172 | 4. Libera a memória do primeiro elemento 173 | 5. Retorna os dados salvos 174 | 175 | **Complexidade**: O(1) 176 | 177 | --- 178 | 179 | #### `Jogador removerFim(Celula **lista)` 180 | **Descrição**: Remove o último elemento da lista. 181 | 182 | **Parâmetros**: 183 | - `lista`: Ponteiro duplo para o primeiro nó da lista 184 | 185 | **Retorno**: 186 | - Estrutura Jogador removida 187 | - Jogador com numCamisa = -1 se a lista estiver vazia 188 | 189 | **Funcionamento**: 190 | 1. Verifica se a lista não está vazia 191 | 2. Se há apenas um elemento, remove do início 192 | 3. Percorre até o penúltimo elemento 193 | 4. Salva os dados do último elemento 194 | 5. Faz o penúltimo apontar para NULL 195 | 6. Libera a memória do último elemento 196 | 197 | **Complexidade**: O(n) para encontrar o final da lista 198 | 199 | --- 200 | 201 | #### `Celula * pesquisar(Celula **lista, Jogador pesquisado)` 202 | **Descrição**: Busca um elemento na lista pelo nome do jogador. 203 | 204 | **Parâmetros**: 205 | - `lista`: Ponteiro duplo para o primeiro nó da lista 206 | - `pesquisado`: Estrutura Jogador com o nome a ser encontrado 207 | 208 | **Retorno**: 209 | - Ponteiro para a célula encontrada 210 | - NULL se não encontrou ou lista vazia 211 | 212 | **Funcionamento**: 213 | 1. Verifica se a lista não está vazia 214 | 2. Percorre a lista comparando nomes 215 | 3. Retorna ponteiro para a primeira ocorrência encontrada 216 | 217 | **Complexidade**: O(n) no pior caso (elemento no final ou não encontrado) 218 | 219 | --- 220 | 221 | #### `Jogador removerElemento(Celula **lista, Jogador elemento)` 222 | **Descrição**: Remove um elemento específico da lista baseado no nome. 223 | 224 | **Parâmetros**: 225 | - `lista`: Ponteiro duplo para o primeiro nó da lista 226 | - `elemento`: Estrutura Jogador com o nome a ser removido 227 | 228 | **Retorno**: 229 | - Estrutura Jogador removida 230 | - Jogador com numCamisa = -1 se não encontrou 231 | 232 | **Funcionamento**: 233 | 1. Usa a função pesquisar para localizar o elemento 234 | 2. Se é o primeiro elemento, usa removerInicio() 235 | 3. Caso contrário, encontra o elemento anterior 236 | 4. Ajusta os ponteiros para "pular" o elemento removido 237 | 5. Libera a memória do elemento removido 238 | 239 | **Complexidade**: O(n) para encontrar o elemento 240 | 241 | --- 242 | 243 | #### `Jogador criarElemento(int numCamisa, char nome[])` 244 | **Descrição**: Função auxiliar para criar uma estrutura Jogador. 245 | 246 | **Parâmetros**: 247 | - `numCamisa`: Número da camisa do jogador 248 | - `nome`: Nome do jogador 249 | 250 | **Retorno**: Estrutura Jogador preenchida 251 | 252 | **Funcionamento**: Cria e preenche uma estrutura Jogador com os dados fornecidos. 253 | 254 | **Complexidade**: O(1) 255 | 256 | --- 257 | 258 | #### `int compararElemento(Jogador j1, Jogador j2)` 259 | **Descrição**: Compara dois jogadores pelos nomes. 260 | 261 | **Parâmetros**: 262 | - `j1`, `j2`: Estruturas Jogador a serem comparadas 263 | 264 | **Retorno**: 265 | - 0 se os nomes são iguais 266 | - Valor diferente de 0 se são diferentes 267 | 268 | **Funcionamento**: Usa `strcmp()` para comparar os nomes dos jogadores. 269 | 270 | **Complexidade**: O(m) onde m é o tamanho da string 271 | 272 | ## Funções de Interface 273 | 274 | ### `void exibirMenu(Celula **lista, int *opcao)` 275 | Exibe o menu principal com opções específicas para lista encadeada e captura a escolha do usuário. 276 | 277 | ### `void menuExibirElementos(Celula **lista)` 278 | Percorre e exibe todos os elementos da lista em formato de tabela, incluindo contador. 279 | 280 | ### `void menuInserirInicio(Celula **lista)` 281 | Interface para inserção de elemento no início da lista. 282 | 283 | ### `void menuInserirFim(Celula **lista)` 284 | Interface para inserção de elemento no final da lista. 285 | 286 | ### `void menuRemoverInicio(Celula **lista)` 287 | Interface para remoção do primeiro elemento, com confirmação do elemento removido. 288 | 289 | ### `void menuRemoverFim(Celula **lista)` 290 | Interface para remoção do último elemento, com confirmação do elemento removido. 291 | 292 | ### `void menuPesquisarElemento(Celula **lista)` 293 | Interface para busca de elemento por nome, exibindo resultado formatado. 294 | 295 | ### `void menuRemoverElemento(Celula **lista)` 296 | Interface para remoção de elemento específico por nome. 297 | 298 | ## Compilação e Execução 299 | 300 | ```bash 301 | gcc -o programa main.c 302 | ./programa 303 | ``` 304 | 305 | ## Gerenciamento de Memória 306 | 307 | Esta implementação utiliza alocação dinâmica de memória: 308 | 309 | - **Alocação**: `malloc()` para criar novos nós 310 | - **Liberação**: `free()` para remover nós da memória 311 | - **Cuidados**: Sempre verificar se a alocação foi bem-sucedida 312 | - **Vazamentos**: Garantir que toda memória alocada seja eventualmente liberada 313 | 314 | ## Considerações de Implementação 315 | 316 | 1. **Ponteiros Duplos**: Usados para permitir modificação do primeiro elemento 317 | 2. **Verificação de Memória**: Todas as alocações são verificadas antes do uso 318 | 3. **Casos Especiais**: Tratamento específico para lista vazia e elemento único 319 | 4. **Interface Consistente**: Retornos padronizados para indicar sucesso/erro 320 | 5. **Robustez**: Validações em todas as operações críticas 321 | -------------------------------------------------------------------------------- /deques/estatico/README.md: -------------------------------------------------------------------------------- 1 | # Deque Estático em C 2 | 3 | ## Conceito 4 | 5 | Um **Deque** (Double-ended Queue - Fila de Duas Pontas) é uma estrutura de dados linear que permite inserção e remoção de elementos em ambas as extremidades. Combina características de pilhas (LIFO) e filas (FIFO), oferecendo máxima flexibilidade para operações nas extremidades. A implementação estática utiliza um array circular com controle de início e fim. 6 | 7 | ### Características Principais 8 | 9 | - **Dupla Extremidade**: Inserção e remoção no início e no fim 10 | - **Flexibilidade**: Pode funcionar como pilha ou fila 11 | - **Array Circular**: Otimiza o uso do espaço disponível 12 | - **Tamanho Fixo**: Definido em tempo de compilação 13 | - **Operações O(1)**: Todas as operações básicas são constantes 14 | 15 | ### Vantagens 16 | 17 | - **Versatilidade**: Combina pilha e fila em uma estrutura 18 | - **Eficiência**: Operações O(1) em ambas as extremidades 19 | - **Simplicidade**: Implementação direta com array 20 | - **Previsibilidade**: Comportamento determinístico de memória 21 | - **Baixo Overhead**: Não requer ponteiros extras 22 | 23 | ### Desvantagens 24 | 25 | - **Tamanho Limitado**: Não pode exceder o tamanho pré-definido 26 | - **Rigidez**: Tamanho não pode ser alterado durante execução 27 | - **Desperdício Potencial**: Pode reservar mais espaço que necessário 28 | 29 | ## Estrutura de Dados 30 | 31 | ### Definição do Elemento (Cliente) 32 | ```c 33 | typedef struct { 34 | int codigo; 35 | char nome[60]; 36 | } Cliente; 37 | ``` 38 | 39 | ### Definição do Deque Estático 40 | ```c 41 | typedef struct { 42 | Cliente elementos[MAX_ELEMENTOS]; 43 | int inicio; 44 | int fim; 45 | int tamanho; 46 | } DequeEstatico; 47 | ``` 48 | 49 | - `elementos[]`: Array que armazena os dados 50 | - `inicio`: Índice do primeiro elemento 51 | - `fim`: Índice do último elemento 52 | - `tamanho`: Número atual de elementos no deque 53 | 54 | ## Funcionamento do Array Circular 55 | 56 | O deque utiliza **array circular** para maximizar eficiência: 57 | 58 | ``` 59 | Estado Inicial: [_, _, _, _, _, _] inicio=0, fim=-1, tamanho=0 60 | 61 | Inserir A no fim: [A, _, _, _, _, _] inicio=0, fim=0, tamanho=1 62 | Inserir B no início: [A, _, _, _, _, B] inicio=5, fim=0, tamanho=2 63 | Inserir C no fim: [A, C, _, _, _, B] inicio=5, fim=1, tamanho=3 64 | 65 | Visualização lógica: B ← A ← C 66 | ↑ ↑ 67 | início fim 68 | ``` 69 | 70 | ## Funções Implementadas 71 | 72 | ### Funções Auxiliares 73 | 74 | #### `void limparBuffer()` 75 | Remove caracteres residuais do buffer de entrada. 76 | 77 | #### `void removerQuebraLinha(char *str)` 78 | Remove o caractere de quebra de linha de uma string. 79 | 80 | #### `void limparTela()` 81 | Limpa a tela do terminal de forma multiplataforma. 82 | 83 | #### `void pausar()` 84 | Pausa a execução aguardando ENTER do usuário. 85 | 86 | #### `void exibirCabecalho(DequeEstatico *deque)` 87 | Exibe cabeçalho com status do deque (VAZIO/PARCIAL/CHEIO) e contador. 88 | 89 | ### Funções de Manipulação do Deque 90 | 91 | #### `void inicializarDeque(DequeEstatico *deque)` 92 | **Descrição**: Inicializa um deque estático vazio. 93 | 94 | **Parâmetros**: 95 | - `deque`: Ponteiro para a estrutura do deque 96 | 97 | **Funcionamento**: 98 | - Define `inicio = 0` 99 | - Define `fim = -1` 100 | - Define `tamanho = 0` 101 | 102 | **Complexidade**: O(1) 103 | 104 | --- 105 | 106 | #### `int dequeVazio(DequeEstatico *deque)` 107 | **Descrição**: Verifica se o deque está vazio. 108 | 109 | **Retorno**: 110 | - `1` se vazio (`tamanho == 0`) 111 | - `0` se contém elementos 112 | 113 | **Complexidade**: O(1) 114 | 115 | --- 116 | 117 | #### `int dequeCheio(DequeEstatico *deque)` 118 | **Descrição**: Verifica se o deque atingiu capacidade máxima. 119 | 120 | **Retorno**: 121 | - `1` se cheio (`tamanho == MAX_ELEMENTOS`) 122 | - `0` se há espaço disponível 123 | 124 | **Complexidade**: O(1) 125 | 126 | --- 127 | 128 | #### `int inserirInicio(DequeEstatico *deque, Cliente elemento)` 129 | **Descrição**: Insere elemento no início do deque. 130 | 131 | **Parâmetros**: 132 | - `deque`: Ponteiro para a estrutura do deque 133 | - `elemento`: Cliente a ser inserido 134 | 135 | **Retorno**: 136 | - `1` se inserção bem-sucedida 137 | - `0` se deque cheio 138 | 139 | **Funcionamento**: 140 | 1. Verifica se deque está cheio 141 | 2. Calcula nova posição do início: `(inicio - 1 + MAX_ELEMENTOS) % MAX_ELEMENTOS` 142 | 3. Insere elemento na nova posição 143 | 4. Incrementa tamanho 144 | 145 | **Complexidade**: O(1) 146 | 147 | **Exemplo**: 148 | ```c 149 | Cliente c = {101, "João Silva"}; 150 | if (inserirInicio(&deque, c)) { 151 | printf("Cliente inserido no início!\n"); 152 | } 153 | ``` 154 | 155 | --- 156 | 157 | #### `int inserirFim(DequeEstatico *deque, Cliente elemento)` 158 | **Descrição**: Insere elemento no fim do deque. 159 | 160 | **Funcionamento**: 161 | 1. Verifica se deque está cheio 162 | 2. Calcula nova posição do fim: `(fim + 1) % MAX_ELEMENTOS` 163 | 3. Insere elemento na nova posição 164 | 4. Incrementa tamanho 165 | 166 | **Complexidade**: O(1) 167 | 168 | --- 169 | 170 | #### `Cliente removerInicio(DequeEstatico *deque)` 171 | **Descrição**: Remove elemento do início do deque. 172 | 173 | **Retorno**: 174 | - Cliente removido 175 | - Cliente com código -1 se deque vazio 176 | 177 | **Funcionamento**: 178 | 1. Verifica se deque está vazio 179 | 2. Salva elemento a ser removido 180 | 3. Atualiza início: `(inicio + 1) % MAX_ELEMENTOS` 181 | 4. Decrementa tamanho 182 | 5. Retorna elemento removido 183 | 184 | **Complexidade**: O(1) 185 | 186 | --- 187 | 188 | #### `Cliente removerFim(DequeEstatico *deque)` 189 | **Descrição**: Remove elemento do fim do deque. 190 | 191 | **Funcionamento**: 192 | 1. Verifica se deque está vazio 193 | 2. Salva elemento a ser removido 194 | 3. Atualiza fim: `(fim - 1 + MAX_ELEMENTOS) % MAX_ELEMENTOS` 195 | 4. Decrementa tamanho 196 | 5. Retorna elemento removido 197 | 198 | **Complexidade**: O(1) 199 | 200 | --- 201 | 202 | #### `Cliente consultarInicio(DequeEstatico *deque)` 203 | **Descrição**: Consulta primeiro elemento sem removê-lo. 204 | 205 | **Retorno**: Cliente do início ou código -1 se vazio 206 | 207 | **Complexidade**: O(1) 208 | 209 | --- 210 | 211 | #### `Cliente consultarFim(DequeEstatico *deque)` 212 | **Descrição**: Consulta último elemento sem removê-lo. 213 | 214 | **Retorno**: Cliente do fim ou código -1 se vazio 215 | 216 | **Complexidade**: O(1) 217 | 218 | ## Funções de Interface 219 | 220 | ### `void exibirMenu(DequeEstatico *deque, int *opcao)` 221 | Exibe menu principal com 9 opções específicas para deque. 222 | 223 | ### `void menuExibirDeque(DequeEstatico *deque)` 224 | Exibe todos os elementos com indicadores visuais: 225 | - Posição no deque 226 | - Marcadores (I) para início, (F) para fim 227 | - Informações dos extremos 228 | - Contador total 229 | 230 | ### `void menuInserirInicio(DequeEstatico *deque)` 231 | Interface para inserção no início com validação de deque cheio. 232 | 233 | ### `void menuInserirFim(DequeEstatico *deque)` 234 | Interface para inserção no fim com validação de deque cheio. 235 | 236 | ### `void menuRemoverInicio(DequeEstatico *deque)` 237 | Interface para remoção do início mostrando: 238 | - Elemento que será removido 239 | - Confirmação da remoção 240 | - Novo primeiro elemento (se houver) 241 | 242 | ### `void menuRemoverFim(DequeEstatico *deque)` 243 | Interface para remoção do fim com feedback similar. 244 | 245 | ### `void menuConsultarInicio(DequeEstatico *deque)` 246 | Interface para consultar primeiro elemento sem remover. 247 | 248 | ### `void menuConsultarFim(DequeEstatico *deque)` 249 | Interface para consultar último elemento sem remover. 250 | 251 | ### `void menuLimparDeque(DequeEstatico *deque)` 252 | Interface para limpar todo o deque com confirmação do usuário. 253 | 254 | ## Aplicações Práticas 255 | 256 | ### Sistemas de Atendimento 257 | - **Fila Prioritária**: Clientes VIP entram no início 258 | - **Atendimento Flexível**: Remoção de ambas as extremidades 259 | - **Cancelamentos**: Remoção do fim para últimos inseridos 260 | 261 | ### Algoritmos 262 | - **Busca Bidirecional**: Exploração de ambas as direções 263 | - **Sliding Window**: Janela deslizante em arrays 264 | - **Palindrome Check**: Verificação de palíndromos 265 | 266 | ### Sistemas de Cache 267 | - **LRU Cache**: Elementos recentes no início 268 | - **Eviction Policy**: Remoção flexível de extremidades 269 | 270 | ## Compilação e Execução 271 | 272 | ```bash 273 | gcc -o programa main.c 274 | ./programa 275 | ``` 276 | 277 | ## Análise de Complexidade 278 | 279 | | Operação | Complexidade Temporal | Complexidade Espacial | 280 | |----------|----------------------|----------------------| 281 | | **Inicializar** | O(1) | O(1) | 282 | | **Inserir Início** | O(1) | O(1) | 283 | | **Inserir Fim** | O(1) | O(1) | 284 | | **Remover Início** | O(1) | O(1) | 285 | | **Remover Fim** | O(1) | O(1) | 286 | | **Consultar** | O(1) | O(1) | 287 | | **Verificar Estado** | O(1) | O(1) | 288 | | **Exibir Deque** | O(n) | O(1) | 289 | 290 | ## Vantagens da Implementação Circular 291 | 292 | 1. **Reutilização Eficiente**: Posições liberadas são reutilizadas 293 | 2. **Operações Simétricas**: Início e fim têm mesma eficiência 294 | 3. **Sem Deslocamentos**: Não move elementos desnecessariamente 295 | 4. **Aproveitamento Máximo**: Usa todo o espaço do array 296 | 297 | ## Padrões de Uso 298 | 299 | ### Como Pilha (LIFO) 300 | ```c 301 | // Inserir e remover sempre do mesmo lado 302 | inserirInicio(&deque, elemento); 303 | elemento = removerInicio(&deque); 304 | ``` 305 | 306 | ### Como Fila (FIFO) 307 | ```c 308 | // Inserir em um lado, remover do outro 309 | inserirFim(&deque, elemento); 310 | elemento = removerInicio(&deque); 311 | ``` 312 | 313 | ### Como Deque (Flexível) 314 | ```c 315 | // Operações em ambas as extremidades conforme necessário 316 | inserirInicio(&deque, elementoUrgente); 317 | inserirFim(&deque, elementoNormal); 318 | elemento = removerInicio(&deque); // Processa urgente primeiro 319 | ``` 320 | 321 | ## Comparação: Deque vs Outras Estruturas 322 | 323 | | Aspecto | Deque | Pilha | Fila | Lista | 324 | |---------|-------|-------|------|-------| 325 | | **Inserção** | Início/Fim | Apenas topo | Apenas fim | Qualquer posição | 326 | | **Remoção** | Início/Fim | Apenas topo | Apenas início | Qualquer posição | 327 | | **Flexibilidade** | Alta | Baixa | Baixa | Muito Alta | 328 | | **Eficiência** | O(1) extremos | O(1) topo | O(1) extremos | O(n) geral | 329 | | **Uso de Memória** | Eficiente | Eficiente | Eficiente | Variável | 330 | 331 | ## Considerações de Implementação 332 | 333 | 1. **Aritmética Modular**: Essencial para comportamento circular 334 | 2. **Controle de Estado**: Distinção entre vazio e cheio 335 | 3. **Validações**: Verificações em todas as operações 336 | 4. **Interface Clara**: Indicadores visuais para extremos 337 | 5. **Consistência**: Manutenção de invariantes da estrutura 338 | 339 | --- 340 | 341 | **Desenvolvido como material didático para ensino de Estruturas de Dados em C** -------------------------------------------------------------------------------- /listas/encadeada-ordenada/README.md: -------------------------------------------------------------------------------- 1 | # Lista Encadeada Ordenada em C 2 | 3 | ## Conceito 4 | 5 | Uma **Lista Encadeada Ordenada** é uma variação da lista encadeada onde os elementos são mantidos em ordem crescente automaticamente. Cada inserção é feita na posição correta para manter a ordenação, eliminando a necessidade de ordenação posterior. Esta estrutura combina a flexibilidade de tamanho dinâmico com a vantagem de sempre manter os dados organizados. 6 | 7 | ### Características Principais 8 | 9 | - **Ordenação Automática**: Elementos sempre mantidos em ordem crescente 10 | - **Tamanho Dinâmico**: Cresce e diminui conforme necessário durante a execução 11 | - **Inserção Posicionada**: Novo elemento é inserido na posição correta automaticamente 12 | - **Acesso Sequencial Ordenado**: Percurso sempre resulta em sequência ordenada 13 | 14 | ### Vantagens 15 | 16 | - **Dados Sempre Ordenados**: Não requer ordenação posterior 17 | - **Busca Mais Eficiente**: Pode parar a busca quando encontra elemento maior 18 | - **Flexibilidade de Tamanho**: Não tem limite pré-definido de elementos 19 | - **Inserção Inteligente**: Posicionamento automático mantém ordem 20 | 21 | ### Desvantagens 22 | 23 | - **Inserção Mais Lenta**: Precisa encontrar posição correta O(n) 24 | - **Overhead de Comparação**: Cada inserção requer comparações 25 | - **Complexidade**: Mais complexa que lista encadeada simples 26 | - **Não Permite Inserção Arbitrária**: Posição é determinada pela ordenação 27 | 28 | ## Estrutura de Dados 29 | 30 | ### Definição do Elemento (Jogador) 31 | ```c 32 | typedef struct { 33 | int numCamisa; 34 | char nome[50]; 35 | } Jogador; 36 | ``` 37 | 38 | ### Definição da Célula (Nó) 39 | ```c 40 | typedef struct celula { 41 | Jogador info; 42 | struct celula *prox; 43 | } Celula; 44 | ``` 45 | 46 | - `info`: Dados armazenados no nó 47 | - `prox`: Ponteiro para o próximo nó (NULL se for o último) 48 | 49 | **Critério de Ordenação**: Os elementos são ordenados alfabeticamente pelo campo `nome`. 50 | 51 | ## Funções Implementadas 52 | 53 | ### Funções Auxiliares 54 | 55 | #### `void limparBuffer()` 56 | Remove caracteres residuais do buffer de entrada, evitando problemas na leitura de dados. 57 | 58 | #### `void removerQuebraLinha(char *str)` 59 | Remove o caractere de quebra de linha ('\n') de uma string, normalmente após usar `fgets()`. 60 | 61 | #### `void limparTela()` 62 | Limpa a tela do terminal de forma compatível com Windows e sistemas Unix. 63 | 64 | #### `void pausar()` 65 | Pausa a execução e aguarda o usuário pressionar ENTER para continuar. 66 | 67 | #### `int contarElementos(Celula **lista)` 68 | Percorre a lista e retorna o número total de elementos armazenados. 69 | 70 | #### `void exibirCabecalho(Celula **lista)` 71 | Exibe o cabeçalho do sistema com informações sobre o status atual da lista: 72 | - Status: VAZIA ou ORDENADA 73 | - Contador de jogadores 74 | 75 | ### Funções de Manipulação da Lista 76 | 77 | #### `void inicializarLista(Celula **lista)` 78 | **Descrição**: Inicializa uma lista encadeada ordenada vazia. 79 | 80 | **Parâmetros**: 81 | - `lista`: Ponteiro duplo para o primeiro nó da lista 82 | 83 | **Funcionamento**: Define o ponteiro da lista como NULL, indicando lista vazia. 84 | 85 | **Complexidade**: O(1) 86 | 87 | --- 88 | 89 | #### `int listaVazia(Celula **lista)` 90 | **Descrição**: Verifica se a lista está vazia. 91 | 92 | **Parâmetros**: 93 | - `lista`: Ponteiro duplo para o primeiro nó da lista 94 | 95 | **Retorno**: 96 | - `1` se a lista estiver vazia 97 | - `0` se a lista contiver elementos 98 | 99 | **Funcionamento**: Verifica se o ponteiro da lista é NULL. 100 | 101 | **Complexidade**: O(1) 102 | 103 | --- 104 | 105 | #### `Celula * criarCelula()` 106 | **Descrição**: Aloca dinamicamente memória para um novo nó. 107 | 108 | **Retorno**: 109 | - Ponteiro para a nova célula alocada 110 | - NULL se não conseguir alocar memória 111 | 112 | **Funcionamento**: Usa `malloc()` para alocar memória do tamanho de uma Celula. 113 | 114 | **Complexidade**: O(1) 115 | 116 | --- 117 | 118 | #### `int inserir(Celula **lista, Jogador elemento)` 119 | **Descrição**: Insere um elemento na posição correta para manter a ordenação. 120 | 121 | **Parâmetros**: 122 | - `lista`: Ponteiro duplo para o primeiro nó da lista 123 | - `elemento`: Estrutura Jogador a ser inserida 124 | 125 | **Retorno**: 126 | - `1` se a inserção foi bem-sucedida 127 | - `0` se houve erro de alocação de memória 128 | 129 | **Funcionamento**: 130 | 1. Cria uma nova célula 131 | 2. Percorre a lista até encontrar a posição correta (comparando nomes) 132 | 3. Insere o elemento mantendo a ordenação alfabética 133 | 4. Ajusta os ponteiros para incluir o novo elemento 134 | 135 | **Complexidade**: O(n) para encontrar a posição correta 136 | 137 | **Ordenação**: Os elementos são inseridos em ordem alfabética crescente pelo nome. 138 | 139 | --- 140 | 141 | #### `Jogador removerInicio(Celula **lista)` 142 | **Descrição**: Remove o primeiro elemento da lista (menor alfabeticamente). 143 | 144 | **Parâmetros**: 145 | - `lista`: Ponteiro duplo para o primeiro nó da lista 146 | 147 | **Retorno**: 148 | - Estrutura Jogador removida 149 | - Jogador com numCamisa = -1 se a lista estiver vazia 150 | 151 | **Funcionamento**: 152 | 1. Verifica se a lista não está vazia 153 | 2. Salva os dados do primeiro elemento 154 | 3. Atualiza o ponteiro da lista para o segundo elemento 155 | 4. Libera a memória do primeiro elemento 156 | 5. Retorna os dados salvos 157 | 158 | **Complexidade**: O(1) 159 | 160 | --- 161 | 162 | #### `Jogador removerFim(Celula **lista)` 163 | **Descrição**: Remove o último elemento da lista (maior alfabeticamente). 164 | 165 | **Parâmetros**: 166 | - `lista`: Ponteiro duplo para o primeiro nó da lista 167 | 168 | **Retorno**: 169 | - Estrutura Jogador removida 170 | - Jogador com numCamisa = -1 se a lista estiver vazia 171 | 172 | **Funcionamento**: 173 | 1. Verifica se a lista não está vazia 174 | 2. Se há apenas um elemento, remove do início 175 | 3. Percorre até o penúltimo elemento 176 | 4. Salva os dados do último elemento 177 | 5. Faz o penúltimo apontar para NULL 178 | 6. Libera a memória do último elemento 179 | 180 | **Complexidade**: O(n) para encontrar o final da lista 181 | 182 | --- 183 | 184 | #### `Celula * pesquisar(Celula **lista, Jogador pesquisado)` 185 | **Descrição**: Busca um elemento na lista pelo nome do jogador. 186 | 187 | **Parâmetros**: 188 | - `lista`: Ponteiro duplo para o primeiro nó da lista 189 | - `pesquisado`: Estrutura Jogador com o nome a ser encontrado 190 | 191 | **Retorno**: 192 | - Ponteiro para a célula encontrada 193 | - NULL se não encontrou ou lista vazia 194 | 195 | **Funcionamento**: 196 | 1. Verifica se a lista não está vazia 197 | 2. Percorre a lista comparando nomes 198 | 3. Pode otimizar parando quando encontra nome maior (lista ordenada) 199 | 4. Retorna ponteiro para a primeira ocorrência encontrada 200 | 201 | **Complexidade**: O(n) no pior caso, mas pode terminar antes devido à ordenação 202 | 203 | --- 204 | 205 | #### `Jogador removerElemento(Celula **lista, Jogador elemento)` 206 | **Descrição**: Remove um elemento específico da lista baseado no nome. 207 | 208 | **Parâmetros**: 209 | - `lista`: Ponteiro duplo para o primeiro nó da lista 210 | - `elemento`: Estrutura Jogador com o nome a ser removido 211 | 212 | **Retorno**: 213 | - Estrutura Jogador removida 214 | - Jogador com numCamisa = -1 se não encontrou 215 | 216 | **Funcionamento**: 217 | 1. Usa a função pesquisar para localizar o elemento 218 | 2. Se é o primeiro elemento, usa removerInicio() 219 | 3. Caso contrário, encontra o elemento anterior 220 | 4. Ajusta os ponteiros para "pular" o elemento removido 221 | 5. Libera a memória do elemento removido 222 | 223 | **Complexidade**: O(n) para encontrar o elemento 224 | 225 | --- 226 | 227 | #### `Jogador criarElemento(int numCamisa, char nome[])` 228 | **Descrição**: Função auxiliar para criar uma estrutura Jogador. 229 | 230 | **Parâmetros**: 231 | - `numCamisa`: Número da camisa do jogador 232 | - `nome`: Nome do jogador 233 | 234 | **Retorno**: Estrutura Jogador preenchida 235 | 236 | **Funcionamento**: Cria e preenche uma estrutura Jogador com os dados fornecidos. 237 | 238 | **Complexidade**: O(1) 239 | 240 | --- 241 | 242 | #### `int compararElemento(Jogador j1, Jogador j2)` 243 | **Descrição**: Compara dois jogadores pelos nomes para ordenação. 244 | 245 | **Parâmetros**: 246 | - `j1`, `j2`: Estruturas Jogador a serem comparadas 247 | 248 | **Retorno**: 249 | - 0 se os nomes são iguais 250 | - Valor negativo se j1 < j2 (alfabeticamente) 251 | - Valor positivo se j1 > j2 (alfabeticamente) 252 | 253 | **Funcionamento**: Usa `strcmp()` para comparar os nomes dos jogadores. 254 | 255 | **Complexidade**: O(m) onde m é o tamanho da string 256 | 257 | ## Funções de Interface 258 | 259 | ### `void exibirMenu(Celula **lista, int *opcao)` 260 | Exibe o menu principal com opções específicas para lista encadeada ordenada. 261 | 262 | ### `void menuExibirElementos(Celula **lista)` 263 | Percorre e exibe todos os elementos da lista em formato de tabela. Os elementos aparecem em ordem alfabética. 264 | 265 | ### `void menuInserir(Celula **lista)` 266 | Interface para inserção de elemento na posição ordenada correta automaticamente. 267 | 268 | ### `void menuRemoverInicio(Celula **lista)` 269 | Interface para remoção do primeiro elemento (menor nome alfabeticamente). 270 | 271 | ### `void menuRemoverFim(Celula **lista)` 272 | Interface para remoção do último elemento (maior nome alfabeticamente). 273 | 274 | ### `void menuPesquisarElemento(Celula **lista)` 275 | Interface para busca de elemento por nome, aproveitando a ordenação para otimizar. 276 | 277 | ### `void menuRemoverElemento(Celula **lista)` 278 | Interface para remoção de elemento específico por nome. 279 | 280 | ## Algoritmo de Inserção Ordenada 281 | 282 | A função `inserir()` implementa o seguinte algoritmo: 283 | 284 | 1. **Criação do Nó**: Aloca memória para novo elemento 285 | 2. **Busca da Posição**: Percorre lista até encontrar primeiro elemento maior 286 | 3. **Inserção**: 287 | - Se deve ser o primeiro: atualiza ponteiro da lista 288 | - Caso contrário: ajusta ponteiros do anterior e atual 289 | 4. **Manutenção da Ordem**: Garante que a sequência continue ordenada 290 | 291 | ## Compilação e Execução 292 | 293 | ```bash 294 | gcc -o programa main.c 295 | ./programa 296 | ``` 297 | 298 | ## Comparação com Lista Encadeada Simples 299 | 300 | | Aspecto | Lista Simples | Lista Ordenada | 301 | |---------|---------------|----------------| 302 | | Inserção | O(1) no início | O(n) posição ordenada | 303 | | Busca | O(n) linear | O(n) mas pode parar antes | 304 | | Ordenação | Requer algoritmo extra | Sempre ordenada | 305 | | Flexibilidade | Total controle posição | Posição determinada pela ordem | 306 | | Uso de Memória | Igual | Igual | 307 | 308 | ## Vantagens da Ordenação Automática 309 | 310 | 1. **Sem Necessidade de Ordenação**: Dados sempre prontos para uso 311 | 2. **Busca Otimizada**: Pode parar quando encontra elemento maior 312 | 3. **Apresentação**: Sempre exibe dados em ordem lógica 313 | 4. **Algoritmos**: Facilita implementação de operações como merge 314 | 315 | ## Considerações de Implementação 316 | 317 | 1. **Critério de Ordenação**: Implementado através da comparação de nomes 318 | 2. **Estabilidade**: Mantém ordem relativa de elementos iguais 319 | 3. **Performance**: Trade-off entre inserção mais lenta e dados sempre ordenados 320 | 4. **Robustez**: Todas as operações mantêm a invariante de ordenação 321 | 5. **Reutilização**: Código base similar à lista encadeada simples 322 | -------------------------------------------------------------------------------- /listas/duplamente-encadeada/README.md: -------------------------------------------------------------------------------- 1 | # Lista Duplamente Encadeada em C 2 | 3 | ## Conceito 4 | 5 | Uma **Lista Duplamente Encadeada** é uma estrutura de dados linear e dinâmica onde cada elemento (nó) contém dados e dois ponteiros: um para o próximo elemento e outro para o elemento anterior na sequência. Esta estrutura permite navegação bidirecional e operações de inserção/remoção mais eficientes em qualquer posição da lista. 6 | 7 | ### Características Principais 8 | 9 | - **Navegação Bidirecional**: Possibilita percorrer a lista em ambas as direções 10 | - **Tamanho Dinâmico**: Cresce e diminui conforme necessário durante a execução 11 | - **Dois Ponteiros por Nó**: Cada célula mantém referências para o próximo e anterior 12 | - **Alocação Dinâmica**: Usa `malloc()` e `free()` para gerenciar memória 13 | 14 | ### Vantagens 15 | 16 | - **Flexibilidade de Navegação**: Permite percorrer a lista em qualquer direção 17 | - **Eficiência de Remoção**: Não precisa percorrer para encontrar o elemento anterior 18 | - **Inserção Eficiente**: Operações O(1) quando se tem o ponteiro do nó 19 | - **Uso Eficiente de Memória**: Aloca apenas o necessário 20 | - **Operações Simétricas**: Inserção/remoção no início e fim com complexidade similar 21 | 22 | ### Desvantagens 23 | 24 | - **Overhead de Memória**: Cada nó precisa armazenar dois ponteiros adicionais 25 | - **Complexidade de Implementação**: Mais complexa que lista simples devido às ligações duplas 26 | - **Fragmentação de Memória**: Nós podem estar espalhados pela memória 27 | - **Manutenção de Integridade**: Requer cuidado para manter ligações corretas 28 | 29 | ## Estrutura de Dados 30 | 31 | ### Definição do Elemento (Jogador) 32 | ```c 33 | typedef struct { 34 | int numCamisa; 35 | char nome[50]; 36 | } Jogador; 37 | ``` 38 | 39 | ### Definição da Célula (Nó) 40 | ```c 41 | typedef struct celula { 42 | struct celula* ante; 43 | Jogador elemento; 44 | struct celula* prox; 45 | } Celula; 46 | ``` 47 | 48 | - `ante`: Ponteiro para o nó anterior (NULL se for o primeiro) 49 | - `elemento`: Dados armazenados no nó 50 | - `prox`: Ponteiro para o próximo nó (NULL se for o último) 51 | 52 | ## Funções Implementadas 53 | 54 | ### Funções Auxiliares 55 | 56 | #### `void limparBuffer()` 57 | Remove caracteres residuais do buffer de entrada, evitando problemas na leitura de dados. 58 | 59 | #### `void removerQuebraLinha(char *str)` 60 | Remove o caractere de quebra de linha ('\n') de uma string, normalmente após usar `fgets()`. 61 | 62 | #### `void limparTela()` 63 | Limpa a tela do terminal de forma compatível com Windows e sistemas Unix. 64 | 65 | #### `void pausar()` 66 | Pausa a execução e aguarda o usuário pressionar ENTER para continuar. 67 | 68 | #### `int contarElementos(Celula **lista)` 69 | Percorre a lista e retorna o número total de elementos armazenados. 70 | 71 | #### `void exibirCabecalho(Celula **lista)` 72 | Exibe o cabeçalho do sistema com informações sobre o status atual da lista: 73 | - Status: VAZIA ou COM DADOS 74 | - Contador de jogadores 75 | 76 | ### Funções de Manipulação da Lista 77 | 78 | #### `void inicializarLista(Celula **lista)` 79 | **Descrição**: Inicializa uma lista duplamente encadeada vazia. 80 | 81 | **Parâmetros**: 82 | - `lista`: Ponteiro duplo para o primeiro nó da lista 83 | 84 | **Funcionamento**: Define o ponteiro da lista como NULL, indicando lista vazia. 85 | 86 | **Complexidade**: O(1) 87 | 88 | --- 89 | 90 | #### `int listaVazia(Celula **lista)` 91 | **Descrição**: Verifica se a lista está vazia. 92 | 93 | **Parâmetros**: 94 | - `lista`: Ponteiro duplo para o primeiro nó da lista 95 | 96 | **Retorno**: 97 | - `1` se a lista estiver vazia 98 | - `0` se a lista contiver elementos 99 | 100 | **Funcionamento**: Verifica se o ponteiro da lista é NULL. 101 | 102 | **Complexidade**: O(1) 103 | 104 | --- 105 | 106 | #### `Celula * criarCelula()` 107 | **Descrição**: Aloca dinamicamente memória para um novo nó. 108 | 109 | **Retorno**: 110 | - Ponteiro para a nova célula alocada 111 | - NULL se não conseguir alocar memória 112 | 113 | **Funcionamento**: Usa `malloc()` para alocar memória do tamanho de uma Celula. 114 | 115 | **Complexidade**: O(1) 116 | 117 | --- 118 | 119 | #### `int inserirNoFim(Celula **lista, Jogador novo)` 120 | **Descrição**: Insere um novo elemento no final da lista duplamente encadeada. 121 | 122 | **Parâmetros**: 123 | - `lista`: Ponteiro duplo para o primeiro nó da lista 124 | - `novo`: Estrutura Jogador a ser inserida 125 | 126 | **Retorno**: 127 | - `1` se a inserção foi bem-sucedida 128 | - `0` se houve erro de alocação de memória 129 | 130 | **Funcionamento**: 131 | 1. Cria uma nova célula e verifica alocação 132 | 2. Inicializa os campos da nova célula 133 | 3. Se a lista estiver vazia, faz o ponteiro principal apontar para ela 134 | 4. Caso contrário, percorre até o último nó 135 | 5. Faz as ligações duplas: último->prox = nova e nova->ante = último 136 | 137 | **Complexidade**: O(n) para encontrar o final da lista 138 | 139 | --- 140 | 141 | #### `int inserirNoInicio(Celula **lista, Jogador novo)` 142 | **Descrição**: Insere um novo elemento no início da lista duplamente encadeada. 143 | 144 | **Parâmetros**: 145 | - `lista`: Ponteiro duplo para o primeiro nó da lista 146 | - `novo`: Estrutura Jogador a ser inserida 147 | 148 | **Retorno**: 149 | - `1` se a inserção foi bem-sucedida 150 | - `0` se houve erro de alocação de memória 151 | 152 | **Funcionamento**: 153 | 1. Cria uma nova célula 154 | 2. Se a lista estiver vazia, reutiliza inserirNoFim() 155 | 3. Caso contrário, configura os ponteiros: 156 | - nova->prox = primeiro elemento atual 157 | - primeira célula atual->ante = nova 158 | - nova->ante = NULL 159 | 4. Atualiza o ponteiro principal para a nova célula 160 | 161 | **Complexidade**: O(1) 162 | 163 | --- 164 | 165 | #### `Jogador removerNoInicio(Celula **lista)` 166 | **Descrição**: Remove o primeiro elemento da lista duplamente encadeada. 167 | 168 | **Parâmetros**: 169 | - `lista`: Ponteiro duplo para o primeiro nó da lista 170 | 171 | **Retorno**: 172 | - Estrutura Jogador removida 173 | - Jogador com numCamisa = -1 se a lista estiver vazia 174 | 175 | **Funcionamento**: 176 | 1. Verifica se a lista não está vazia 177 | 2. Guarda o endereço da célula a ser removida 178 | 3. Faz uma cópia do elemento da célula removida 179 | 4. Atualiza o ponteiro principal para o segundo elemento 180 | 5. Se ainda há elementos, define o campo ante do novo primeiro como NULL 181 | 6. Libera a memória da célula removida 182 | 183 | **Complexidade**: O(1) 184 | 185 | --- 186 | 187 | #### `Jogador removerNoFim(Celula **lista)` 188 | **Descrição**: Remove o último elemento da lista duplamente encadeada. 189 | 190 | **Parâmetros**: 191 | - `lista`: Ponteiro duplo para o primeiro nó da lista 192 | 193 | **Retorno**: 194 | - Estrutura Jogador removida 195 | - Jogador com numCamisa = -1 se a lista estiver vazia 196 | 197 | **Funcionamento**: 198 | 1. Verifica se a lista não está vazia 199 | 2. Percorre até encontrar a última célula 200 | 3. Se há apenas um elemento, reutiliza removerNoInicio() 201 | 4. Caso contrário, ajusta o ponteiro prox da célula anterior para NULL 202 | 5. Libera a memória da última célula 203 | 204 | **Complexidade**: O(n) para encontrar o final da lista 205 | 206 | --- 207 | 208 | #### `Celula * pesquisar(Celula **lista, Jogador pesquisado)` 209 | **Descrição**: Busca um elemento na lista pelo nome do jogador. 210 | 211 | **Parâmetros**: 212 | - `lista`: Ponteiro duplo para o primeiro nó da lista 213 | - `pesquisado`: Estrutura Jogador com o nome a ser buscado 214 | 215 | **Retorno**: 216 | - Ponteiro para a célula que contém o elemento 217 | - NULL se não encontrar ou lista vazia 218 | 219 | **Funcionamento**: 220 | 1. Verifica se a lista não está vazia 221 | 2. Percorre a lista comparando nomes com strcmp() 222 | 3. Retorna o ponteiro da célula se encontrar 223 | 4. Retorna NULL se percorrer toda a lista sem encontrar 224 | 225 | **Complexidade**: O(n) no pior caso 226 | 227 | --- 228 | 229 | #### `Jogador removerElemento(Celula **lista, Jogador elemento)` 230 | **Descrição**: Remove um elemento específico da lista baseado no nome. 231 | 232 | **Parâmetros**: 233 | - `lista`: Ponteiro duplo para o primeiro nó da lista 234 | - `elemento`: Estrutura Jogador com o nome a ser removido 235 | 236 | **Retorno**: 237 | - Estrutura Jogador removida 238 | - Jogador com numCamisa = -1 se não encontrou 239 | 240 | **Funcionamento**: 241 | 1. Usa a função pesquisar para localizar o elemento 242 | 2. Se for o primeiro elemento, usa removerNoInicio() 243 | 3. Se for o último elemento, usa removerNoFim() 244 | 4. Caso contrário, ajusta as ligações duplas: 245 | - anterior->prox = próximo 246 | - próximo->ante = anterior 247 | 5. Libera a memória do elemento removido 248 | 249 | **Complexidade**: O(n) para encontrar o elemento 250 | 251 | --- 252 | 253 | #### `Jogador criarElemento(int numCamisa, char nome[])` 254 | **Descrição**: Função auxiliar para criar uma estrutura Jogador. 255 | 256 | **Parâmetros**: 257 | - `numCamisa`: Número da camisa do jogador 258 | - `nome`: Nome do jogador 259 | 260 | **Retorno**: Estrutura Jogador preenchida 261 | 262 | **Funcionamento**: Cria e preenche uma estrutura Jogador com os dados fornecidos. 263 | 264 | **Complexidade**: O(1) 265 | 266 | --- 267 | 268 | #### `int compararElemento(Jogador j1, Jogador j2)` 269 | **Descrição**: Compara dois jogadores pelos nomes. 270 | 271 | **Parâmetros**: 272 | - `j1`, `j2`: Estruturas Jogador a serem comparadas 273 | 274 | **Retorno**: 275 | - 0 se os nomes são iguais 276 | - Valor negativo se j1 < j2 (alfabeticamente) 277 | - Valor positivo se j1 > j2 (alfabeticamente) 278 | 279 | **Funcionamento**: Usa `strcmp()` para comparar os nomes dos jogadores. 280 | 281 | **Complexidade**: O(m) onde m é o tamanho da string 282 | 283 | ## Funções de Interface 284 | 285 | ### `void exibirMenu(Celula **lista, int *opcao)` 286 | Exibe o menu principal com opções para manipular a lista duplamente encadeada. 287 | 288 | ### `void menuExibirElementos(Celula **lista)` 289 | Interface para exibir todos os elementos da lista em formato tabular. 290 | 291 | ### `void menuInserirInicio(Celula **lista)` 292 | Interface para inserir um novo jogador no início da lista. 293 | 294 | ### `void menuInserirFim(Celula **lista)` 295 | Interface para inserir um novo jogador no final da lista. 296 | 297 | ### `void menuRemoverInicio(Celula **lista)` 298 | Interface para remover o primeiro jogador da lista. 299 | 300 | ### `void menuRemoverFim(Celula **lista)` 301 | Interface para remover o último jogador da lista. 302 | 303 | ### `void menuPesquisarElemento(Celula **lista)` 304 | Interface para pesquisar um jogador pelo nome. 305 | 306 | ### `void menuRemoverElemento(Celula **lista)` 307 | Interface para remover um jogador específico pelo nome. 308 | 309 | ## Complexidade das Operações 310 | 311 | | Operação | Complexidade | Observações | 312 | |----------|--------------|-------------| 313 | | Inserir no início | O(1) | Operação constante | 314 | | Inserir no fim | O(n) | Precisa percorrer até o final | 315 | | Remover do início | O(1) | Operação constante | 316 | | Remover do fim | O(n) | Precisa percorrer até o final | 317 | | Buscar elemento | O(n) | Busca sequencial | 318 | | Remover elemento específico | O(n) | Inclui tempo de busca | 319 | 320 | ## Vantagens da Lista Duplamente Encadeada 321 | 322 | 1. **Navegação Bidirecional**: Permite percorrer em ambas as direções 323 | 2. **Remoção Eficiente**: Não precisa buscar o elemento anterior 324 | 3. **Flexibilidade**: Facilita implementação de operações simétricas 325 | 4. **Integridade**: Ligações duplas aumentam a robustez da estrutura 326 | 327 | ## Como Usar 328 | 329 | 1. **Compilar**: `gcc -o programa main.c` 330 | 2. **Executar**: `./programa` 331 | 3. **Navegar**: Use o menu interativo para testar as funcionalidades 332 | 333 | O programa oferece uma interface completa para gerenciamento de jogadores usando lista duplamente encadeada, com operações de inserção, remoção, busca e visualização. -------------------------------------------------------------------------------- /pilhas/estatica/README.md: -------------------------------------------------------------------------------- 1 | # Pilha Estática em C 2 | 3 | ## 📚 Conceito Teórico 4 | 5 | Uma **Pilha (Stack)** é uma estrutura de dados linear que segue o princípio **LIFO (Last In, First Out)** - o último elemento inserido é o primeiro a ser removido. Imagine uma pilha de pratos: você sempre adiciona e remove pratos do topo da pilha. 6 | 7 | A **Pilha Estática** implementa este conceito utilizando um array de tamanho fixo, onde o "topo" da pilha é controlado por um índice que aponta para o último elemento inserido. 8 | 9 | ### 🔍 Características Principais 10 | 11 | - **LIFO (Last In, First Out)**: Último a entrar, primeiro a sair 12 | - **Tamanho Fixo**: Capacidade máxima definida em tempo de compilação 13 | - **Acesso Restrito**: Apenas o elemento do topo pode ser acessado diretamente 14 | - **Operações Fundamentais**: Push (empilhar) e Pop (desempilhar) 15 | - **Memória Contígua**: Elementos armazenados em posições consecutivas 16 | 17 | ### ⚡ Vantagens 18 | 19 | - **Simplicidade**: Implementação direta e fácil compreensão 20 | - **Eficiência**: Operações de inserção e remoção em O(1) 21 | - **Controle de Memória**: Não há necessidade de alocação dinâmica 22 | - **Previsibilidade**: Comportamento determinístico e sem surpresas 23 | - **Cache Friendly**: Elementos contíguos melhoram performance 24 | 25 | ### ⚠️ Desvantagens 26 | 27 | - **Tamanho Limitado**: Não pode exceder a capacidade pré-definida 28 | - **Overflow**: Erro ao tentar empilhar em pilha cheia 29 | - **Underflow**: Erro ao tentar desempilhar de pilha vazia 30 | - **Desperdício de Memória**: Pode reservar mais espaço que necessário 31 | - **Acesso Limitado**: Apenas o topo é acessível 32 | 33 | ### 🌍 Aplicações Práticas 34 | 35 | #### Sistemas de Computação 36 | - **Chamadas de Função**: Stack de execução de funções 37 | - **Recursão**: Controle de chamadas recursivas 38 | - **Compiladores**: Análise sintática e semântica 39 | - **Máquinas Virtuais**: Pilha de operandos (JVM, CLR) 40 | 41 | #### Algoritmos 42 | - **Avaliação de Expressões**: Conversão infix para postfix 43 | - **Balanceamento de Parênteses**: Verificação de delimitadores 44 | - **Backtracking**: Labirintos, N-rainhas, Sudoku 45 | - **Algoritmos de Parsing**: Análise de linguagens 46 | 47 | #### Estruturas de Dados 48 | - **Implementação de Recursão Iterativa**: Simulação de pilha de chamadas 49 | - **Desfazer/Refazer (Undo/Redo)**: Editores de texto, navegadores 50 | - **Navegação**: Histórico de páginas web, pastas 51 | - **Inversão de Dados**: Strings, arrays, listas 52 | 53 | ## 🏗️ Estrutura de Dados 54 | 55 | ### Definição do Elemento (Produto) 56 | ```c 57 | typedef struct { 58 | int codigo; 59 | char nome[50]; 60 | float preco; 61 | } Produto; 62 | ``` 63 | 64 | ### Definição da Pilha Estática 65 | ```c 66 | typedef struct { 67 | Produto elementos[MAX_ELEMENTOS]; 68 | int topo; 69 | } PilhaEstatica; 70 | ``` 71 | 72 | **Campos da Estrutura:** 73 | - `elementos[]`: Array que armazena os dados da pilha 74 | - `topo`: Índice do elemento no topo da pilha (-1 quando vazia) 75 | 76 | ## 🔧 Funções Implementadas 77 | 78 | ### Funções Auxiliares 79 | 80 | #### `void limparBuffer()` 81 | **Descrição**: Remove caracteres residuais do buffer de entrada. 82 | **Uso**: Evita problemas na leitura sequencial de dados. 83 | 84 | #### `void removerQuebraLinha(char *str)` 85 | **Descrição**: Remove o caractere '\n' de strings lidas com `fgets()`. 86 | **Parâmetros**: `str` - string a ser processada 87 | 88 | #### `void limparTela()` 89 | **Descrição**: Limpa a tela do terminal de forma multiplataforma. 90 | **Compatibilidade**: Windows (`cls`) e Unix/Linux (`clear`) 91 | 92 | #### `void pausar()` 93 | **Descrição**: Pausa a execução aguardando input do usuário. 94 | **Uso**: Permite visualizar resultados antes de continuar 95 | 96 | #### `void exibirCabecalho(PilhaEstatica *pilha)` 97 | **Descrição**: Exibe interface visual com status da pilha. 98 | **Informações**: Status (VAZIA/PARCIAL/CHEIA) e contador de elementos 99 | 100 | ### Funções de Manipulação da Pilha 101 | 102 | #### `void inicializarPilha(PilhaEstatica *pilha)` 103 | **Descrição**: Inicializa uma pilha estática vazia. 104 | 105 | **Parâmetros**: 106 | - `pilha`: Ponteiro para a estrutura da pilha 107 | 108 | **Funcionamento**: Define `topo = -1`, indicando pilha vazia. 109 | 110 | **Complexidade**: O(1) 111 | 112 | **Exemplo**: 113 | ```c 114 | PilhaEstatica pilha; 115 | inicializarPilha(&pilha); 116 | // pilha.topo = -1 (vazia) 117 | ``` 118 | 119 | --- 120 | 121 | #### `int pilhaVazia(PilhaEstatica *pilha)` 122 | **Descrição**: Verifica se a pilha está vazia. 123 | 124 | **Parâmetros**: 125 | - `pilha`: Ponteiro para a estrutura da pilha 126 | 127 | **Retorno**: 128 | - `1` se a pilha estiver vazia (topo == -1) 129 | - `0` se contém elementos 130 | 131 | **Funcionamento**: Compara o campo `topo` com -1. 132 | 133 | **Complexidade**: O(1) 134 | 135 | **Exemplo**: 136 | ```c 137 | if (pilhaVazia(&pilha)) { 138 | printf("Pilha vazia!\n"); 139 | } 140 | ``` 141 | 142 | --- 143 | 144 | #### `int pilhaCheia(PilhaEstatica *pilha)` 145 | **Descrição**: Verifica se a pilha atingiu capacidade máxima. 146 | 147 | **Parâmetros**: 148 | - `pilha`: Ponteiro para a estrutura da pilha 149 | 150 | **Retorno**: 151 | - `1` se a pilha estiver cheia (topo == MAX_ELEMENTOS - 1) 152 | - `0` se ainda há espaço disponível 153 | 154 | **Funcionamento**: Compara o campo `topo` com (MAX_ELEMENTOS - 1). 155 | 156 | **Complexidade**: O(1) 157 | 158 | **Exemplo**: 159 | ```c 160 | if (pilhaCheia(&pilha)) { 161 | printf("Pilha cheia! Overflow!\n"); 162 | } 163 | ``` 164 | 165 | --- 166 | 167 | #### `int push(PilhaEstatica *pilha, Produto elemento)` 168 | **Descrição**: Empilha (insere) um elemento no topo da pilha. 169 | 170 | **Parâmetros**: 171 | - `pilha`: Ponteiro para a estrutura da pilha 172 | - `elemento`: Produto a ser empilhado 173 | 174 | **Retorno**: 175 | - `1` se a operação foi bem-sucedida 176 | - `0` se a pilha estiver cheia (overflow) 177 | 178 | **Funcionamento**: 179 | 1. Verifica se a pilha não está cheia 180 | 2. Incrementa o índice `topo` 181 | 3. Insere o elemento na posição `topo` 182 | 183 | **Complexidade**: O(1) 184 | 185 | **Exemplo**: 186 | ```c 187 | Produto p = {1, "Notebook", 2500.00}; 188 | if (push(&pilha, p)) { 189 | printf("Produto empilhado com sucesso!\n"); 190 | } 191 | ``` 192 | 193 | --- 194 | 195 | #### `Produto pop(PilhaEstatica *pilha)` 196 | **Descrição**: Desempilha (remove) o elemento do topo da pilha. 197 | 198 | **Parâmetros**: 199 | - `pilha`: Ponteiro para a estrutura da pilha 200 | 201 | **Retorno**: 202 | - Produto removido do topo 203 | - Produto com código -1 se pilha vazia (underflow) 204 | 205 | **Funcionamento**: 206 | 1. Verifica se a pilha não está vazia 207 | 2. Salva o elemento do topo 208 | 3. Decrementa o índice `topo` 209 | 4. Retorna o elemento salvo 210 | 211 | **Complexidade**: O(1) 212 | 213 | **Exemplo**: 214 | ```c 215 | Produto removido = pop(&pilha); 216 | if (removido.codigo != -1) { 217 | printf("Produto removido: %s\n", removido.nome); 218 | } 219 | ``` 220 | 221 | --- 222 | 223 | #### `Produto top(PilhaEstatica *pilha)` 224 | **Descrição**: Consulta o elemento do topo sem removê-lo. 225 | 226 | **Parâmetros**: 227 | - `pilha`: Ponteiro para a estrutura da pilha 228 | 229 | **Retorno**: 230 | - Produto do topo da pilha 231 | - Produto com código -1 se pilha vazia 232 | 233 | **Funcionamento**: 234 | 1. Verifica se a pilha não está vazia 235 | 2. Retorna o elemento na posição `topo` 236 | 3. Não modifica a estrutura da pilha 237 | 238 | **Complexidade**: O(1) 239 | 240 | **Exemplo**: 241 | ```c 242 | Produto topo = top(&pilha); 243 | if (topo.codigo != -1) { 244 | printf("Topo da pilha: %s\n", topo.nome); 245 | } 246 | ``` 247 | 248 | --- 249 | 250 | #### `int tamanho(PilhaEstatica *pilha)` 251 | **Descrição**: Retorna o número de elementos na pilha. 252 | 253 | **Parâmetros**: 254 | - `pilha`: Ponteiro para a estrutura da pilha 255 | 256 | **Retorno**: 257 | - Quantidade de elementos (topo + 1) 258 | - 0 se a pilha estiver vazia 259 | 260 | **Funcionamento**: Calcula `topo + 1` para obter o total de elementos. 261 | 262 | **Complexidade**: O(1) 263 | 264 | **Exemplo**: 265 | ```c 266 | int total = tamanho(&pilha); 267 | printf("A pilha contém %d elementos\n", total); 268 | ``` 269 | 270 | --- 271 | 272 | #### `void exibirPilha(PilhaEstatica *pilha)` 273 | **Descrição**: Exibe todos os elementos da pilha do topo para a base. 274 | 275 | **Parâmetros**: 276 | - `pilha`: Ponteiro para a estrutura da pilha 277 | 278 | **Funcionamento**: 279 | 1. Verifica se a pilha não está vazia 280 | 2. Percorre do topo (índice maior) até a base (índice 0) 281 | 3. Exibe cada elemento com formatação visual 282 | 283 | **Complexidade**: O(n) onde n é o número de elementos 284 | 285 | **Exemplo de Saída**: 286 | ``` 287 | PILHA (Topo → Base): 288 | [2] Produto: Mouse - R$ 45.00 289 | [1] Produto: Teclado - R$ 120.00 290 | [0] Produto: Monitor - R$ 800.00 291 | ``` 292 | 293 | ## 📊 Análise de Complexidade 294 | 295 | | Operação | Complexidade | Justificativa | 296 | |----------|--------------|---------------| 297 | | Inicializar | O(1) | Apenas define topo = -1 | 298 | | Verificar Vazia | O(1) | Comparação simples | 299 | | Verificar Cheia | O(1) | Comparação simples | 300 | | Push (Empilhar) | O(1) | Acesso direto por índice | 301 | | Pop (Desempilhar) | O(1) | Acesso direto por índice | 302 | | Top (Consultar Topo) | O(1) | Acesso direto por índice | 303 | | Tamanho | O(1) | Cálculo aritmético simples | 304 | | Exibir Pilha | O(n) | Percorre todos os elementos | 305 | 306 | ## 🔬 Estados da Pilha 307 | 308 | ### Estado Inicial (Vazia) 309 | ``` 310 | topo = -1 311 | elementos = [?, ?, ?, ...] 312 | Status: VAZIA 313 | ``` 314 | 315 | ### Após push("Monitor") 316 | ``` 317 | topo = 0 318 | elementos = [Monitor, ?, ?, ...] 319 | Status: PARCIAL 320 | ``` 321 | 322 | ### Após push("Teclado") 323 | ``` 324 | topo = 1 325 | elementos = [Monitor, Teclado, ?, ...] 326 | Status: PARCIAL 327 | ``` 328 | 329 | ### Pilha Cheia (MAX_ELEMENTOS = 3) 330 | ``` 331 | topo = 2 332 | elementos = [Monitor, Teclado, Mouse] 333 | Status: CHEIA 334 | ``` 335 | 336 | ### Após pop() 337 | ``` 338 | topo = 1 339 | elementos = [Monitor, Teclado, Mouse] // Mouse permanece fisicamente 340 | Status: PARCIAL 341 | // Retorna: Mouse 342 | ``` 343 | 344 | ## 🚨 Tratamento de Erros 345 | 346 | ### Stack Overflow 347 | - **Causa**: Tentar empilhar em pilha cheia 348 | - **Prevenção**: Verificar `pilhaCheia()` antes do `push()` 349 | - **Tratamento**: Retornar código de erro e exibir mensagem 350 | 351 | ### Stack Underflow 352 | - **Causa**: Tentar desempilhar de pilha vazia 353 | - **Prevenção**: Verificar `pilhaVazia()` antes do `pop()` 354 | - **Tratamento**: Retornar elemento inválido (código -1) 355 | 356 | ## 🎯 Menu Interativo 357 | 358 | O sistema oferece interface amigável com as seguintes opções: 359 | 360 | 1. **Exibir Pilha**: Mostra todos os elementos do topo à base 361 | 2. **Empilhar (Push)**: Adiciona novo produto ao topo 362 | 3. **Desempilhar (Pop)**: Remove produto do topo 363 | 4. **Consultar Topo**: Visualiza elemento do topo sem remover 364 | 5. **Verificar Status**: Mostra se pilha está vazia, cheia ou parcial 365 | 6. **Sair**: Encerra o programa 366 | 367 | ## 📚 Conceitos Relacionados 368 | 369 | ### Pilha vs Fila 370 | - **Pilha**: LIFO - útil para desfazer operações, recursão 371 | - **Fila**: FIFO - útil para processamento sequencial, scheduling 372 | 373 | ### Pilha vs Lista 374 | - **Pilha**: Acesso restrito ao topo, operações específicas 375 | - **Lista**: Acesso a qualquer posição, operações genéricas 376 | 377 | ### Estática vs Dinâmica 378 | - **Estática**: Array fixo, eficiente, limitada em tamanho 379 | - **Dinâmica**: Ponteiros, flexível, overhead de memória 380 | 381 | ## 🔗 Próximos Passos 382 | 383 | Após dominar a Pilha Estática, explore: 384 | 1. **Pilha Dinâmica**: Implementação com ponteiros 385 | 2. **Fila Estática**: Princípio FIFO com array 386 | 3. **Aplicações Avançadas**: Calculadora postfix, parsing de expressões 387 | 4. **Otimizações**: Pilha com template, pilha thread-safe -------------------------------------------------------------------------------- /filas/dinamica/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct 6 | { 7 | int prioridade; 8 | char tarefa[100]; 9 | } Ticket; 10 | 11 | typedef struct NoFila 12 | { 13 | Ticket dados; 14 | struct NoFila *proximo; 15 | } NoFila; 16 | 17 | void limparBuffer() 18 | { 19 | int c; 20 | while ((c = getchar()) != '\n' && c != EOF) 21 | ; 22 | } 23 | 24 | void removerQuebraLinha(char *str) { 25 | str[strcspn(str, "\n")] = 0; 26 | } 27 | 28 | // FUNÇÕES DA FILA DINÂMICA 29 | void inicializarFila(NoFila **fila) 30 | { 31 | *fila = NULL; 32 | } 33 | 34 | int filaVazia(NoFila **fila) 35 | { 36 | return *fila == NULL; 37 | } 38 | 39 | // FUNÇÕES AUXILIARES PARA INTERFACE 40 | void limparTela() { 41 | #ifdef _WIN32 42 | system("cls"); 43 | #else 44 | system("clear"); 45 | #endif 46 | } 47 | 48 | void pausar() { 49 | printf("\nPressione ENTER para continuar..."); 50 | limparBuffer(); 51 | getchar(); 52 | } 53 | 54 | int contarElementos(NoFila **fila) { 55 | if (filaVazia(fila)) { 56 | return 0; 57 | } 58 | 59 | NoFila *aux = *fila; 60 | int contador = 0; 61 | 62 | while (aux != NULL) { 63 | contador++; 64 | aux = aux->proximo; 65 | } 66 | 67 | return contador; 68 | } 69 | 70 | void exibirCabecalho(NoFila **fila) { 71 | int total = contarElementos(fila); 72 | char status[20]; 73 | 74 | if (filaVazia(fila)) { 75 | strcpy(status, "VAZIA"); 76 | } else { 77 | strcpy(status, "ATIVA"); 78 | } 79 | 80 | printf("╔══════════════════════════════════════╗\n"); 81 | printf("║ FILA DINAMICA ║\n"); 82 | printf("║ Sistema de Tickets ║\n"); 83 | printf("╠══════════════════════════════════════╣\n"); 84 | printf("║ Status: %-8s | Tickets: %-9d║\n", status, total); 85 | printf("╚══════════════════════════════════════╝\n\n"); 86 | } 87 | 88 | NoFila* encontrarUltimo(NoFila **fila) { 89 | if (filaVazia(fila)) { 90 | return NULL; 91 | } 92 | 93 | NoFila *aux = *fila; 94 | while (aux->proximo != NULL) { 95 | aux = aux->proximo; 96 | } 97 | 98 | return aux; 99 | } 100 | 101 | int enqueue(NoFila **fila, Ticket elemento) 102 | { 103 | NoFila *novoNo = (NoFila *)malloc(sizeof(NoFila)); 104 | 105 | if (novoNo == NULL) 106 | return 0; // Falha na alocação 107 | 108 | novoNo->dados = elemento; 109 | novoNo->proximo = NULL; 110 | 111 | if (filaVazia(fila)) { 112 | *fila = novoNo; 113 | } else { 114 | NoFila *ultimo = encontrarUltimo(fila); 115 | ultimo->proximo = novoNo; 116 | } 117 | 118 | return 1; 119 | } 120 | 121 | Ticket dequeue(NoFila **fila) 122 | { 123 | Ticket vazio = {-1, ""}; 124 | 125 | if (filaVazia(fila)) 126 | return vazio; 127 | 128 | NoFila *noRemover = *fila; 129 | Ticket dadosRemovidos = noRemover->dados; 130 | 131 | *fila = (*fila)->proximo; 132 | free(noRemover); 133 | 134 | return dadosRemovidos; 135 | } 136 | 137 | Ticket consultarProximo(NoFila **fila) 138 | { 139 | Ticket vazio = {-1, ""}; 140 | 141 | if (filaVazia(fila)) 142 | return vazio; 143 | 144 | return (*fila)->dados; 145 | } 146 | 147 | void liberarFila(NoFila **fila) 148 | { 149 | while (!filaVazia(fila)) { 150 | dequeue(fila); 151 | } 152 | } 153 | 154 | // FUNÇÕES UTILIZADAS PELO MENU 155 | void exibirMenu(NoFila **fila, int *opcao) 156 | { 157 | limparTela(); 158 | exibirCabecalho(fila); 159 | 160 | printf("┌──────────────────────────────────────┐\n"); 161 | printf("│ MENU │\n"); 162 | printf("├──────────────────────────────────────┤\n"); 163 | printf("│ 1 - Exibir fila │\n"); 164 | printf("│ 2 - Enqueue (inserir) │\n"); 165 | printf("│ 3 - Dequeue (remover) │\n"); 166 | printf("│ 4 - Consultar proximo │\n"); 167 | printf("│ 5 - Limpar fila │\n"); 168 | printf("│ 6 - Estatisticas │\n"); 169 | printf("│ 0 - Sair │\n"); 170 | printf("└──────────────────────────────────────┘\n\n"); 171 | printf("Escolha uma opcao: "); 172 | scanf("%d", opcao); 173 | } 174 | 175 | void menuExibirFila(NoFila **fila) { 176 | limparTela(); 177 | printf("╔══════════════════════════════════════╗\n"); 178 | printf("║ FILA DE TICKETS ║\n"); 179 | printf("╚══════════════════════════════════════╝\n\n"); 180 | 181 | if (filaVazia(fila)) { 182 | printf("Fila vazia! Nenhum ticket na fila.\n"); 183 | } else { 184 | printf("┌─────────┬────────────┬───────────────────────┐\n"); 185 | printf("│ Posicao │ Prioridade │ Tarefa │\n"); 186 | printf("├─────────┼────────────┼───────────────────────┤\n"); 187 | 188 | NoFila *atual = *fila; 189 | int posicao = 1; 190 | 191 | while (atual != NULL) { 192 | printf("│ %7d │ %10d │ %-21s │\n", posicao, 193 | atual->dados.prioridade, 194 | atual->dados.tarefa); 195 | atual = atual->proximo; 196 | posicao++; 197 | } 198 | printf("└─────────┴────────────┴───────────────────────┘\n"); 199 | printf("\nTotal na fila: %d tickets\n", contarElementos(fila)); 200 | printf("Proximo a ser atendido: Prioridade %d - %s\n", 201 | (*fila)->dados.prioridade, 202 | (*fila)->dados.tarefa); 203 | } 204 | 205 | pausar(); 206 | } 207 | 208 | void menuEnqueue(NoFila **fila) 209 | { 210 | int sucesso; 211 | Ticket novoTicket; 212 | 213 | limparTela(); 214 | printf("╔══════════════════════════════════════╗\n"); 215 | printf("║ INSERIR TICKET ║\n"); 216 | printf("╚══════════════════════════════════════╝\n\n"); 217 | 218 | printf("Digite a prioridade do ticket: "); 219 | scanf("%d", &novoTicket.prioridade); 220 | limparBuffer(); 221 | 222 | printf("Digite a descricao da tarefa: "); 223 | fgets(novoTicket.tarefa, sizeof(novoTicket.tarefa), stdin); 224 | removerQuebraLinha(novoTicket.tarefa); 225 | 226 | sucesso = enqueue(fila, novoTicket); 227 | 228 | if (sucesso) { 229 | printf("\n✅ Ticket inserido com sucesso!\n"); 230 | printf(" Prioridade: %d\n", novoTicket.prioridade); 231 | printf(" Tarefa: %s\n", novoTicket.tarefa); 232 | } else { 233 | printf("\n❌ Erro ao inserir ticket! Memoria insuficiente.\n"); 234 | } 235 | 236 | pausar(); 237 | } 238 | 239 | void menuDequeue(NoFila **fila) { 240 | Ticket removido; 241 | 242 | limparTela(); 243 | printf("╔══════════════════════════════════════╗\n"); 244 | printf("║ REMOVER TICKET ║\n"); 245 | printf("╚══════════════════════════════════════╝\n\n"); 246 | 247 | if (filaVazia(fila)) { 248 | printf("❌ Fila vazia! Nenhum ticket para remover.\n"); 249 | } else { 250 | printf("Ticket a ser removido:\n"); 251 | printf("┌────────────┬───────────────────────┐\n"); 252 | printf("│ Prioridade │ Tarefa │\n"); 253 | printf("├────────────┼───────────────────────┤\n"); 254 | printf("│ %10d │ %-21s │\n", 255 | (*fila)->dados.prioridade, 256 | (*fila)->dados.tarefa); 257 | printf("└────────────┴───────────────────────┘\n\n"); 258 | 259 | removido = dequeue(fila); 260 | 261 | if (removido.prioridade != -1) { 262 | printf("✅ Ticket removido com sucesso!\n"); 263 | printf(" Prioridade: %d\n", removido.prioridade); 264 | printf(" Tarefa: %s\n", removido.tarefa); 265 | } 266 | } 267 | 268 | pausar(); 269 | } 270 | 271 | void menuConsultarProximo(NoFila **fila) { 272 | Ticket proximo; 273 | 274 | limparTela(); 275 | printf("╔══════════════════════════════════════╗\n"); 276 | printf("║ CONSULTAR PROXIMO ║\n"); 277 | printf("╚══════════════════════════════════════╝\n\n"); 278 | 279 | if (filaVazia(fila)) { 280 | printf("❌ Fila vazia! Nenhum ticket na fila.\n"); 281 | } else { 282 | proximo = consultarProximo(fila); 283 | 284 | printf("Proximo ticket a ser atendido:\n"); 285 | printf("┌────────────┬───────────────────────┐\n"); 286 | printf("│ Prioridade │ Tarefa │\n"); 287 | printf("├────────────┼───────────────────────┤\n"); 288 | printf("│ %10d │ %-21s │\n", 289 | proximo.prioridade, 290 | proximo.tarefa); 291 | printf("└────────────┴───────────────────────┘\n"); 292 | 293 | printf("\n📋 Este ticket sera o proximo a ser processado.\n"); 294 | } 295 | 296 | pausar(); 297 | } 298 | 299 | void menuLimparFila(NoFila **fila) { 300 | int confirmacao; 301 | int totalAntes = contarElementos(fila); 302 | 303 | limparTela(); 304 | printf("╔══════════════════════════════════════╗\n"); 305 | printf("║ LIMPAR FILA ║\n"); 306 | printf("╚══════════════════════════════════════╝\n\n"); 307 | 308 | if (filaVazia(fila)) { 309 | printf("❌ A fila ja esta vazia!\n"); 310 | } else { 311 | printf("⚠️ ATENÇÃO: Esta operacao ira remover TODOS os %d tickets da fila!\n", totalAntes); 312 | printf(" Esta acao nao pode ser desfeita.\n\n"); 313 | printf("Deseja realmente limpar a fila? (1-Sim / 0-Nao): "); 314 | scanf("%d", &confirmacao); 315 | 316 | if (confirmacao == 1) { 317 | liberarFila(fila); 318 | printf("\n✅ Fila limpa com sucesso!\n"); 319 | printf(" %d tickets foram removidos.\n", totalAntes); 320 | } else { 321 | printf("\n❌ Operacao cancelada. Fila mantida.\n"); 322 | } 323 | } 324 | 325 | pausar(); 326 | } 327 | 328 | void menuEstatisticas(NoFila **fila) { 329 | limparTela(); 330 | printf("╔══════════════════════════════════════╗\n"); 331 | printf("║ ESTATISTICAS ║\n"); 332 | printf("╚══════════════════════════════════════╝\n\n"); 333 | 334 | int total = contarElementos(fila); 335 | 336 | if (filaVazia(fila)) { 337 | printf("📊 ESTATISTICAS DA FILA:\n"); 338 | printf("┌─────────────────────────┬─────────┐\n"); 339 | printf("│ Total de tickets │ %5d │\n", total); 340 | printf("│ Status │ VAZIA │\n"); 341 | printf("│ Memoria utilizada │ 0 KB │\n"); 342 | printf("└─────────────────────────┴─────────┘\n"); 343 | } else { 344 | // Calcular estatísticas de prioridade 345 | int prioridadeMin = (*fila)->dados.prioridade; 346 | int prioridadeMax = (*fila)->dados.prioridade; 347 | int somaPrioridades = 0; 348 | 349 | NoFila *atual = *fila; 350 | while (atual != NULL) { 351 | if (atual->dados.prioridade < prioridadeMin) { 352 | prioridadeMin = atual->dados.prioridade; 353 | } 354 | if (atual->dados.prioridade > prioridadeMax) { 355 | prioridadeMax = atual->dados.prioridade; 356 | } 357 | somaPrioridades += atual->dados.prioridade; 358 | atual = atual->proximo; 359 | } 360 | 361 | float mediaPrioridade = (float)somaPrioridades / total; 362 | int memoriaKB = (total * sizeof(NoFila)) / 1024; 363 | if (memoriaKB == 0) memoriaKB = 1; // Mínimo 1KB 364 | 365 | printf("📊 ESTATISTICAS DA FILA:\n"); 366 | printf("┌─────────────────────────┬─────────┐\n"); 367 | printf("│ Total de tickets │ %5d │\n", total); 368 | printf("│ Status │ ATIVA │\n"); 369 | printf("│ Prioridade minima │ %5d │\n", prioridadeMin); 370 | printf("│ Prioridade maxima │ %5d │\n", prioridadeMax); 371 | printf("│ Prioridade media │ %5.1f │\n", mediaPrioridade); 372 | printf("│ Memoria utilizada │ %4d KB │\n", memoriaKB); 373 | printf("└─────────────────────────┴─────────┘\n"); 374 | 375 | printf("\n🎯 PROXIMO TICKET:\n"); 376 | printf(" Prioridade: %d\n", (*fila)->dados.prioridade); 377 | printf(" Tarefa: %s\n", (*fila)->dados.tarefa); 378 | } 379 | 380 | pausar(); 381 | } 382 | 383 | int main() 384 | { 385 | NoFila *fila; 386 | int opcao; 387 | 388 | inicializarFila(&fila); 389 | 390 | do { 391 | exibirMenu(&fila, &opcao); 392 | 393 | switch (opcao) { 394 | case 1: 395 | menuExibirFila(&fila); 396 | break; 397 | case 2: 398 | menuEnqueue(&fila); 399 | break; 400 | case 3: 401 | menuDequeue(&fila); 402 | break; 403 | case 4: 404 | menuConsultarProximo(&fila); 405 | break; 406 | case 5: 407 | menuLimparFila(&fila); 408 | break; 409 | case 6: 410 | menuEstatisticas(&fila); 411 | break; 412 | case 0: 413 | printf("\n👋 Encerrando o programa...\n"); 414 | liberarFila(&fila); 415 | printf("✅ Memoria liberada com sucesso!\n"); 416 | break; 417 | default: 418 | printf("\n❌ Opcao invalida! Tente novamente.\n"); 419 | pausar(); 420 | break; 421 | } 422 | } while (opcao != 0); 423 | 424 | return 0; 425 | } -------------------------------------------------------------------------------- /listas/encadeada-ordenada/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct { 6 | int numCamisa; 7 | char nome[50]; 8 | } Jogador; 9 | 10 | typedef struct celula { 11 | Jogador info; 12 | struct celula *prox; 13 | } Celula; 14 | 15 | void limparBuffer() 16 | { 17 | int c; 18 | while ((c = getchar()) != '\n' && c != EOF) 19 | ; 20 | } 21 | 22 | void removerQuebraLinha(char *str) { 23 | str[strcspn(str, "\n")] = 0; 24 | } 25 | 26 | void inicializarLista(Celula **lista) { 27 | (*lista) = NULL; 28 | } 29 | 30 | int listaVazia(Celula **lista) { 31 | if ((*lista) == NULL) 32 | return 1; 33 | 34 | return 0; 35 | } 36 | 37 | // FUNÇÕES AUXILIARES PARA INTERFACE 38 | void limparTela() { 39 | #ifdef _WIN32 40 | system("cls"); 41 | #else 42 | system("clear"); 43 | #endif 44 | } 45 | 46 | void pausar() { 47 | printf("\nPressione ENTER para continuar..."); 48 | limparBuffer(); 49 | getchar(); 50 | } 51 | 52 | int contarElementos(Celula **lista) { 53 | if (listaVazia(lista)) { 54 | return 0; 55 | } 56 | 57 | Celula *aux = (*lista); 58 | int contador = 0; 59 | 60 | while (aux != NULL) { 61 | contador++; 62 | aux = aux->prox; 63 | } 64 | 65 | return contador; 66 | } 67 | 68 | void exibirCabecalho(Celula **lista) { 69 | int total = contarElementos(lista); 70 | char status[20]; 71 | 72 | if (listaVazia(lista)) { 73 | strcpy(status, "VAZIA"); 74 | } else { 75 | strcpy(status, "ORDENADA"); 76 | } 77 | 78 | printf("╔══════════════════════════════════════╗\n"); 79 | printf("║ LISTA ENCADEADA ORDENADA ║\n"); 80 | printf("║ Sistema de Jogadores ║\n"); 81 | printf("╠══════════════════════════════════════╣\n"); 82 | printf("║ Status: %-8s | Jogadores: %d ║\n", status, total); 83 | printf("╚══════════════════════════════════════╝\n\n"); 84 | } 85 | 86 | Celula * criarCelula() { 87 | Celula *nova = (Celula*) malloc(sizeof(Celula)); 88 | return nova; 89 | } 90 | 91 | int inserir(Celula **lista, Jogador elemento) { 92 | Celula *nova; 93 | Celula *aux; 94 | Celula *auxAnterior; 95 | 96 | nova = criarCelula(); 97 | if(nova == NULL) { 98 | return 0; 99 | } 100 | 101 | nova->info = elemento; 102 | nova->prox = NULL; 103 | 104 | aux = (*lista); 105 | while(aux != NULL) { 106 | if (strcmp(nova->info.nome, aux->info.nome) < 0) { 107 | break; 108 | } 109 | 110 | auxAnterior = aux; 111 | aux = aux->prox; 112 | } 113 | 114 | nova->prox = aux; 115 | 116 | if(aux == (*lista)) { 117 | (*lista) = nova; 118 | } else { 119 | auxAnterior->prox = nova; 120 | } 121 | 122 | return 1; 123 | } 124 | 125 | void exibirElementos(Celula **lista) { 126 | if (listaVazia(lista)) { 127 | printf("Lista vazia!\n"); 128 | return; 129 | } 130 | 131 | Celula *aux = (*lista); 132 | 133 | while (aux != NULL) { 134 | printf( 135 | "%d - %s\n", 136 | aux->info.numCamisa, 137 | aux->info.nome 138 | ); 139 | 140 | aux = aux->prox; 141 | } 142 | } 143 | 144 | Jogador criarElemento(int numCamisa, char nome[]) { 145 | Jogador elemento; 146 | 147 | strcpy(elemento.nome, nome); 148 | elemento.numCamisa = numCamisa; 149 | 150 | return elemento; 151 | } 152 | 153 | Jogador removerInicio(Celula **lista) { 154 | Celula *removida; 155 | Jogador removido = criarElemento(-1, ""); 156 | 157 | if(listaVazia(lista)) { 158 | return removido; 159 | } 160 | 161 | removida = (*lista); 162 | removido = removida->info; 163 | 164 | (*lista) = (*lista)->prox; 165 | 166 | free(removida); 167 | 168 | return removido; 169 | } 170 | 171 | Jogador removerFim(Celula **lista) { 172 | Celula *removida; 173 | Celula *anterior; 174 | Jogador removido = criarElemento(-1, ""); 175 | 176 | if(listaVazia(lista)) { 177 | return removido; 178 | } 179 | 180 | if((*lista)->prox == NULL) { 181 | return removerInicio(lista); 182 | } 183 | 184 | removida = (*lista); 185 | while(removida->prox != NULL) { 186 | anterior = removida; 187 | removida = removida->prox; 188 | } 189 | 190 | removido = removida->info; 191 | anterior->prox = NULL; 192 | 193 | free(removida); 194 | 195 | return removido; 196 | } 197 | 198 | int compararElemento(Jogador j1, Jogador j2) { 199 | return strcmp(j1.nome, j2.nome); 200 | } 201 | 202 | Celula * pesquisar(Celula **lista, Jogador pesquisado) { 203 | Celula *aux; 204 | 205 | if(listaVazia(lista)) { 206 | return NULL; 207 | } 208 | 209 | aux = (*lista); 210 | while(aux != NULL) { 211 | if (compararElemento(aux->info, pesquisado) == 0) { 212 | return aux; 213 | } 214 | 215 | aux = aux->prox; 216 | } 217 | 218 | return NULL; 219 | } 220 | 221 | Jogador removerElemento(Celula **lista, Jogador elemento) { 222 | Celula *removida; 223 | Celula *anterior; 224 | Jogador removido = criarElemento(-1, ""); 225 | 226 | if(listaVazia(lista)) { 227 | return removido; 228 | } 229 | 230 | removida = pesquisar(lista, elemento); 231 | if(removida == NULL) { 232 | return removido; 233 | } 234 | 235 | if(removida == (*lista)) { 236 | return removerInicio(lista); 237 | } 238 | 239 | removido = removida->info; 240 | 241 | anterior = (*lista); 242 | while(anterior->prox != removida) { 243 | anterior = anterior->prox; 244 | } 245 | 246 | anterior->prox = removida->prox; 247 | 248 | free(removida); 249 | 250 | return removido; 251 | } 252 | 253 | // FUNÇÕES UTILIZADAS PELO MENU 254 | void exibirMenu(Celula **lista, int *opcao) 255 | { 256 | limparTela(); 257 | exibirCabecalho(lista); 258 | 259 | printf("┌──────────────────────────────────────┐\n"); 260 | printf("│ MENU │\n"); 261 | printf("├──────────────────────────────────────┤\n"); 262 | printf("│ 1 - Exibir elementos │\n"); 263 | printf("│ 2 - Inserir elemento (ordenado) │\n"); 264 | printf("│ 3 - Remover do inicio │\n"); 265 | printf("│ 4 - Remover do fim │\n"); 266 | printf("│ 5 - Pesquisar elemento │\n"); 267 | printf("│ 6 - Remover elemento especifico │\n"); 268 | printf("│ 0 - Sair │\n"); 269 | printf("└──────────────────────────────────────┘\n\n"); 270 | printf("Escolha uma opcao: "); 271 | scanf("%d", opcao); 272 | } 273 | 274 | void menuExibirElementos(Celula **lista) { 275 | limparTela(); 276 | printf("╔══════════════════════════════════════╗\n"); 277 | printf("║ LISTA DE JOGADORES (ORDENADA) ║\n"); 278 | printf("╚══════════════════════════════════════╝\n\n"); 279 | 280 | if (listaVazia(lista)) { 281 | printf("Lista vazia! Nenhum jogador cadastrado.\n"); 282 | } else { 283 | printf("┌─────────────┬────────────────────────┐\n"); 284 | printf("│ Num. Camisa │ Nome │\n"); 285 | printf("├─────────────┼────────────────────────┤\n"); 286 | 287 | Celula *aux = (*lista); 288 | while (aux != NULL) { 289 | printf("│ %11d │ %-22s │\n", aux->info.numCamisa, aux->info.nome); 290 | aux = aux->prox; 291 | } 292 | printf("└─────────────┴────────────────────────┘\n"); 293 | printf("\nTotal de jogadores: %d (ordenados por nome)\n", contarElementos(lista)); 294 | } 295 | 296 | pausar(); 297 | } 298 | 299 | void menuInserir(Celula **lista) 300 | { 301 | int sucesso; 302 | Jogador novoJogador; 303 | 304 | limparTela(); 305 | printf("╔══════════════════════════════════════╗\n"); 306 | printf("║ INSERIR ELEMENTO (ORDENADO) ║\n"); 307 | printf("╚══════════════════════════════════════╝\n\n"); 308 | 309 | printf("Digite o numero da camisa: "); 310 | scanf("%d", &novoJogador.numCamisa); 311 | 312 | limparBuffer(); 313 | 314 | printf("Digite o nome do jogador: "); 315 | fgets(novoJogador.nome, 50, stdin); 316 | 317 | removerQuebraLinha(novoJogador.nome); 318 | 319 | sucesso = inserir(lista, novoJogador); 320 | 321 | printf("\n"); 322 | if (sucesso) 323 | printf("Jogador inserido com sucesso na posicao ordenada!\n"); 324 | else 325 | printf("Erro ao inserir jogador!\n"); 326 | 327 | pausar(); 328 | } 329 | 330 | void menuRemoverInicio(Celula **lista) { 331 | Jogador removido; 332 | 333 | limparTela(); 334 | printf("╔══════════════════════════════════════╗\n"); 335 | printf("║ REMOVER DO INICIO ║\n"); 336 | printf("╚══════════════════════════════════════╝\n\n"); 337 | 338 | if (listaVazia(lista)) { 339 | printf("Lista vazia! Nada para remover.\n"); 340 | pausar(); 341 | return; 342 | } 343 | 344 | removido = removerInicio(lista); 345 | 346 | printf("\n"); 347 | if (removido.numCamisa != -1) 348 | printf("Jogador removido: %d - %s\n", removido.numCamisa, removido.nome); 349 | else 350 | printf("Erro ao remover jogador!\n"); 351 | 352 | pausar(); 353 | } 354 | 355 | void menuRemoverFim(Celula **lista) { 356 | Jogador removido; 357 | 358 | limparTela(); 359 | printf("╔══════════════════════════════════════╗\n"); 360 | printf("║ REMOVER DO FIM ║\n"); 361 | printf("╚══════════════════════════════════════╝\n\n"); 362 | 363 | if (listaVazia(lista)) { 364 | printf("Lista vazia! Nada para remover.\n"); 365 | pausar(); 366 | return; 367 | } 368 | 369 | removido = removerFim(lista); 370 | 371 | printf("\n"); 372 | if (removido.numCamisa != -1) 373 | printf("Jogador removido: %d - %s\n", removido.numCamisa, removido.nome); 374 | else 375 | printf("Erro ao remover jogador!\n"); 376 | 377 | pausar(); 378 | } 379 | 380 | void menuPesquisarElemento(Celula **lista) { 381 | char nome[50]; 382 | Jogador pesquisado; 383 | Celula *encontrado; 384 | 385 | limparTela(); 386 | printf("╔══════════════════════════════════════╗\n"); 387 | printf("║ PESQUISAR ELEMENTO ║\n"); 388 | printf("╚══════════════════════════════════════╝\n\n"); 389 | 390 | if (listaVazia(lista)) { 391 | printf("Lista vazia! Nada para pesquisar.\n"); 392 | pausar(); 393 | return; 394 | } 395 | 396 | limparBuffer(); 397 | printf("Digite o nome para pesquisar: "); 398 | fgets(nome, 50, stdin); 399 | removerQuebraLinha(nome); 400 | 401 | pesquisado = criarElemento(0, nome); 402 | encontrado = pesquisar(lista, pesquisado); 403 | 404 | printf("\n"); 405 | if (encontrado != NULL) { 406 | printf("Elemento encontrado!\n"); 407 | printf("┌─────────────┬────────────────────────┐\n"); 408 | printf("│ Num. Camisa │ %-22d │\n", encontrado->info.numCamisa); 409 | printf("│ Nome │ %-22s │\n", encontrado->info.nome); 410 | printf("└─────────────┴────────────────────────┘\n"); 411 | } else { 412 | printf("Elemento nao encontrado!\n"); 413 | } 414 | 415 | pausar(); 416 | } 417 | 418 | void menuRemoverElemento(Celula **lista) { 419 | char nome[50]; 420 | Jogador pesquisado, removido; 421 | 422 | limparTela(); 423 | printf("╔══════════════════════════════════════╗\n"); 424 | printf("║ REMOVER ELEMENTO ESPECIFICO ║\n"); 425 | printf("╚══════════════════════════════════════╝\n\n"); 426 | 427 | if (listaVazia(lista)) { 428 | printf("Lista vazia! Nada para remover.\n"); 429 | pausar(); 430 | return; 431 | } 432 | 433 | limparBuffer(); 434 | printf("Digite o nome do jogador a remover: "); 435 | fgets(nome, 50, stdin); 436 | removerQuebraLinha(nome); 437 | 438 | pesquisado = criarElemento(0, nome); 439 | removido = removerElemento(lista, pesquisado); 440 | 441 | printf("\n"); 442 | if (removido.numCamisa != -1) 443 | printf("Jogador removido: %d - %s\n", removido.numCamisa, removido.nome); 444 | else 445 | printf("Jogador nao encontrado!\n"); 446 | 447 | pausar(); 448 | } 449 | 450 | int main() { 451 | Celula *lista; 452 | int opcao; 453 | 454 | inicializarLista(&lista); 455 | 456 | do 457 | { 458 | exibirMenu(&lista, &opcao); 459 | 460 | switch (opcao) 461 | { 462 | case 1: 463 | menuExibirElementos(&lista); 464 | break; 465 | 466 | case 2: 467 | menuInserir(&lista); 468 | break; 469 | 470 | case 3: 471 | menuRemoverInicio(&lista); 472 | break; 473 | 474 | case 4: 475 | menuRemoverFim(&lista); 476 | break; 477 | 478 | case 5: 479 | menuPesquisarElemento(&lista); 480 | break; 481 | 482 | case 6: 483 | menuRemoverElemento(&lista); 484 | break; 485 | 486 | case 0: 487 | limparTela(); 488 | printf("╔══════════════════════════════════════╗\n"); 489 | printf("║ ATE A PROXIMA! ║\n"); 490 | printf("║ ║\n"); 491 | printf("║ Obrigado por usar o sistema! ║\n"); 492 | printf("╚══════════════════════════════════════╝\n\n"); 493 | break; 494 | 495 | default: 496 | limparTela(); 497 | printf("╔══════════════════════════════════════╗\n"); 498 | printf("║ OPCAO INVALIDA! ║\n"); 499 | printf("╚══════════════════════════════════════╝\n\n"); 500 | printf("Por favor, escolha uma opcao valida (0-6).\n"); 501 | pausar(); 502 | break; 503 | } 504 | } while (opcao != 0); 505 | 506 | return 0; 507 | } 508 | -------------------------------------------------------------------------------- /listas/estatica/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_ELEMENTOS 3 6 | 7 | typedef struct 8 | { 9 | int matricula; 10 | char nome[50]; 11 | } Aluno; 12 | 13 | typedef struct 14 | { 15 | Aluno elementos[MAX_ELEMENTOS]; 16 | int ultimo; 17 | } ListaEstatica; 18 | 19 | void limparBuffer() 20 | { 21 | int c; 22 | while ((c = getchar()) != '\n' && c != EOF) 23 | ; 24 | } 25 | 26 | void removerQuebraLinha(char *str) { 27 | str[strcspn(str, "\n")] = 0; 28 | } 29 | 30 | void inicializarLista(ListaEstatica *lista) 31 | { 32 | lista->ultimo = -1; 33 | } 34 | 35 | int listaVazia(ListaEstatica *lista) 36 | { 37 | if (lista->ultimo == -1) 38 | return 1; 39 | 40 | return 0; 41 | } 42 | 43 | int listaCheia(ListaEstatica *lista) 44 | { 45 | if (lista->ultimo == (MAX_ELEMENTOS - 1)) 46 | return 1; 47 | 48 | return 0; 49 | } 50 | 51 | void limparTela() { 52 | #ifdef _WIN32 53 | system("cls"); 54 | #else 55 | system("clear"); 56 | #endif 57 | } 58 | 59 | void pausar() { 60 | printf("\nPressione ENTER para continuar..."); 61 | limparBuffer(); 62 | getchar(); 63 | } 64 | 65 | void exibirCabecalho(ListaEstatica *lista) { 66 | int total = lista->ultimo + 1; 67 | char status[20]; 68 | 69 | if (listaVazia(lista)) { 70 | strcpy(status, "VAZIA"); 71 | } else if (listaCheia(lista)) { 72 | strcpy(status, "CHEIA"); 73 | } else { 74 | strcpy(status, "PARCIAL"); 75 | } 76 | 77 | printf("╔══════════════════════════════════════╗\n"); 78 | printf("║ LISTA ESTATICA ║\n"); 79 | printf("║ Sistema de Alunos ║\n"); 80 | printf("╠══════════════════════════════════════╣\n"); 81 | printf("║ Status: %-8s | Alunos: %d/%d ║\n", status, total, MAX_ELEMENTOS); 82 | printf("╚══════════════════════════════════════╝\n\n"); 83 | } 84 | 85 | void exibirElementos(ListaEstatica *lista) 86 | { 87 | if (listaVazia(lista)) 88 | { 89 | printf("Lista vazia!\n"); 90 | return; 91 | } 92 | 93 | for (int i = 0; i <= lista->ultimo; i++) 94 | printf("%d - %s\n", lista->elementos[i].matricula, lista->elementos[i].nome); 95 | } 96 | 97 | int inserirFim(ListaEstatica *lista, Aluno elemento) 98 | { 99 | if (listaCheia(lista)) 100 | return 0; 101 | 102 | lista->elementos[lista->ultimo + 1] = elemento; 103 | lista->ultimo++; 104 | 105 | return 1; 106 | } 107 | 108 | int inserirPosicao(ListaEstatica *lista, int posicao, Aluno elemento) 109 | { 110 | if (listaCheia(lista)) 111 | { 112 | printf("Lista cheia!\n"); 113 | return 0; 114 | } 115 | 116 | if (posicao < 0 || posicao > lista->ultimo + 1) 117 | { 118 | printf("Posição inválida!\n"); 119 | return 0; 120 | } 121 | 122 | for (int i = lista->ultimo; i >= posicao; i--) 123 | lista->elementos[i + 1] = lista->elementos[i]; 124 | 125 | lista->elementos[posicao] = elemento; 126 | lista->ultimo++; 127 | 128 | return 1; 129 | } 130 | 131 | int removerPosicao(ListaEstatica *lista, int posicao) { 132 | if(listaVazia(lista)) { 133 | printf("Nada para remover\n"); 134 | return 0; 135 | } 136 | 137 | if (posicao < 0 || posicao > lista->ultimo + 1) 138 | { 139 | printf("Posição inválida!\n"); 140 | return 0; 141 | } 142 | 143 | for(int i = posicao; i < lista->ultimo; i++) 144 | lista->elementos[i] = lista->elementos[i + 1]; 145 | 146 | lista->ultimo--; 147 | 148 | return 1; 149 | } 150 | 151 | int modificarElemento(ListaEstatica *lista, int posicao, Aluno elemento) { 152 | if (listaVazia(lista)) 153 | { 154 | printf("Lista vazia!\n"); 155 | return 0; 156 | } 157 | 158 | if (posicao < 0 || posicao > lista->ultimo + 1) 159 | { 160 | printf("Posição inválida!\n"); 161 | return 0; 162 | } 163 | 164 | lista->elementos[posicao] = elemento; 165 | 166 | return 1; 167 | } 168 | 169 | int pesquisarElemento(ListaEstatica *lista, int matricula) { 170 | if (listaVazia(lista)) { 171 | printf("Lista vazia!\n"); 172 | return -1; 173 | } 174 | 175 | for(int i = 0; i <= lista->ultimo; i++) { 176 | if (lista->elementos[i].matricula == matricula) { 177 | return i; 178 | } 179 | } 180 | 181 | return -1; 182 | } 183 | 184 | // FUNÇÕES UTILIZADAS PELO MENU 185 | void exibirMenu(ListaEstatica *lista, int *opcao) 186 | { 187 | limparTela(); 188 | exibirCabecalho(lista); 189 | 190 | printf("┌──────────────────────────────────────┐\n"); 191 | printf("│ MENU │\n"); 192 | printf("├──────────────────────────────────────┤\n"); 193 | printf("│ 1 - Exibir elementos │\n"); 194 | printf("│ 2 - Inserir na posicao │\n"); 195 | printf("│ 3 - Inserir no fim │\n"); 196 | printf("│ 4 - Remover na posicao │\n"); 197 | printf("│ 5 - Modificar elemento │\n"); 198 | printf("│ 6 - Pesquisar elemento │\n"); 199 | printf("│ 0 - Sair │\n"); 200 | printf("└──────────────────────────────────────┘\n\n"); 201 | printf("Escolha uma opcao: "); 202 | scanf("%d", opcao); 203 | } 204 | 205 | void menuExibirElementos(ListaEstatica *lista) { 206 | limparTela(); 207 | printf("╔══════════════════════════════════════╗\n"); 208 | printf("║ LISTA DE ALUNOS ║\n"); 209 | printf("╚══════════════════════════════════════╝\n\n"); 210 | 211 | if (listaVazia(lista)) { 212 | printf("Lista vazia! Nenhum aluno cadastrado.\n"); 213 | } else { 214 | printf("┌─────────────┬────────────────────────┐\n"); 215 | printf("│ Matrícula │ Nome │\n"); 216 | printf("├─────────────┼────────────────────────┤\n"); 217 | 218 | for (int i = 0; i <= lista->ultimo; i++) { 219 | printf("│ %11d │ %-22s │\n", lista->elementos[i].matricula, lista->elementos[i].nome); 220 | } 221 | printf("└─────────────┴────────────────────────┘\n"); 222 | printf("\nTotal de alunos: %d/%d\n", lista->ultimo + 1, MAX_ELEMENTOS); 223 | } 224 | 225 | pausar(); 226 | } 227 | 228 | void menuInserirPosicao(ListaEstatica *lista) 229 | { 230 | int posicao, sucesso; 231 | Aluno novoElemento; 232 | 233 | limparTela(); 234 | printf("╔══════════════════════════════════════╗\n"); 235 | printf("║ INSERIR NA POSICAO ║\n"); 236 | printf("╚══════════════════════════════════════╝\n\n"); 237 | 238 | if (listaCheia(lista)) { 239 | printf("Lista cheia! Nao e possivel inserir novos elementos.\n"); 240 | pausar(); 241 | return; 242 | } 243 | 244 | printf("Digite a posicao (0 a %d): ", lista->ultimo + 1); 245 | scanf("%d", &posicao); 246 | 247 | printf("Digite a matricula do aluno: "); 248 | scanf("%d", &novoElemento.matricula); 249 | 250 | limparBuffer(); 251 | 252 | printf("Digite o nome do aluno: "); 253 | fgets(novoElemento.nome, 50, stdin); 254 | 255 | removerQuebraLinha(novoElemento.nome); 256 | 257 | sucesso = inserirPosicao(lista, posicao, novoElemento); 258 | 259 | printf("\n"); 260 | if (sucesso) 261 | printf("Elemento inserido com sucesso!\n"); 262 | else 263 | printf("Erro ao inserir elemento!\n"); 264 | 265 | pausar(); 266 | } 267 | 268 | void menuInserirFim(ListaEstatica *lista) 269 | { 270 | int sucesso; 271 | Aluno novoElemento; 272 | 273 | limparTela(); 274 | printf("╔══════════════════════════════════════╗\n"); 275 | printf("║ INSERIR NO FIM ║\n"); 276 | printf("╚══════════════════════════════════════╝\n\n"); 277 | 278 | if (listaCheia(lista)) { 279 | printf("Lista cheia! Nao e possivel inserir novos elementos.\n"); 280 | pausar(); 281 | return; 282 | } 283 | 284 | printf("Digite a matricula do aluno: "); 285 | scanf("%d", &novoElemento.matricula); 286 | 287 | limparBuffer(); 288 | 289 | printf("Digite o nome do aluno: "); 290 | fgets(novoElemento.nome, 50, stdin); 291 | 292 | removerQuebraLinha(novoElemento.nome); 293 | 294 | sucesso = inserirFim(lista, novoElemento); 295 | 296 | printf("\n"); 297 | if (sucesso) 298 | printf("Elemento inserido com sucesso!\n"); 299 | else 300 | printf("Erro ao inserir elemento!\n"); 301 | 302 | pausar(); 303 | } 304 | 305 | void menuRemoverPosicao(ListaEstatica *lista) { 306 | int sucesso, posicao; 307 | 308 | limparTela(); 309 | printf("╔══════════════════════════════════════╗\n"); 310 | printf("║ REMOVER DA POSICAO ║\n"); 311 | printf("╚══════════════════════════════════════╝\n\n"); 312 | 313 | if (listaVazia(lista)) { 314 | printf("Lista vazia! Nada para remover.\n"); 315 | pausar(); 316 | return; 317 | } 318 | 319 | printf("Lista atual:\n"); 320 | for (int i = 0; i <= lista->ultimo; i++) { 321 | printf(" [%d] %d - %s\n", i, lista->elementos[i].matricula, lista->elementos[i].nome); 322 | } 323 | 324 | printf("\nDigite a posicao a remover (0 a %d): ", lista->ultimo); 325 | scanf("%d", &posicao); 326 | 327 | sucesso = removerPosicao(lista, posicao); 328 | 329 | printf("\n"); 330 | if (sucesso) 331 | printf("Elemento removido com sucesso!\n"); 332 | else 333 | printf("Erro ao remover elemento!\n"); 334 | 335 | pausar(); 336 | } 337 | 338 | void menuModificarElemento(ListaEstatica *lista) 339 | { 340 | int posicao, sucesso; 341 | Aluno novoElemento; 342 | 343 | limparTela(); 344 | printf("╔══════════════════════════════════════╗\n"); 345 | printf("║ MODIFICAR ELEMENTO ║\n"); 346 | printf("╚══════════════════════════════════════╝\n\n"); 347 | 348 | if (listaVazia(lista)) { 349 | printf("Lista vazia! Nada para modificar.\n"); 350 | pausar(); 351 | return; 352 | } 353 | 354 | printf("Lista atual:\n"); 355 | for (int i = 0; i <= lista->ultimo; i++) { 356 | printf(" [%d] %d - %s\n", i, lista->elementos[i].matricula, lista->elementos[i].nome); 357 | } 358 | 359 | printf("\nDigite a posicao a modificar (0 a %d): ", lista->ultimo); 360 | scanf("%d", &posicao); 361 | 362 | if (posicao < 0 || posicao > lista->ultimo) { 363 | printf("Posicao invalida!\n"); 364 | pausar(); 365 | return; 366 | } 367 | 368 | printf("Digite a nova matricula do aluno: "); 369 | scanf("%d", &novoElemento.matricula); 370 | 371 | limparBuffer(); 372 | 373 | printf("Digite o novo nome do aluno: "); 374 | fgets(novoElemento.nome, 50, stdin); 375 | 376 | removerQuebraLinha(novoElemento.nome); 377 | 378 | sucesso = modificarElemento(lista, posicao, novoElemento); 379 | 380 | printf("\n"); 381 | if (sucesso) 382 | printf("Elemento modificado com sucesso!\n"); 383 | else 384 | printf("Erro ao modificar elemento!\n"); 385 | 386 | pausar(); 387 | } 388 | 389 | void menuPesquisarElemento(ListaEstatica *lista) { 390 | int matricula, encontrado; 391 | 392 | limparTela(); 393 | printf("╔══════════════════════════════════════╗\n"); 394 | printf("║ PESQUISAR ELEMENTO ║\n"); 395 | printf("╚══════════════════════════════════════╝\n\n"); 396 | 397 | if (listaVazia(lista)) { 398 | printf("Lista vazia! Nada para pesquisar.\n"); 399 | pausar(); 400 | return; 401 | } 402 | 403 | printf("Digite a matricula para pesquisar: "); 404 | scanf("%d", &matricula); 405 | 406 | encontrado = pesquisarElemento(lista, matricula); 407 | 408 | printf("\n"); 409 | if (encontrado >= 0) { 410 | printf("Elemento encontrado!\n"); 411 | printf("┌─────────────┬────────────────────────┐\n"); 412 | printf("│ Posicao │ %2d │\n", encontrado); 413 | printf("│ Matricula │ %-22d │\n", lista->elementos[encontrado].matricula); 414 | printf("│ Nome │ %-22s │\n", lista->elementos[encontrado].nome); 415 | printf("└─────────────┴────────────────────────┘\n"); 416 | } else { 417 | printf("Elemento nao encontrado!\n"); 418 | } 419 | 420 | pausar(); 421 | } 422 | 423 | int main() 424 | { 425 | ListaEstatica lista; 426 | int opcao; 427 | 428 | inicializarLista(&lista); 429 | 430 | do 431 | { 432 | exibirMenu(&lista, &opcao); 433 | 434 | switch (opcao) 435 | { 436 | case 1: 437 | menuExibirElementos(&lista); 438 | break; 439 | 440 | case 2: 441 | menuInserirPosicao(&lista); 442 | break; 443 | 444 | case 3: 445 | menuInserirFim(&lista); 446 | break; 447 | 448 | case 4: 449 | menuRemoverPosicao(&lista); 450 | break; 451 | 452 | case 5: 453 | menuModificarElemento(&lista); 454 | break; 455 | 456 | case 6: 457 | menuPesquisarElemento(&lista); 458 | break; 459 | 460 | case 0: 461 | limparTela(); 462 | printf("╔══════════════════════════════════════╗\n"); 463 | printf("║ ATE A PROXIMA! ║\n"); 464 | printf("║ ║\n"); 465 | printf("║ Obrigado por usar o sistema! ║\n"); 466 | printf("╚══════════════════════════════════════╝\n\n"); 467 | break; 468 | 469 | default: 470 | limparTela(); 471 | printf("╔══════════════════════════════════════╗\n"); 472 | printf("║ OPCAO INVALIDA! ║\n"); 473 | printf("╚══════════════════════════════════════╝\n\n"); 474 | printf("Por favor, escolha uma opcao valida (0-6).\n"); 475 | pausar(); 476 | break; 477 | } 478 | } while (opcao != 0); 479 | 480 | return 0; 481 | } 482 | -------------------------------------------------------------------------------- /pilhas/estatica/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_ELEMENTOS 5 6 | 7 | // Estrutura que representa um produto 8 | typedef struct { 9 | int codigo; 10 | char nome[50]; 11 | float preco; 12 | } Produto; 13 | 14 | // Estrutura que representa a pilha estática 15 | typedef struct { 16 | Produto elementos[MAX_ELEMENTOS]; 17 | int topo; 18 | } PilhaEstatica; 19 | 20 | // ========== FUNÇÕES AUXILIARES ========== 21 | 22 | void limparBuffer() { 23 | int c; 24 | while ((c = getchar()) != '\n' && c != EOF); 25 | } 26 | 27 | void removerQuebraLinha(char *str) { 28 | str[strcspn(str, "\n")] = 0; 29 | } 30 | 31 | void limparTela() { 32 | #ifdef _WIN32 33 | system("cls"); 34 | #else 35 | system("clear"); 36 | #endif 37 | } 38 | 39 | void pausar() { 40 | printf("\nPressione ENTER para continuar..."); 41 | limparBuffer(); 42 | getchar(); 43 | } 44 | 45 | // ========== FUNÇÕES DA PILHA ========== 46 | 47 | void inicializarPilha(PilhaEstatica *pilha) { 48 | pilha->topo = -1; 49 | } 50 | 51 | int pilhaVazia(PilhaEstatica *pilha) { 52 | return (pilha->topo == -1); 53 | } 54 | 55 | int pilhaCheia(PilhaEstatica *pilha) { 56 | return (pilha->topo == (MAX_ELEMENTOS - 1)); 57 | } 58 | 59 | void exibirCabecalho(PilhaEstatica *pilha) { 60 | int total = pilha->topo + 1; 61 | char status[20]; 62 | 63 | if (pilhaVazia(pilha)) { 64 | strcpy(status, "VAZIA"); 65 | } else if (pilhaCheia(pilha)) { 66 | strcpy(status, "CHEIA"); 67 | } else { 68 | strcpy(status, "PARCIAL"); 69 | } 70 | 71 | printf("╔══════════════════════════════════════╗\n"); 72 | printf("║ PILHA ESTÁTICA ║\n"); 73 | printf("║ Sistema de Produtos ║\n"); 74 | printf("╠══════════════════════════════════════╣\n"); 75 | printf("║ Status: %-8s | Produtos: %d/%d ║\n", status, total, MAX_ELEMENTOS); 76 | printf("╚══════════════════════════════════════╝\n\n"); 77 | } 78 | 79 | int push(PilhaEstatica *pilha, Produto elemento) { 80 | if (pilhaCheia(pilha)) { 81 | return 0; // Falha: pilha cheia 82 | } 83 | 84 | pilha->topo++; 85 | pilha->elementos[pilha->topo] = elemento; 86 | return 1; // Sucesso 87 | } 88 | 89 | Produto pop(PilhaEstatica *pilha) { 90 | Produto elementoVazio = {-1, "", 0.0}; 91 | 92 | if (pilhaVazia(pilha)) { 93 | return elementoVazio; // Retorna elemento inválido 94 | } 95 | 96 | Produto elemento = pilha->elementos[pilha->topo]; 97 | pilha->topo--; 98 | return elemento; 99 | } 100 | 101 | Produto top(PilhaEstatica *pilha) { 102 | Produto elementoVazio = {-1, "", 0.0}; 103 | 104 | if (pilhaVazia(pilha)) { 105 | return elementoVazio; // Retorna elemento inválido 106 | } 107 | 108 | return pilha->elementos[pilha->topo]; 109 | } 110 | 111 | int tamanho(PilhaEstatica *pilha) { 112 | return (pilha->topo + 1); 113 | } 114 | 115 | void exibirPilha(PilhaEstatica *pilha) { 116 | if (pilhaVazia(pilha)) { 117 | printf("A pilha está vazia!\n"); 118 | return; 119 | } 120 | 121 | printf("PILHA (Topo → Base):\n"); 122 | printf("┌─────────────────────────────────────────────────────┐\n"); 123 | printf("│ Pos │ Código │ Nome │ Preço │\n"); 124 | printf("├─────┼────────┼───────────────────────┼───────────────┤\n"); 125 | 126 | for (int i = pilha->topo; i >= 0; i--) { 127 | printf("│ [%d] │ %-6d │ %-20s │ R$ %10.2f │\n", 128 | i, 129 | pilha->elementos[i].codigo, 130 | pilha->elementos[i].nome, 131 | pilha->elementos[i].preco); 132 | } 133 | 134 | printf("└─────────────────────────────────────────────────────┘\n"); 135 | printf("💡 Elemento [%d] é o TOPO da pilha\n", pilha->topo); 136 | } 137 | 138 | // ========== FUNÇÕES DO MENU ========== 139 | 140 | void exibirMenu(PilhaEstatica *pilha, int *opcao) { 141 | limparTela(); 142 | exibirCabecalho(pilha); 143 | 144 | printf("┌──────────────────────────────────────┐\n"); 145 | printf("│ MENU │\n"); 146 | printf("├──────────────────────────────────────┤\n"); 147 | printf("│ 1 - Exibir pilha │\n"); 148 | printf("│ 2 - Empilhar (Push) │\n"); 149 | printf("│ 3 - Desempilhar (Pop) │\n"); 150 | printf("│ 4 - Consultar topo │\n"); 151 | printf("│ 5 - Verificar se está vazia │\n"); 152 | printf("│ 6 - Verificar se está cheia │\n"); 153 | printf("│ 7 - Consultar tamanho │\n"); 154 | printf("│ 0 - Sair │\n"); 155 | printf("└──────────────────────────────────────┘\n\n"); 156 | 157 | printf("Escolha uma opção: "); 158 | scanf("%d", opcao); 159 | limparBuffer(); 160 | } 161 | 162 | void menuExibirPilha(PilhaEstatica *pilha) { 163 | limparTela(); 164 | exibirCabecalho(pilha); 165 | 166 | printf("═══════════════ VISUALIZAR PILHA ═══════════════\n\n"); 167 | exibirPilha(pilha); 168 | 169 | pausar(); 170 | } 171 | 172 | void menuPush(PilhaEstatica *pilha) { 173 | limparTela(); 174 | exibirCabecalho(pilha); 175 | 176 | printf("═══════════════ EMPILHAR PRODUTO ═══════════════\n\n"); 177 | 178 | if (pilhaCheia(pilha)) { 179 | printf("❌ ERRO: Pilha cheia! Não é possível empilhar.\n"); 180 | printf("💡 Dica: Desempilhe alguns produtos primeiro.\n"); 181 | pausar(); 182 | return; 183 | } 184 | 185 | Produto produto; 186 | 187 | printf("📦 Digite os dados do produto:\n\n"); 188 | 189 | printf("Código: "); 190 | scanf("%d", &produto.codigo); 191 | limparBuffer(); 192 | 193 | printf("Nome: "); 194 | fgets(produto.nome, sizeof(produto.nome), stdin); 195 | removerQuebraLinha(produto.nome); 196 | 197 | printf("Preço: R$ "); 198 | scanf("%f", &produto.preco); 199 | limparBuffer(); 200 | 201 | if (push(pilha, produto)) { 202 | printf("\n✅ Produto empilhado com sucesso!\n"); 203 | printf("📊 Produtos na pilha: %d/%d\n", tamanho(pilha), MAX_ELEMENTOS); 204 | } else { 205 | printf("\n❌ Erro ao empilhar produto!\n"); 206 | } 207 | 208 | pausar(); 209 | } 210 | 211 | void menuPop(PilhaEstatica *pilha) { 212 | limparTela(); 213 | exibirCabecalho(pilha); 214 | 215 | printf("═══════════════ DESEMPILHAR PRODUTO ═══════════════\n\n"); 216 | 217 | if (pilhaVazia(pilha)) { 218 | printf("❌ ERRO: Pilha vazia! Não há produtos para desempilhar.\n"); 219 | printf("💡 Dica: Empilhe alguns produtos primeiro.\n"); 220 | pausar(); 221 | return; 222 | } 223 | 224 | printf("📦 Produto no topo da pilha:\n"); 225 | Produto topo = top(pilha); 226 | printf(" Código: %d\n", topo.codigo); 227 | printf(" Nome: %s\n", topo.nome); 228 | printf(" Preço: R$ %.2f\n\n", topo.preco); 229 | 230 | printf("❓ Deseja realmente desempilhar este produto? (s/n): "); 231 | char resposta; 232 | scanf("%c", &resposta); 233 | limparBuffer(); 234 | 235 | if (resposta == 's' || resposta == 'S') { 236 | Produto removido = pop(pilha); 237 | if (removido.codigo != -1) { 238 | printf("\n✅ Produto desempilhado com sucesso!\n"); 239 | printf("📦 Produto removido: %s\n", removido.nome); 240 | printf("📊 Produtos restantes: %d/%d\n", tamanho(pilha), MAX_ELEMENTOS); 241 | } else { 242 | printf("\n❌ Erro ao desempilhar produto!\n"); 243 | } 244 | } else { 245 | printf("\n↩️ Operação cancelada.\n"); 246 | } 247 | 248 | pausar(); 249 | } 250 | 251 | void menuConsultarTopo(PilhaEstatica *pilha) { 252 | limparTela(); 253 | exibirCabecalho(pilha); 254 | 255 | printf("═══════════════ CONSULTAR TOPO ═══════════════\n\n"); 256 | 257 | if (pilhaVazia(pilha)) { 258 | printf("❌ ERRO: Pilha vazia! Não há produtos no topo.\n"); 259 | printf("💡 Dica: Empilhe alguns produtos primeiro.\n"); 260 | pausar(); 261 | return; 262 | } 263 | 264 | Produto topo = top(pilha); 265 | 266 | printf("🔝 PRODUTO NO TOPO DA PILHA:\n"); 267 | printf("┌─────────────────────────────────────────────────────┐\n"); 268 | printf("│ Código: %-6d │\n", topo.codigo); 269 | printf("│ Nome: %-40s │\n", topo.nome); 270 | printf("│ Preço: R$ %-10.2f │\n", topo.preco); 271 | printf("└─────────────────────────────────────────────────────┘\n"); 272 | 273 | printf("\n📊 Posição do topo: [%d]\n", pilha->topo); 274 | printf("📊 Total de produtos: %d/%d\n", tamanho(pilha), MAX_ELEMENTOS); 275 | 276 | pausar(); 277 | } 278 | 279 | void menuVerificarVazia(PilhaEstatica *pilha) { 280 | limparTela(); 281 | exibirCabecalho(pilha); 282 | 283 | printf("═══════════════ VERIFICAR SE ESTÁ VAZIA ═══════════════\n\n"); 284 | 285 | if (pilhaVazia(pilha)) { 286 | printf("✅ A pilha está VAZIA!\n"); 287 | printf("📊 Produtos na pilha: 0/%d\n", MAX_ELEMENTOS); 288 | printf("💡 Dica: Use a opção 2 para empilhar produtos.\n"); 289 | } else { 290 | printf("❌ A pilha NÃO está vazia!\n"); 291 | printf("📊 Produtos na pilha: %d/%d\n", tamanho(pilha), MAX_ELEMENTOS); 292 | printf("💡 Dica: Use a opção 3 para desempilhar produtos.\n"); 293 | } 294 | 295 | pausar(); 296 | } 297 | 298 | void menuVerificarCheia(PilhaEstatica *pilha) { 299 | limparTela(); 300 | exibirCabecalho(pilha); 301 | 302 | printf("═══════════════ VERIFICAR SE ESTÁ CHEIA ═══════════════\n\n"); 303 | 304 | if (pilhaCheia(pilha)) { 305 | printf("✅ A pilha está CHEIA!\n"); 306 | printf("📊 Produtos na pilha: %d/%d\n", MAX_ELEMENTOS, MAX_ELEMENTOS); 307 | printf("💡 Dica: Use a opção 3 para desempilhar produtos.\n"); 308 | } else { 309 | printf("❌ A pilha NÃO está cheia!\n"); 310 | printf("📊 Produtos na pilha: %d/%d\n", tamanho(pilha), MAX_ELEMENTOS); 311 | printf("📊 Espaços livres: %d\n", MAX_ELEMENTOS - tamanho(pilha)); 312 | printf("💡 Dica: Use a opção 2 para empilhar mais produtos.\n"); 313 | } 314 | 315 | pausar(); 316 | } 317 | 318 | void menuConsultarTamanho(PilhaEstatica *pilha) { 319 | limparTela(); 320 | exibirCabecalho(pilha); 321 | 322 | printf("═══════════════ CONSULTAR TAMANHO ═══════════════\n\n"); 323 | 324 | int total = tamanho(pilha); 325 | int livres = MAX_ELEMENTOS - total; 326 | float percentual = (float)total / MAX_ELEMENTOS * 100; 327 | 328 | printf("📊 ESTATÍSTICAS DA PILHA:\n"); 329 | printf("┌─────────────────────────────────────────────────────┐\n"); 330 | printf("│ Total de produtos: %-6d │\n", total); 331 | printf("│ Capacidade máxima: %-6d │\n", MAX_ELEMENTOS); 332 | printf("│ Espaços livres: %-6d │\n", livres); 333 | printf("│ Percentual usado: %.1f%% │\n", percentual); 334 | printf("│ Índice do topo: %-6d │\n", pilha->topo); 335 | printf("└─────────────────────────────────────────────────────┘\n"); 336 | 337 | printf("\n📈 REPRESENTAÇÃO VISUAL:\n"); 338 | printf("Pilha: ["); 339 | for (int i = 0; i < MAX_ELEMENTOS; i++) { 340 | if (i <= pilha->topo) { 341 | printf("█"); 342 | } else { 343 | printf("░"); 344 | } 345 | } 346 | printf("] %.1f%%\n", percentual); 347 | 348 | pausar(); 349 | } 350 | 351 | // ========== FUNÇÃO PRINCIPAL ========== 352 | 353 | int main() { 354 | PilhaEstatica pilha; 355 | int opcao; 356 | 357 | inicializarPilha(&pilha); 358 | 359 | do { 360 | exibirMenu(&pilha, &opcao); 361 | 362 | switch (opcao) { 363 | case 1: 364 | menuExibirPilha(&pilha); 365 | break; 366 | case 2: 367 | menuPush(&pilha); 368 | break; 369 | case 3: 370 | menuPop(&pilha); 371 | break; 372 | case 4: 373 | menuConsultarTopo(&pilha); 374 | break; 375 | case 5: 376 | menuVerificarVazia(&pilha); 377 | break; 378 | case 6: 379 | menuVerificarCheia(&pilha); 380 | break; 381 | case 7: 382 | menuConsultarTamanho(&pilha); 383 | break; 384 | case 0: 385 | limparTela(); 386 | printf("╔══════════════════════════════════════╗\n"); 387 | printf("║ PROGRAMA FINALIZADO! ║\n"); 388 | printf("║ ║\n"); 389 | printf("║ Obrigado por usar o sistema de ║\n"); 390 | printf("║ Pilha Estática! 🚀 ║\n"); 391 | printf("╚══════════════════════════════════════╝\n"); 392 | break; 393 | default: 394 | limparTela(); 395 | printf("❌ Opção inválida! Tente novamente.\n"); 396 | pausar(); 397 | break; 398 | } 399 | } while (opcao != 0); 400 | 401 | return 0; 402 | } -------------------------------------------------------------------------------- /listas/encadeada/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct { 6 | int numCamisa; 7 | char nome[50]; 8 | } Jogador; 9 | 10 | typedef struct celula { 11 | Jogador info; 12 | struct celula *prox; 13 | } Celula; 14 | 15 | void limparBuffer() 16 | { 17 | int c; 18 | while ((c = getchar()) != '\n' && c != EOF) 19 | ; 20 | } 21 | 22 | void removerQuebraLinha(char *str) { 23 | str[strcspn(str, "\n")] = 0; 24 | } 25 | 26 | void inicializarLista(Celula **lista) { 27 | (*lista) = NULL; 28 | } 29 | 30 | int listaVazia(Celula **lista) { 31 | if ((*lista) == NULL) 32 | return 1; 33 | 34 | return 0; 35 | } 36 | 37 | // FUNÇÕES AUXILIARES PARA INTERFACE 38 | void limparTela() { 39 | #ifdef _WIN32 40 | system("cls"); 41 | #else 42 | system("clear"); 43 | #endif 44 | } 45 | 46 | void pausar() { 47 | printf("\nPressione ENTER para continuar..."); 48 | limparBuffer(); 49 | getchar(); 50 | } 51 | 52 | int contarElementos(Celula **lista) { 53 | if (listaVazia(lista)) { 54 | return 0; 55 | } 56 | 57 | Celula *aux = (*lista); 58 | int contador = 0; 59 | 60 | while (aux != NULL) { 61 | contador++; 62 | aux = aux->prox; 63 | } 64 | 65 | return contador; 66 | } 67 | 68 | void exibirCabecalho(Celula **lista) { 69 | int total = contarElementos(lista); 70 | char status[20]; 71 | 72 | if (listaVazia(lista)) { 73 | strcpy(status, "VAZIA"); 74 | } else { 75 | strcpy(status, "COM DADOS"); 76 | } 77 | 78 | printf("╔══════════════════════════════════════╗\n"); 79 | printf("║ LISTA ENCADEADA ║\n"); 80 | printf("║ Sistema de Jogadores ║\n"); 81 | printf("╠══════════════════════════════════════╣\n"); 82 | printf("║ Status: %-8s | Jogadores: %d ║\n", status, total); 83 | printf("╚══════════════════════════════════════╝\n\n"); 84 | } 85 | 86 | Celula * criarCelula() { 87 | Celula *nova = (Celula*) malloc(sizeof(Celula)); 88 | return nova; 89 | } 90 | 91 | int inserirFim(Celula **lista, Jogador elemento) { 92 | Celula *novaCelula; 93 | Celula *aux; 94 | 95 | novaCelula = criarCelula(); 96 | 97 | if (novaCelula == NULL) { 98 | return 0; 99 | } 100 | 101 | novaCelula->info = elemento; 102 | novaCelula->prox = NULL; 103 | 104 | if (listaVazia(lista)) { 105 | (*lista) = novaCelula; 106 | return 1; 107 | } 108 | 109 | aux = (*lista); 110 | while(aux->prox != NULL) { 111 | aux = aux->prox; 112 | } 113 | 114 | aux->prox = novaCelula; 115 | 116 | return 1; 117 | } 118 | 119 | int inserirInicio(Celula **lista, Jogador elemento) { 120 | Celula *novaCelula = criarCelula(); 121 | 122 | if (novaCelula == NULL) 123 | return 0; 124 | 125 | if(listaVazia(lista)) 126 | return inserirFim(lista, elemento); 127 | 128 | novaCelula->info = elemento; 129 | novaCelula->prox = (*lista); 130 | 131 | (*lista) = novaCelula; 132 | 133 | return 1; 134 | } 135 | 136 | void exibirElementos(Celula **lista) { 137 | if (listaVazia(lista)) { 138 | printf("Lista vazia!\n"); 139 | return; 140 | } 141 | 142 | Celula *aux = (*lista); 143 | 144 | while (aux != NULL) { 145 | printf( 146 | "%d - %s\n", 147 | aux->info.numCamisa, 148 | aux->info.nome 149 | ); 150 | 151 | aux = aux->prox; 152 | } 153 | } 154 | 155 | Jogador criarElemento(int numCamisa, char nome[]) { 156 | Jogador elemento; 157 | 158 | strcpy(elemento.nome, nome); 159 | elemento.numCamisa = numCamisa; 160 | 161 | return elemento; 162 | } 163 | 164 | Jogador removerInicio(Celula **lista) { 165 | Celula *removida; 166 | Jogador removido = criarElemento(-1, ""); 167 | 168 | if(listaVazia(lista)) { 169 | return removido; 170 | } 171 | 172 | removida = (*lista); 173 | removido = removida->info; 174 | 175 | (*lista) = (*lista)->prox; 176 | 177 | free(removida); 178 | 179 | return removido; 180 | } 181 | 182 | Jogador removerFim(Celula **lista) { 183 | Celula *removida; 184 | Celula *anterior; 185 | Jogador removido = criarElemento(-1, ""); 186 | 187 | if(listaVazia(lista)) { 188 | return removido; 189 | } 190 | 191 | if((*lista)->prox == NULL) { 192 | return removerInicio(lista); 193 | } 194 | 195 | removida = (*lista); 196 | while(removida->prox != NULL) { 197 | anterior = removida; 198 | removida = removida->prox; 199 | } 200 | 201 | removido = removida->info; 202 | anterior->prox = NULL; 203 | 204 | free(removida); 205 | 206 | return removido; 207 | } 208 | 209 | int compararElemento(Jogador j1, Jogador j2) { 210 | return strcmp(j1.nome, j2.nome); 211 | } 212 | 213 | Celula * pesquisar(Celula **lista, Jogador pesquisado) { 214 | Celula *aux; 215 | 216 | if(listaVazia(lista)) { 217 | return NULL; 218 | } 219 | 220 | aux = (*lista); 221 | while(aux != NULL) { 222 | if (compararElemento(aux->info, pesquisado) == 0) { 223 | return aux; 224 | } 225 | 226 | aux = aux->prox; 227 | } 228 | 229 | return NULL; 230 | } 231 | 232 | Jogador removerElemento(Celula **lista, Jogador elemento) { 233 | Celula *removida; 234 | Celula *anterior; 235 | Jogador removido = criarElemento(-1, ""); 236 | 237 | if(listaVazia(lista)) { 238 | return removido; 239 | } 240 | 241 | removida = pesquisar(lista, elemento); 242 | if(removida == NULL) { 243 | return removido; 244 | } 245 | 246 | if(removida == (*lista)) { 247 | return removerInicio(lista); 248 | } 249 | 250 | removido = removida->info; 251 | 252 | anterior = (*lista); 253 | while(anterior->prox != removida) { 254 | anterior = anterior->prox; 255 | } 256 | 257 | anterior->prox = removida->prox; 258 | 259 | free(removida); 260 | 261 | return removido; 262 | } 263 | 264 | // FUNÇÕES UTILIZADAS PELO MENU 265 | void exibirMenu(Celula **lista, int *opcao) 266 | { 267 | limparTela(); 268 | exibirCabecalho(lista); 269 | 270 | printf("┌──────────────────────────────────────┐\n"); 271 | printf("│ MENU │\n"); 272 | printf("├──────────────────────────────────────┤\n"); 273 | printf("│ 1 - Exibir elementos │\n"); 274 | printf("│ 2 - Inserir no inicio │\n"); 275 | printf("│ 3 - Inserir no fim │\n"); 276 | printf("│ 4 - Remover do inicio │\n"); 277 | printf("│ 5 - Remover do fim │\n"); 278 | printf("│ 6 - Pesquisar elemento │\n"); 279 | printf("│ 7 - Remover elemento especifico │\n"); 280 | printf("│ 0 - Sair │\n"); 281 | printf("└──────────────────────────────────────┘\n\n"); 282 | printf("Escolha uma opcao: "); 283 | scanf("%d", opcao); 284 | } 285 | 286 | void menuExibirElementos(Celula **lista) { 287 | limparTela(); 288 | printf("╔══════════════════════════════════════╗\n"); 289 | printf("║ LISTA DE JOGADORES ║\n"); 290 | printf("╚══════════════════════════════════════╝\n\n"); 291 | 292 | if (listaVazia(lista)) { 293 | printf("Lista vazia! Nenhum jogador cadastrado.\n"); 294 | } else { 295 | printf("┌─────────────┬────────────────────────┐\n"); 296 | printf("│ Num. Camisa │ Nome │\n"); 297 | printf("├─────────────┼────────────────────────┤\n"); 298 | 299 | Celula *aux = (*lista); 300 | while (aux != NULL) { 301 | printf("│ %11d │ %-22s │\n", aux->info.numCamisa, aux->info.nome); 302 | aux = aux->prox; 303 | } 304 | printf("└─────────────┴────────────────────────┘\n"); 305 | printf("\nTotal de jogadores: %d\n", contarElementos(lista)); 306 | } 307 | 308 | pausar(); 309 | } 310 | 311 | void menuInserirInicio(Celula **lista) 312 | { 313 | int sucesso; 314 | Jogador novoJogador; 315 | 316 | limparTela(); 317 | printf("╔══════════════════════════════════════╗\n"); 318 | printf("║ INSERIR NO INICIO ║\n"); 319 | printf("╚══════════════════════════════════════╝\n\n"); 320 | 321 | printf("Digite o numero da camisa: "); 322 | scanf("%d", &novoJogador.numCamisa); 323 | 324 | limparBuffer(); 325 | 326 | printf("Digite o nome do jogador: "); 327 | fgets(novoJogador.nome, 50, stdin); 328 | 329 | removerQuebraLinha(novoJogador.nome); 330 | 331 | sucesso = inserirInicio(lista, novoJogador); 332 | 333 | printf("\n"); 334 | if (sucesso) 335 | printf("Jogador inserido com sucesso!\n"); 336 | else 337 | printf("Erro ao inserir jogador!\n"); 338 | 339 | pausar(); 340 | } 341 | 342 | void menuInserirFim(Celula **lista) 343 | { 344 | int sucesso; 345 | Jogador novoJogador; 346 | 347 | limparTela(); 348 | printf("╔══════════════════════════════════════╗\n"); 349 | printf("║ INSERIR NO FIM ║\n"); 350 | printf("╚══════════════════════════════════════╝\n\n"); 351 | 352 | printf("Digite o numero da camisa: "); 353 | scanf("%d", &novoJogador.numCamisa); 354 | 355 | limparBuffer(); 356 | 357 | printf("Digite o nome do jogador: "); 358 | fgets(novoJogador.nome, 50, stdin); 359 | 360 | removerQuebraLinha(novoJogador.nome); 361 | 362 | sucesso = inserirFim(lista, novoJogador); 363 | 364 | printf("\n"); 365 | if (sucesso) 366 | printf("Jogador inserido com sucesso!\n"); 367 | else 368 | printf("Erro ao inserir jogador!\n"); 369 | 370 | pausar(); 371 | } 372 | 373 | void menuRemoverInicio(Celula **lista) { 374 | Jogador removido; 375 | 376 | limparTela(); 377 | printf("╔══════════════════════════════════════╗\n"); 378 | printf("║ REMOVER DO INICIO ║\n"); 379 | printf("╚══════════════════════════════════════╝\n\n"); 380 | 381 | if (listaVazia(lista)) { 382 | printf("Lista vazia! Nada para remover.\n"); 383 | pausar(); 384 | return; 385 | } 386 | 387 | removido = removerInicio(lista); 388 | 389 | printf("\n"); 390 | if (removido.numCamisa != -1) 391 | printf("Jogador removido: %d - %s\n", removido.numCamisa, removido.nome); 392 | else 393 | printf("Erro ao remover jogador!\n"); 394 | 395 | pausar(); 396 | } 397 | 398 | void menuRemoverFim(Celula **lista) { 399 | Jogador removido; 400 | 401 | limparTela(); 402 | printf("╔══════════════════════════════════════╗\n"); 403 | printf("║ REMOVER DO FIM ║\n"); 404 | printf("╚══════════════════════════════════════╝\n\n"); 405 | 406 | if (listaVazia(lista)) { 407 | printf("Lista vazia! Nada para remover.\n"); 408 | pausar(); 409 | return; 410 | } 411 | 412 | removido = removerFim(lista); 413 | 414 | printf("\n"); 415 | if (removido.numCamisa != -1) 416 | printf("Jogador removido: %d - %s\n", removido.numCamisa, removido.nome); 417 | else 418 | printf("Erro ao remover jogador!\n"); 419 | 420 | pausar(); 421 | } 422 | 423 | void menuPesquisarElemento(Celula **lista) { 424 | char nome[50]; 425 | Jogador pesquisado; 426 | Celula *encontrado; 427 | 428 | limparTela(); 429 | printf("╔══════════════════════════════════════╗\n"); 430 | printf("║ PESQUISAR ELEMENTO ║\n"); 431 | printf("╚══════════════════════════════════════╝\n\n"); 432 | 433 | if (listaVazia(lista)) { 434 | printf("Lista vazia! Nada para pesquisar.\n"); 435 | pausar(); 436 | return; 437 | } 438 | 439 | limparBuffer(); 440 | printf("Digite o nome para pesquisar: "); 441 | fgets(nome, 50, stdin); 442 | removerQuebraLinha(nome); 443 | 444 | pesquisado = criarElemento(0, nome); 445 | encontrado = pesquisar(lista, pesquisado); 446 | 447 | printf("\n"); 448 | if (encontrado != NULL) { 449 | printf("Elemento encontrado!\n"); 450 | printf("┌─────────────┬────────────────────────┐\n"); 451 | printf("│ Num. Camisa │ %-22d │\n", encontrado->info.numCamisa); 452 | printf("│ Nome │ %-22s │\n", encontrado->info.nome); 453 | printf("└─────────────┴────────────────────────┘\n"); 454 | } else { 455 | printf("Elemento nao encontrado!\n"); 456 | } 457 | 458 | pausar(); 459 | } 460 | 461 | void menuRemoverElemento(Celula **lista) { 462 | char nome[50]; 463 | Jogador pesquisado, removido; 464 | 465 | limparTela(); 466 | printf("╔══════════════════════════════════════╗\n"); 467 | printf("║ REMOVER ELEMENTO ESPECIFICO ║\n"); 468 | printf("╚══════════════════════════════════════╝\n\n"); 469 | 470 | if (listaVazia(lista)) { 471 | printf("Lista vazia! Nada para remover.\n"); 472 | pausar(); 473 | return; 474 | } 475 | 476 | limparBuffer(); 477 | printf("Digite o nome do jogador a remover: "); 478 | fgets(nome, 50, stdin); 479 | removerQuebraLinha(nome); 480 | 481 | pesquisado = criarElemento(0, nome); 482 | removido = removerElemento(lista, pesquisado); 483 | 484 | printf("\n"); 485 | if (removido.numCamisa != -1) 486 | printf("Jogador removido: %d - %s\n", removido.numCamisa, removido.nome); 487 | else 488 | printf("Jogador nao encontrado!\n"); 489 | 490 | pausar(); 491 | } 492 | 493 | int main() { 494 | Celula *lista; 495 | int opcao; 496 | 497 | inicializarLista(&lista); 498 | 499 | do 500 | { 501 | exibirMenu(&lista, &opcao); 502 | 503 | switch (opcao) 504 | { 505 | case 1: 506 | menuExibirElementos(&lista); 507 | break; 508 | 509 | case 2: 510 | menuInserirInicio(&lista); 511 | break; 512 | 513 | case 3: 514 | menuInserirFim(&lista); 515 | break; 516 | 517 | case 4: 518 | menuRemoverInicio(&lista); 519 | break; 520 | 521 | case 5: 522 | menuRemoverFim(&lista); 523 | break; 524 | 525 | case 6: 526 | menuPesquisarElemento(&lista); 527 | break; 528 | 529 | case 7: 530 | menuRemoverElemento(&lista); 531 | break; 532 | 533 | case 0: 534 | limparTela(); 535 | printf("╔══════════════════════════════════════╗\n"); 536 | printf("║ ATE A PROXIMA! ║\n"); 537 | printf("║ ║\n"); 538 | printf("║ Obrigado por usar o sistema! ║\n"); 539 | printf("╚══════════════════════════════════════╝\n\n"); 540 | break; 541 | 542 | default: 543 | limparTela(); 544 | printf("╔══════════════════════════════════════╗\n"); 545 | printf("║ OPCAO INVALIDA! ║\n"); 546 | printf("╚══════════════════════════════════════╝\n\n"); 547 | printf("Por favor, escolha uma opcao valida (0-7).\n"); 548 | pausar(); 549 | break; 550 | } 551 | } while (opcao != 0); 552 | 553 | return 0; 554 | } 555 | -------------------------------------------------------------------------------- /deques/estatico/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_ELEMENTOS 6 6 | 7 | typedef struct 8 | { 9 | int codigo; 10 | char nome[60]; 11 | } Cliente; 12 | 13 | typedef struct 14 | { 15 | Cliente elementos[MAX_ELEMENTOS]; 16 | int inicio; 17 | int fim; 18 | int tamanho; 19 | } DequeEstatico; 20 | 21 | void limparBuffer() 22 | { 23 | int c; 24 | while ((c = getchar()) != '\n' && c != EOF) 25 | ; 26 | } 27 | 28 | void removerQuebraLinha(char *str) { 29 | str[strcspn(str, "\n")] = 0; 30 | } 31 | 32 | // FUNÇÕES DO DEQUE ESTÁTICO 33 | void inicializarDeque(DequeEstatico *deque) 34 | { 35 | deque->inicio = 0; 36 | deque->fim = -1; 37 | deque->tamanho = 0; 38 | } 39 | 40 | int dequeVazio(DequeEstatico *deque) 41 | { 42 | return deque->tamanho == 0; 43 | } 44 | 45 | int dequeCheio(DequeEstatico *deque) 46 | { 47 | return deque->tamanho == MAX_ELEMENTOS; 48 | } 49 | 50 | // FUNÇÕES AUXILIARES PARA INTERFACE 51 | void limparTela() { 52 | #ifdef _WIN32 53 | system("cls"); 54 | #else 55 | system("clear"); 56 | #endif 57 | } 58 | 59 | void pausar() { 60 | printf("\nPressione ENTER para continuar..."); 61 | limparBuffer(); 62 | getchar(); 63 | } 64 | 65 | void exibirCabecalho(DequeEstatico *deque) { 66 | int total = deque->tamanho; 67 | char status[20]; 68 | 69 | if (dequeVazio(deque)) { 70 | strcpy(status, "VAZIO"); 71 | } else if (dequeCheio(deque)) { 72 | strcpy(status, "CHEIO"); 73 | } else { 74 | strcpy(status, "PARCIAL"); 75 | } 76 | 77 | printf("╔══════════════════════════════════════╗\n"); 78 | printf("║ DEQUE ESTATICO ║\n"); 79 | printf("║ Sistema de Clientes ║\n"); 80 | printf("╠══════════════════════════════════════╣\n"); 81 | printf("║ Status: %-8s | Clientes: %d/%d ║\n", status, total, MAX_ELEMENTOS); 82 | printf("╚══════════════════════════════════════╝\n\n"); 83 | } 84 | 85 | int inserirInicio(DequeEstatico *deque, Cliente elemento) 86 | { 87 | if (dequeCheio(deque)) 88 | return 0; 89 | 90 | deque->inicio = (deque->inicio - 1 + MAX_ELEMENTOS) % MAX_ELEMENTOS; 91 | deque->elementos[deque->inicio] = elemento; 92 | deque->tamanho++; 93 | 94 | return 1; 95 | } 96 | 97 | int inserirFim(DequeEstatico *deque, Cliente elemento) 98 | { 99 | if (dequeCheio(deque)) 100 | return 0; 101 | 102 | deque->fim = (deque->fim + 1) % MAX_ELEMENTOS; 103 | deque->elementos[deque->fim] = elemento; 104 | deque->tamanho++; 105 | 106 | return 1; 107 | } 108 | 109 | Cliente removerInicio(DequeEstatico *deque) 110 | { 111 | Cliente vazio = {-1, ""}; 112 | 113 | if (dequeVazio(deque)) 114 | return vazio; 115 | 116 | Cliente removido = deque->elementos[deque->inicio]; 117 | deque->inicio = (deque->inicio + 1) % MAX_ELEMENTOS; 118 | deque->tamanho--; 119 | 120 | return removido; 121 | } 122 | 123 | Cliente removerFim(DequeEstatico *deque) 124 | { 125 | Cliente vazio = {-1, ""}; 126 | 127 | if (dequeVazio(deque)) 128 | return vazio; 129 | 130 | Cliente removido = deque->elementos[deque->fim]; 131 | deque->fim = (deque->fim - 1 + MAX_ELEMENTOS) % MAX_ELEMENTOS; 132 | deque->tamanho--; 133 | 134 | return removido; 135 | } 136 | 137 | Cliente consultarInicio(DequeEstatico *deque) 138 | { 139 | Cliente vazio = {-1, ""}; 140 | 141 | if (dequeVazio(deque)) 142 | return vazio; 143 | 144 | return deque->elementos[deque->inicio]; 145 | } 146 | 147 | Cliente consultarFim(DequeEstatico *deque) 148 | { 149 | Cliente vazio = {-1, ""}; 150 | 151 | if (dequeVazio(deque)) 152 | return vazio; 153 | 154 | return deque->elementos[deque->fim]; 155 | } 156 | 157 | // FUNÇÕES UTILIZADAS PELO MENU 158 | void exibirMenu(DequeEstatico *deque, int *opcao) 159 | { 160 | limparTela(); 161 | exibirCabecalho(deque); 162 | 163 | printf("┌──────────────────────────────────────┐\n"); 164 | printf("│ MENU │\n"); 165 | printf("├──────────────────────────────────────┤\n"); 166 | printf("│ 1 - Exibir deque │\n"); 167 | printf("│ 2 - Inserir no inicio │\n"); 168 | printf("│ 3 - Inserir no fim │\n"); 169 | printf("│ 4 - Remover do inicio │\n"); 170 | printf("│ 5 - Remover do fim │\n"); 171 | printf("│ 6 - Consultar inicio │\n"); 172 | printf("│ 7 - Consultar fim │\n"); 173 | printf("│ 8 - Limpar deque │\n"); 174 | printf("│ 0 - Sair │\n"); 175 | printf("└──────────────────────────────────────┘\n\n"); 176 | printf("Escolha uma opcao: "); 177 | scanf("%d", opcao); 178 | } 179 | 180 | void menuExibirDeque(DequeEstatico *deque) { 181 | limparTela(); 182 | printf("╔══════════════════════════════════════╗\n"); 183 | printf("║ DEQUE DE CLIENTES ║\n"); 184 | printf("╚══════════════════════════════════════╝\n\n"); 185 | 186 | if (dequeVazio(deque)) { 187 | printf("Deque vazio! Nenhum cliente no deque.\n"); 188 | } else { 189 | printf("┌─────────┬─────────┬──────────────────────┐\n"); 190 | printf("│ Posicao │ Codigo │ Nome │\n"); 191 | printf("├─────────┼─────────┼──────────────────────┤\n"); 192 | 193 | int atual = deque->inicio; 194 | for (int i = 0; i < deque->tamanho; i++) { 195 | int posicao = i + 1; 196 | char indicador[10] = ""; 197 | 198 | if (i == 0 && i == deque->tamanho - 1) { 199 | strcpy(indicador, " (I/F)"); 200 | } else if (i == 0) { 201 | strcpy(indicador, " (I)"); 202 | } else if (i == deque->tamanho - 1) { 203 | strcpy(indicador, " (F)"); 204 | } 205 | 206 | printf("│ %5d%s │ %7d │ %-20s │\n", posicao, indicador, 207 | deque->elementos[atual].codigo, 208 | deque->elementos[atual].nome); 209 | atual = (atual + 1) % MAX_ELEMENTOS; 210 | } 211 | printf("└─────────┴─────────┴──────────────────────┘\n"); 212 | printf("\nTotal no deque: %d/%d clientes\n", deque->tamanho, MAX_ELEMENTOS); 213 | printf("Legenda: (I) = Inicio, (F) = Fim\n"); 214 | 215 | if (deque->tamanho > 0) { 216 | printf("\nExtremos do deque:\n"); 217 | printf("- Inicio: %d - %s\n", 218 | deque->elementos[deque->inicio].codigo, 219 | deque->elementos[deque->inicio].nome); 220 | printf("- Fim: %d - %s\n", 221 | deque->elementos[deque->fim].codigo, 222 | deque->elementos[deque->fim].nome); 223 | } 224 | } 225 | 226 | pausar(); 227 | } 228 | 229 | void menuInserirInicio(DequeEstatico *deque) 230 | { 231 | int sucesso; 232 | Cliente novoCliente; 233 | 234 | limparTela(); 235 | printf("╔══════════════════════════════════════╗\n"); 236 | printf("║ INSERIR NO INICIO ║\n"); 237 | printf("╚══════════════════════════════════════╝\n\n"); 238 | 239 | if (dequeCheio(deque)) { 240 | printf("Deque cheio! Nao e possivel inserir novos clientes.\n"); 241 | pausar(); 242 | return; 243 | } 244 | 245 | printf("Digite o codigo do cliente: "); 246 | scanf("%d", &novoCliente.codigo); 247 | 248 | limparBuffer(); 249 | 250 | printf("Digite o nome do cliente: "); 251 | fgets(novoCliente.nome, 60, stdin); 252 | 253 | removerQuebraLinha(novoCliente.nome); 254 | 255 | sucesso = inserirInicio(deque, novoCliente); 256 | 257 | printf("\n"); 258 | if (sucesso) 259 | printf("Cliente inserido no INICIO do deque com sucesso!\n"); 260 | else 261 | printf("Erro ao inserir cliente no deque!\n"); 262 | 263 | pausar(); 264 | } 265 | 266 | void menuInserirFim(DequeEstatico *deque) 267 | { 268 | int sucesso; 269 | Cliente novoCliente; 270 | 271 | limparTela(); 272 | printf("╔══════════════════════════════════════╗\n"); 273 | printf("║ INSERIR NO FIM ║\n"); 274 | printf("╚══════════════════════════════════════╝\n\n"); 275 | 276 | if (dequeCheio(deque)) { 277 | printf("Deque cheio! Nao e possivel inserir novos clientes.\n"); 278 | pausar(); 279 | return; 280 | } 281 | 282 | printf("Digite o codigo do cliente: "); 283 | scanf("%d", &novoCliente.codigo); 284 | 285 | limparBuffer(); 286 | 287 | printf("Digite o nome do cliente: "); 288 | fgets(novoCliente.nome, 60, stdin); 289 | 290 | removerQuebraLinha(novoCliente.nome); 291 | 292 | sucesso = inserirFim(deque, novoCliente); 293 | 294 | printf("\n"); 295 | if (sucesso) 296 | printf("Cliente inserido no FIM do deque com sucesso!\n"); 297 | else 298 | printf("Erro ao inserir cliente no deque!\n"); 299 | 300 | pausar(); 301 | } 302 | 303 | void menuRemoverInicio(DequeEstatico *deque) { 304 | Cliente removido; 305 | 306 | limparTela(); 307 | printf("╔══════════════════════════════════════╗\n"); 308 | printf("║ REMOVER DO INICIO ║\n"); 309 | printf("╚══════════════════════════════════════╝\n\n"); 310 | 311 | if (dequeVazio(deque)) { 312 | printf("Deque vazio! Nada para remover.\n"); 313 | pausar(); 314 | return; 315 | } 316 | 317 | printf("Cliente a ser removido do INICIO:\n"); 318 | printf("Codigo: %d - %s\n\n", deque->elementos[deque->inicio].codigo, 319 | deque->elementos[deque->inicio].nome); 320 | 321 | removido = removerInicio(deque); 322 | 323 | printf("Cliente removido do inicio: %d - %s\n", removido.codigo, removido.nome); 324 | 325 | if (!dequeVazio(deque)) { 326 | printf("Novo primeiro cliente: %d - %s\n", 327 | deque->elementos[deque->inicio].codigo, 328 | deque->elementos[deque->inicio].nome); 329 | } else { 330 | printf("Deque agora esta vazio.\n"); 331 | } 332 | 333 | pausar(); 334 | } 335 | 336 | void menuRemoverFim(DequeEstatico *deque) { 337 | Cliente removido; 338 | 339 | limparTela(); 340 | printf("╔══════════════════════════════════════╗\n"); 341 | printf("║ REMOVER DO FIM ║\n"); 342 | printf("╚══════════════════════════════════════╝\n\n"); 343 | 344 | if (dequeVazio(deque)) { 345 | printf("Deque vazio! Nada para remover.\n"); 346 | pausar(); 347 | return; 348 | } 349 | 350 | printf("Cliente a ser removido do FIM:\n"); 351 | printf("Codigo: %d - %s\n\n", deque->elementos[deque->fim].codigo, 352 | deque->elementos[deque->fim].nome); 353 | 354 | removido = removerFim(deque); 355 | 356 | printf("Cliente removido do fim: %d - %s\n", removido.codigo, removido.nome); 357 | 358 | if (!dequeVazio(deque)) { 359 | printf("Novo ultimo cliente: %d - %s\n", 360 | deque->elementos[deque->fim].codigo, 361 | deque->elementos[deque->fim].nome); 362 | } else { 363 | printf("Deque agora esta vazio.\n"); 364 | } 365 | 366 | pausar(); 367 | } 368 | 369 | void menuConsultarInicio(DequeEstatico *deque) { 370 | Cliente primeiro; 371 | 372 | limparTela(); 373 | printf("╔══════════════════════════════════════╗\n"); 374 | printf("║ CONSULTAR INICIO ║\n"); 375 | printf("╚══════════════════════════════════════╝\n\n"); 376 | 377 | if (dequeVazio(deque)) { 378 | printf("Deque vazio! Nenhum cliente para consultar.\n"); 379 | pausar(); 380 | return; 381 | } 382 | 383 | primeiro = consultarInicio(deque); 384 | 385 | printf("Primeiro cliente do deque (INICIO):\n"); 386 | printf("┌─────────────┬──────────────────────────┐\n"); 387 | printf("│ Codigo │ %-24d │\n", primeiro.codigo); 388 | printf("│ Nome │ %-24s │\n", primeiro.nome); 389 | printf("│ Posicao │ Inicio do deque │\n"); 390 | printf("└─────────────┴──────────────────────────┘\n"); 391 | 392 | pausar(); 393 | } 394 | 395 | void menuConsultarFim(DequeEstatico *deque) { 396 | Cliente ultimo; 397 | 398 | limparTela(); 399 | printf("╔══════════════════════════════════════╗\n"); 400 | printf("║ CONSULTAR FIM ║\n"); 401 | printf("╚══════════════════════════════════════╝\n\n"); 402 | 403 | if (dequeVazio(deque)) { 404 | printf("Deque vazio! Nenhum cliente para consultar.\n"); 405 | pausar(); 406 | return; 407 | } 408 | 409 | ultimo = consultarFim(deque); 410 | 411 | printf("Ultimo cliente do deque (FIM):\n"); 412 | printf("┌─────────────┬──────────────────────────┐\n"); 413 | printf("│ Codigo │ %-24d │\n", ultimo.codigo); 414 | printf("│ Nome │ %-24s │\n", ultimo.nome); 415 | printf("│ Posicao │ Fim do deque │\n"); 416 | printf("└─────────────┴──────────────────────────┘\n"); 417 | 418 | pausar(); 419 | } 420 | 421 | void menuLimparDeque(DequeEstatico *deque) { 422 | char confirmacao; 423 | 424 | limparTela(); 425 | printf("╔══════════════════════════════════════╗\n"); 426 | printf("║ LIMPAR DEQUE ║\n"); 427 | printf("╚══════════════════════════════════════╝\n\n"); 428 | 429 | if (dequeVazio(deque)) { 430 | printf("Deque ja esta vazio!\n"); 431 | pausar(); 432 | return; 433 | } 434 | 435 | printf("ATENCAO: Esta operacao ira remover TODOS os clientes do deque!\n"); 436 | printf("Clientes no deque: %d\n\n", deque->tamanho); 437 | 438 | printf("Tem certeza? (s/N): "); 439 | limparBuffer(); 440 | scanf("%c", &confirmacao); 441 | 442 | if (confirmacao == 's' || confirmacao == 'S') { 443 | inicializarDeque(deque); 444 | printf("\nDeque limpo com sucesso! Todos os clientes foram removidos.\n"); 445 | } else { 446 | printf("\nOperacao cancelada. Deque mantido inalterado.\n"); 447 | } 448 | 449 | pausar(); 450 | } 451 | 452 | int main() 453 | { 454 | DequeEstatico deque; 455 | int opcao; 456 | 457 | inicializarDeque(&deque); 458 | 459 | do 460 | { 461 | exibirMenu(&deque, &opcao); 462 | 463 | switch (opcao) 464 | { 465 | case 1: 466 | menuExibirDeque(&deque); 467 | break; 468 | 469 | case 2: 470 | menuInserirInicio(&deque); 471 | break; 472 | 473 | case 3: 474 | menuInserirFim(&deque); 475 | break; 476 | 477 | case 4: 478 | menuRemoverInicio(&deque); 479 | break; 480 | 481 | case 5: 482 | menuRemoverFim(&deque); 483 | break; 484 | 485 | case 6: 486 | menuConsultarInicio(&deque); 487 | break; 488 | 489 | case 7: 490 | menuConsultarFim(&deque); 491 | break; 492 | 493 | case 8: 494 | menuLimparDeque(&deque); 495 | break; 496 | 497 | case 0: 498 | limparTela(); 499 | printf("╔══════════════════════════════════════╗\n"); 500 | printf("║ ATE A PROXIMA! ║\n"); 501 | printf("║ ║\n"); 502 | printf("║ Obrigado por usar o sistema! ║\n"); 503 | printf("╚══════════════════════════════════════╝\n\n"); 504 | break; 505 | 506 | default: 507 | limparTela(); 508 | printf("╔══════════════════════════════════════╗\n"); 509 | printf("║ OPCAO INVALIDA! ║\n"); 510 | printf("╚══════════════════════════════════════╝\n\n"); 511 | printf("Por favor, escolha uma opcao valida (0-8).\n"); 512 | pausar(); 513 | break; 514 | } 515 | } while (opcao != 0); 516 | 517 | return 0; 518 | } -------------------------------------------------------------------------------- /pilhas/dinamica/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef _WIN32 6 | #include 7 | #else 8 | #include 9 | #endif 10 | 11 | // Estrutura que representa um livro 12 | typedef struct { 13 | int isbn; 14 | char titulo[100]; 15 | char autor[50]; 16 | int paginas; 17 | } Livro; 18 | 19 | // Estrutura que representa um nó da pilha 20 | typedef struct no { 21 | Livro info; 22 | struct no *proximo; 23 | } No; 24 | 25 | // ========== FUNÇÕES AUXILIARES ========== 26 | 27 | void limparBuffer() { 28 | int c; 29 | while ((c = getchar()) != '\n' && c != EOF); 30 | } 31 | 32 | void removerQuebraLinha(char *str) { 33 | str[strcspn(str, "\n")] = 0; 34 | } 35 | 36 | void limparTela() { 37 | #ifdef _WIN32 38 | system("cls"); 39 | #else 40 | system("clear"); 41 | #endif 42 | } 43 | 44 | void pausar() { 45 | printf("\nPressione ENTER para continuar..."); 46 | limparBuffer(); 47 | getchar(); 48 | } 49 | 50 | // ========== FUNÇÕES DA PILHA ========== 51 | 52 | void inicializarPilha(No **pilha) { 53 | *pilha = NULL; 54 | } 55 | 56 | int pilhaVazia(No **pilha) { 57 | return (*pilha == NULL); 58 | } 59 | 60 | int contarElementos(No **pilha) { 61 | if (pilhaVazia(pilha)) { 62 | return 0; 63 | } 64 | 65 | No *aux = *pilha; 66 | int contador = 0; 67 | 68 | while (aux != NULL) { 69 | contador++; 70 | aux = aux->proximo; 71 | } 72 | 73 | return contador; 74 | } 75 | 76 | void exibirCabecalho(No **pilha) { 77 | int tamanho = contarElementos(pilha); 78 | char status[20]; 79 | 80 | if (pilhaVazia(pilha)) { 81 | strcpy(status, "VAZIA"); 82 | } else { 83 | strcpy(status, "COM DADOS"); 84 | } 85 | 86 | printf("╔══════════════════════════════════════╗\n"); 87 | printf("║ PILHA DINÂMICA ║\n"); 88 | printf("║ Sistema de Livros ║\n"); 89 | printf("╠══════════════════════════════════════╣\n"); 90 | printf("║ Status: %-10s | Livros: %-6d ║\n", status, tamanho); 91 | printf("╚══════════════════════════════════════╝\n\n"); 92 | } 93 | 94 | No* criarNo(Livro elemento) { 95 | No *novo = (No*)malloc(sizeof(No)); 96 | if (novo == NULL) { 97 | printf("❌ ERRO: Memória insuficiente!\n"); 98 | return NULL; 99 | } 100 | 101 | novo->info = elemento; 102 | novo->proximo = NULL; 103 | return novo; 104 | } 105 | 106 | int push(No **pilha, Livro elemento) { 107 | No *novo = criarNo(elemento); 108 | if (novo == NULL) { 109 | return 0; // Falha na alocação 110 | } 111 | 112 | novo->proximo = *pilha; 113 | *pilha = novo; 114 | 115 | return 1; // Sucesso 116 | } 117 | 118 | Livro pop(No **pilha) { 119 | Livro livroVazio = {-1, "", "", 0}; 120 | 121 | if (pilhaVazia(pilha)) { 122 | return livroVazio; // Retorna livro inválido 123 | } 124 | 125 | No *removido = *pilha; 126 | Livro elemento = removido->info; 127 | 128 | *pilha = (*pilha)->proximo; 129 | free(removido); 130 | 131 | return elemento; 132 | } 133 | 134 | Livro top(No **pilha) { 135 | Livro livroVazio = {-1, "", "", 0}; 136 | 137 | if (pilhaVazia(pilha)) { 138 | return livroVazio; // Retorna livro inválido 139 | } 140 | 141 | return (*pilha)->info; 142 | } 143 | 144 | void exibirPilha(No **pilha) { 145 | if (pilhaVazia(pilha)) { 146 | printf("A pilha está vazia!\n"); 147 | return; 148 | } 149 | 150 | int tamanho = contarElementos(pilha); 151 | 152 | printf("PILHA DINÂMICA (Topo → Base):\n"); 153 | printf("┌────────────────────────────────────────────────────────────────────┐\n"); 154 | printf("│ Pos │ ISBN │ Título │ Autor │ Pág.│\n"); 155 | printf("├─────┼──────────┼────────────────────────────┼─────────────────┼─────┤\n"); 156 | 157 | No *atual = *pilha; 158 | int posicao = tamanho - 1; 159 | 160 | while (atual != NULL) { 161 | char simbolo = (atual == *pilha) ? '>' : '|'; 162 | printf("│ %c%2d │ %-8d │ %-26s │ %-15s │ %3d │\n", 163 | simbolo, 164 | posicao, 165 | atual->info.isbn, 166 | atual->info.titulo, 167 | atual->info.autor, 168 | atual->info.paginas); 169 | 170 | atual = atual->proximo; 171 | posicao--; 172 | } 173 | 174 | printf("└────────────────────────────────────────────────────────────────────┘\n"); 175 | printf("💡 Topo da pilha: [%d] elementos empilhados\n", tamanho); 176 | } 177 | 178 | void liberarPilha(No **pilha) { 179 | while (!pilhaVazia(pilha)) { 180 | pop(pilha); // Pop já faz o free() interno 181 | } 182 | printf("✅ Memória da pilha liberada com sucesso!\n"); 183 | } 184 | 185 | // ========== FUNÇÕES DO MENU ========== 186 | 187 | void exibirMenu(No **pilha, int *opcao) { 188 | limparTela(); 189 | exibirCabecalho(pilha); 190 | 191 | printf("┌──────────────────────────────────────┐\n"); 192 | printf("│ MENU │\n"); 193 | printf("├──────────────────────────────────────┤\n"); 194 | printf("│ 1 - Exibir pilha │\n"); 195 | printf("│ 2 - Empilhar (Push) │\n"); 196 | printf("│ 3 - Desempilhar (Pop) │\n"); 197 | printf("│ 4 - Consultar topo │\n"); 198 | printf("│ 5 - Verificar se está vazia │\n"); 199 | printf("│ 6 - Consultar tamanho │\n"); 200 | printf("│ 7 - Liberar pilha │\n"); 201 | printf("│ 0 - Sair │\n"); 202 | printf("└──────────────────────────────────────┘\n\n"); 203 | 204 | printf("Escolha uma opção: "); 205 | scanf("%d", opcao); 206 | limparBuffer(); 207 | } 208 | 209 | void menuExibirPilha(No **pilha) { 210 | limparTela(); 211 | exibirCabecalho(pilha); 212 | 213 | printf("═══════════════ VISUALIZAR PILHA ═══════════════\n\n"); 214 | exibirPilha(pilha); 215 | 216 | if (!pilhaVazia(pilha)) { 217 | printf("\n📊 Informações da Pilha:\n"); 218 | printf(" • Total de livros: %d\n", contarElementos(pilha)); 219 | printf(" • Memória utilizada: ~%lu bytes\n", contarElementos(pilha) * sizeof(No)); 220 | printf(" • Último livro empilhado: %s\n", (*pilha)->info.titulo); 221 | } 222 | 223 | pausar(); 224 | } 225 | 226 | void menuPush(No **pilha) { 227 | Livro novoLivro; 228 | int sucesso; 229 | 230 | limparTela(); 231 | exibirCabecalho(pilha); 232 | 233 | printf("═══════════════ EMPILHAR LIVRO ═══════════════\n\n"); 234 | 235 | printf("📚 Digite os dados do livro:\n\n"); 236 | 237 | printf("ISBN: "); 238 | scanf("%d", &novoLivro.isbn); 239 | limparBuffer(); 240 | 241 | printf("Título: "); 242 | fgets(novoLivro.titulo, sizeof(novoLivro.titulo), stdin); 243 | removerQuebraLinha(novoLivro.titulo); 244 | 245 | printf("Autor: "); 246 | fgets(novoLivro.autor, sizeof(novoLivro.autor), stdin); 247 | removerQuebraLinha(novoLivro.autor); 248 | 249 | printf("Páginas: "); 250 | scanf("%d", &novoLivro.paginas); 251 | limparBuffer(); 252 | 253 | sucesso = push(pilha, novoLivro); 254 | 255 | printf("\n"); 256 | if (sucesso) { 257 | printf("✅ Livro empilhado com sucesso!\n"); 258 | printf(" 📖 %s - %s\n", novoLivro.titulo, novoLivro.autor); 259 | printf(" 📊 Total na pilha: %d livros\n", contarElementos(pilha)); 260 | } else { 261 | printf("❌ Erro ao empilhar livro! Memória insuficiente.\n"); 262 | } 263 | 264 | pausar(); 265 | } 266 | 267 | void menuPop(No **pilha) { 268 | Livro removido; 269 | 270 | limparTela(); 271 | exibirCabecalho(pilha); 272 | 273 | printf("═══════════════ DESEMPILHAR LIVRO ═══════════════\n\n"); 274 | 275 | if (pilhaVazia(pilha)) { 276 | printf("❌ ERRO: Pilha vazia! Não há livros para desempilhar.\n"); 277 | printf("💡 Dica: Empilhe alguns livros primeiro.\n"); 278 | pausar(); 279 | return; 280 | } 281 | 282 | printf("📚 Livro no topo da pilha:\n"); 283 | removido = pop(pilha); 284 | 285 | if (removido.isbn != -1) { 286 | printf("\n✅ Livro desempilhado com sucesso!\n"); 287 | printf(" 📖 %s - %s\n", removido.titulo, removido.autor); 288 | printf(" 📊 Restam na pilha: %d livros\n", contarElementos(pilha)); 289 | 290 | if (!pilhaVazia(pilha)) { 291 | printf("\n🔝 Novo topo: %s\n", (*pilha)->info.titulo); 292 | } else { 293 | printf("\n📭 Pilha agora está vazia!\n"); 294 | } 295 | } else { 296 | printf("\n❌ Erro ao desempilhar livro!\n"); 297 | } 298 | 299 | pausar(); 300 | } 301 | 302 | void menuConsultarTopo(No **pilha) { 303 | Livro topo; 304 | 305 | limparTela(); 306 | exibirCabecalho(pilha); 307 | 308 | printf("═══════════════ CONSULTAR TOPO ═══════════════\n\n"); 309 | 310 | if (pilhaVazia(pilha)) { 311 | printf("❌ ERRO: Pilha vazia! Não há livros no topo.\n"); 312 | printf("💡 Dica: Empilhe alguns livros primeiro.\n"); 313 | pausar(); 314 | return; 315 | } 316 | 317 | topo = top(pilha); 318 | 319 | printf("🔝 LIVRO NO TOPO DA PILHA:\n"); 320 | printf("┌─────────────────────────────────────────────────────────────────┐\n"); 321 | printf("│ ISBN: %-10d │\n", topo.isbn); 322 | printf("│ Título: %-55s │\n", topo.titulo); 323 | printf("│ Autor: %-56s │\n", topo.autor); 324 | printf("│ Páginas: %-53d │\n", topo.paginas); 325 | printf("└─────────────────────────────────────────────────────────────────┘\n"); 326 | 327 | printf("\n📊 Informações da Pilha:\n"); 328 | printf(" • Total de livros: %d\n", contarElementos(pilha)); 329 | printf(" • Endereço do topo: %p\n", (void*)(*pilha)); 330 | printf(" • Próximo elemento: %p\n", (void*)(*pilha)->proximo); 331 | 332 | pausar(); 333 | } 334 | 335 | void menuVerificarVazia(No **pilha) { 336 | limparTela(); 337 | exibirCabecalho(pilha); 338 | 339 | printf("═══════════════ VERIFICAR SE ESTÁ VAZIA ═══════════════\n\n"); 340 | 341 | if (pilhaVazia(pilha)) { 342 | printf("✅ A pilha está VAZIA!\n"); 343 | printf("📊 Livros na pilha: 0\n"); 344 | printf("💾 Memória utilizada: 0 bytes\n"); 345 | printf("🎯 Ponteiro do topo: NULL\n"); 346 | printf("💡 Dica: Use a opção 2 para empilhar livros.\n"); 347 | } else { 348 | printf("❌ A pilha NÃO está vazia!\n"); 349 | printf("📊 Livros na pilha: %d\n", contarElementos(pilha)); 350 | printf("💾 Memória utilizada: ~%lu bytes\n", contarElementos(pilha) * sizeof(No)); 351 | printf("🎯 Ponteiro do topo: %p\n", (void*)(*pilha)); 352 | printf("📚 Livro no topo: %s\n", (*pilha)->info.titulo); 353 | printf("💡 Dica: Use a opção 3 para desempilhar livros.\n"); 354 | } 355 | 356 | pausar(); 357 | } 358 | 359 | void menuConsultarTamanho(No **pilha) { 360 | int tamanho = contarElementos(pilha); 361 | 362 | limparTela(); 363 | exibirCabecalho(pilha); 364 | 365 | printf("═══════════════ CONSULTAR TAMANHO ═══════════════\n\n"); 366 | 367 | printf("📊 INFORMAÇÕES DA PILHA:\n"); 368 | printf("┌─────────────────────────┬─────────┐\n"); 369 | printf("│ Total de livros │ %5d │\n", tamanho); 370 | 371 | if (tamanho == 0) { 372 | printf("│ Status │ VAZIA │\n"); 373 | printf("│ Memória utilizada │ 0 KB │\n"); 374 | } else { 375 | printf("│ Status │ ATIVA │\n"); 376 | printf("│ Memória utilizada │ %4d KB │\n", 377 | (tamanho * (int)sizeof(No)) / 1024 + 1); 378 | printf("│ Livro no topo │ %-7s │\n", (*pilha)->info.titulo); 379 | } 380 | 381 | printf("└─────────────────────────┴─────────┘\n"); 382 | 383 | if (tamanho > 0) { 384 | printf("\n📈 ESTATÍSTICAS:\n"); 385 | 386 | // Calcular estatísticas 387 | int totalPaginas = 0; 388 | int isbnMin = (*pilha)->info.isbn; 389 | int isbnMax = (*pilha)->info.isbn; 390 | 391 | No *atual = *pilha; 392 | while (atual != NULL) { 393 | totalPaginas += atual->info.paginas; 394 | if (atual->info.isbn < isbnMin) isbnMin = atual->info.isbn; 395 | if (atual->info.isbn > isbnMax) isbnMax = atual->info.isbn; 396 | atual = atual->proximo; 397 | } 398 | 399 | float mediaPaginas = (float)totalPaginas / tamanho; 400 | 401 | printf(" • Páginas totais: %d\n", totalPaginas); 402 | printf(" • Média de páginas: %.1f\n", mediaPaginas); 403 | printf(" • ISBN menor: %d\n", isbnMin); 404 | printf(" • ISBN maior: %d\n", isbnMax); 405 | } 406 | 407 | pausar(); 408 | } 409 | 410 | void menuLiberarPilha(No **pilha) { 411 | int confirmacao; 412 | int totalAntes = contarElementos(pilha); 413 | 414 | limparTela(); 415 | exibirCabecalho(pilha); 416 | 417 | printf("═══════════════ LIBERAR PILHA ═══════════════\n\n"); 418 | 419 | if (pilhaVazia(pilha)) { 420 | printf("ℹ️ A pilha já está vazia! Não há memória para liberar.\n"); 421 | pausar(); 422 | return; 423 | } 424 | 425 | printf("⚠️ ATENÇÃO: Esta operação irá remover TODOS os %d livros da pilha!\n", totalAntes); 426 | printf("📊 Livros a serem removidos:\n"); 427 | 428 | No *atual = *pilha; 429 | int contador = 1; 430 | while (atual != NULL && contador <= 3) { // Mostrar apenas os 3 primeiros 431 | printf(" %d. %s - %s\n", contador, atual->info.titulo, atual->info.autor); 432 | atual = atual->proximo; 433 | contador++; 434 | } 435 | if (totalAntes > 3) { 436 | printf(" ... e mais %d livros\n", totalAntes - 3); 437 | } 438 | 439 | printf("\nDeseja realmente liberar toda a pilha? (1-Sim / 0-Não): "); 440 | scanf("%d", &confirmacao); 441 | 442 | if (confirmacao == 1) { 443 | printf("\n🔄 Liberando memória"); 444 | 445 | // Animação visual 446 | for (int i = 0; i < 3; i++) { 447 | printf("."); 448 | fflush(stdout); 449 | #ifdef _WIN32 450 | Sleep(500); 451 | #else 452 | usleep(500000); 453 | #endif 454 | } 455 | 456 | liberarPilha(pilha); 457 | 458 | printf("\n✅ Pilha liberada com sucesso!\n"); 459 | printf("📊 Livros removidos: %d\n", totalAntes); 460 | printf("💾 Memória liberada: ~%lu bytes\n", totalAntes * sizeof(No)); 461 | printf("🎯 Status atual: VAZIA\n"); 462 | } else { 463 | printf("\n↩️ Operação cancelada. Pilha mantida intacta.\n"); 464 | } 465 | 466 | pausar(); 467 | } 468 | 469 | // ========== FUNÇÃO PRINCIPAL ========== 470 | 471 | int main() { 472 | No *pilha; 473 | int opcao; 474 | 475 | inicializarPilha(&pilha); 476 | 477 | do { 478 | exibirMenu(&pilha, &opcao); 479 | 480 | switch (opcao) { 481 | case 1: 482 | menuExibirPilha(&pilha); 483 | break; 484 | case 2: 485 | menuPush(&pilha); 486 | break; 487 | case 3: 488 | menuPop(&pilha); 489 | break; 490 | case 4: 491 | menuConsultarTopo(&pilha); 492 | break; 493 | case 5: 494 | menuVerificarVazia(&pilha); 495 | break; 496 | case 6: 497 | menuConsultarTamanho(&pilha); 498 | break; 499 | case 7: 500 | menuLiberarPilha(&pilha); 501 | break; 502 | case 0: 503 | // Cleanup automático antes de sair 504 | if (!pilhaVazia(&pilha)) { 505 | printf("\n🔄 Limpando memória antes de sair...\n"); 506 | liberarPilha(&pilha); 507 | } 508 | 509 | limparTela(); 510 | printf("╔══════════════════════════════════════╗\n"); 511 | printf("║ PROGRAMA FINALIZADO! ║\n"); 512 | printf("║ ║\n"); 513 | printf("║ Obrigado por usar o sistema de ║\n"); 514 | printf("║ Pilha Dinâmica! 🚀 ║\n"); 515 | printf("║ ║\n"); 516 | printf("║ Memória liberada com segurança ║\n"); 517 | printf("╚══════════════════════════════════════╝\n"); 518 | break; 519 | default: 520 | limparTela(); 521 | printf("❌ Opção inválida! Tente novamente.\n"); 522 | pausar(); 523 | break; 524 | } 525 | } while (opcao != 0); 526 | 527 | return 0; 528 | } --------------------------------------------------------------------------------