-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstack.c
More file actions
285 lines (234 loc) · 6.59 KB
/
stack.c
File metadata and controls
285 lines (234 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
/* *
* stack.c
* Implementação de uma pilha dinâmica genérica em C.
*
* Autor: @0xCsr
* Data: 30/06/2025
*
* Esta pilha suporta operações básicas, como:
* - push: adiciona elemento ao topo,
* - pop: retira um elemento do topo e retorna o mesmo,
* - peek: acessa o elemento do topo e retorna,
* - isEmpty: verifica se a pilha está vazia,
* - destroy: destrói a pilha, liberando memória, com a opção de liberar também os dados (freeData).
* - size: retorna a quantidade de elementos da pilha.
* - clear: limpa todos elementos da pilha. Mas não desaloca a pilha.
* - foreach: percorre toda a pilha e também faz chamada por (*callback).
* */
#include <stdio.h>
#include <stdlib.h>
#include "debug.h"
#include "stack.h"
#include "array.h"
static void _push(Stack* stack, void* data);
static void* _pop(Stack* stack);
static int _isEmpty(Stack* stack);
static void _destroy(Stack* stack, int freeData);
static void* _peek(Stack* stack);
static int _size(Stack* stack);
static void _clear(Stack* stack, int);
static void _foreach(Stack* stack, void (*callback)(void*));
static int _search(Stack* stack, void* data);
static Array* _toArray(Stack* stack);
// Cria uma nova pilha (stack) e inicializa seus métodos através dos ponteiros de função.
Stack* newStack(void (*destroy_data)(void*)) {
Stack* stack = malloc(sizeof(Stack));
if (!stack) {
DEBUG_PRINT("%s: falha ao alocar memoria.\n", __func__);
return NULL;
}
stack->top = NULL;
stack->count = 0;
stack->destroy_data = destroy_data;
stack->push = &_push;
stack->pop = &_pop;
stack->isEmpty = &_isEmpty;
stack->destroy = &_destroy;
stack->peek = &_peek;
stack->size = &_size;
stack->clear = &_clear;
stack->foreach = &_foreach;
stack->search = &_search;
stack->toArray = &_toArray;
return stack;
}
// Adiciona um elemento ao topo da lista, não faz cópia desse dado, apenas armazena o ponteiro do conteúdo.
static void _push(Stack* stack, void* data) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return;
}
Node* node = malloc(sizeof(Node));
if (!node) {
DEBUG_PRINT("%s: falha ao alocar memoria para node.\n", __func__);
return;
}
node->data = data;
node->next = stack->top;
stack->top = node;
stack->count++;
DEBUG_PRINT("%s: no adicionado com sucesso.\n", __func__);
}
// Remove e retorna o elemento do topo da pilha.
static void* _pop(Stack* stack) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return NULL;
}
Node* temp = stack->top;
if (!temp) {
DEBUG_PRINT("%s: o topo esta vazio.\n", __func__);
return NULL;
}
void* data = temp->data;
stack->top = stack->top->next;
stack->count--;
free(temp);
DEBUG_PRINT("%s: node removido do topo com sucesso.\n", __func__);
return data;
}
// Checa se a pilha está vazia.
// Se tiver retorna 1, se não 0.
static int _isEmpty(Stack* stack) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return 1;
}
return (!stack->top) ? 1 : 0;
}
// Destrói a pilha liberando todos seus nós.
// Se a variavel 'freeData' for 1, libera também o conteúdo que os nós apontavam.
//
// ATENÇÃO
// Caso os dados apontados não tenham sido alocados
// dinamicamente, por exemplo: variáveis locais.
// Jamais utilize o 'freeData' igual a 1. Pois isso
// vai causar comportamentos indefinido ao tentar
// liberar a memória não alocada.
static void _destroy(Stack* stack, int freeData) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return;
}
while (!stack->isEmpty(stack)) {
Node* temp = stack->top;
stack->top = stack->top->next;
if (temp->data && freeData && stack->destroy_data) {
stack->destroy_data(temp->data);
} else if (temp->data && freeData && !stack->destroy_data) {
free(temp->data);
temp->data = NULL;
}
free(temp);
temp = NULL;
}
free(stack);
stack = NULL;
DEBUG_PRINT("%s: stack deletada com sucesso.\n", __func__);
}
// Retorna o conteúdo do topo da pilha.
static void* _peek(Stack* stack) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return NULL;
}
if (stack->isEmpty(stack)) {
DEBUG_PRINT("%s: a stack esta vazia.\n", __func__);
return NULL;
}
DEBUG_PRINT("%s: topo da stack acessado com sucesso.\n", __func__);
return stack->top->data;
}
// Retorna a quantidade de elementos na stack.
static int _size(Stack* stack) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return 0;
}
return (stack) ? stack->count : 0;
}
// Limpa a stack por completo mas não faz desalocação.
static void _clear(Stack* stack, int freeData) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return;
}
if (stack->isEmpty(stack)) {
DEBUG_PRINT("%s: a stack ja esta vazia.\n", __func__);
return;
}
while (!stack->isEmpty(stack)) {
Node* temp = stack->top;
stack->top = temp->next;
if (temp->data && freeData && stack->destroy_data) {
stack->destroy_data(temp->data);
} else if (temp->data && freeData) {
free(temp->data);
}
free(temp);
}
stack->count = 0;
DEBUG_PRINT("%s: stack limpa com sucesso.\n", __func__);
}
// Percorre todos os nós da pilha e chama um ponteiro de função.
static void _foreach(Stack* stack, void (*callback)(void* data)) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return;
}
if (stack->isEmpty(stack)) {
DEBUG_PRINT("%s: a pilha esta vazia.\n", __func__);
return;
}
if (!callback) {
DEBUG_PRINT("%s: callback nulo.\n", __func__);
return;
}
Node* current = stack->top;
while (current) {
callback(current->data);
current = current->next;
}
DEBUG_PRINT("%s: loop concluido com sucesso.\n", __func__);
}
// Busca e retorna a posição do index que se encontra o conteúdo no array.
static int _search(Stack* stack, void* data) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return 0;
}
if (!data) {
DEBUG_PRINT("%s: ponteiro nulo para data.\n", __func__);
return 0;
}
Node* temp = stack->top;
int position = 0;
while (temp) {
if (temp->data && temp->data == data) {
return position + 1;
}
position++;
temp = temp->next;
}
return -1;
}
// Converte uma pilha para array.
static Array* _toArray(Stack* stack) {
if (!stack) {
DEBUG_PRINT("%s: ponteiro nulo para stack.\n", __func__);
return NULL;
}
Array* array = newArray(stack->destroy_data, NULL);
if (!array) {
DEBUG_PRINT("%s: falha ao alocar memoria para array.\n", __func__);
return NULL;
}
Node* temp = stack->top;
while (temp) {
if (temp) {
array->add(array, temp->data);
}
temp = temp->next;
}
return array;
}