-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathheap.c
executable file
·146 lines (119 loc) · 3.63 KB
/
heap.c
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
#include <stdlib.h>
#include "heap.h"
#define CAPACIDAD_STANDARD 10
void swap(void **a, void **b) {
void* temp = *a;
*a = *b;
*b = temp;
}
struct heap {
cmp_func_t cmp;
size_t capacidad, cantidad;
void** datos;
};
heap_t *heap_crear(cmp_func_t cmp) {
heap_t* heap = malloc(sizeof (heap_t));
if (heap == NULL) return NULL;
heap->capacidad = CAPACIDAD_STANDARD;
heap->cantidad = 0;
heap->cmp = cmp;
heap->datos = malloc (sizeof (void*) * CAPACIDAD_STANDARD);
if (heap->datos == NULL){
free(heap);
return NULL;
}
return heap;
}
void heap_redimensionar_datos(heap_t *heap, size_t nuevaCapacidad){
heap->datos = realloc(heap->datos, sizeof (void*) * nuevaCapacidad);
if (heap->datos) heap->capacidad = nuevaCapacidad;
}
void downHeap(void** datos, cmp_func_t cmp, size_t cantidad, size_t padre){
size_t h_izq = 2 * padre + 1;
size_t h_der = 2 * padre + 2;
if (h_izq >= cantidad) return;
size_t min = h_izq;
if (h_der < cantidad && cmp(datos[h_izq], datos[h_der]) < 0)
min = h_der;
if (cmp(datos[min], datos[padre]) > 0){
swap(&datos[min], &datos[padre]);
downHeap(datos, cmp, cantidad, min);
}
}
void heapify(void **elementos, cmp_func_t cmp, size_t cant){
for (int i = (int)cant/2-1; i>= 0; i--){
downHeap(elementos, cmp, cant, (size_t)i);
}
}
heap_t *heap_crear_arr(void **arreglo, size_t n, cmp_func_t cmp) {
heap_t* heap = heap_crear(cmp);
if (heap == NULL) return NULL;
while (heap->capacidad < n){
heap_redimensionar_datos(heap, heap->capacidad*2);
if (!heap->datos){
free(heap);
return NULL;
}
}
for (int i = 0; i < n; i++){
heap->datos[i] = arreglo[i];
}
heap->cantidad = n;
heapify(heap->datos, cmp, heap->cantidad);
return heap;
}
size_t heap_cantidad(const heap_t *heap) {
return heap->cantidad;
}
bool heap_esta_vacio(const heap_t *heap) {
return heap->cantidad == 0;
}
void upHeap(void** datos, cmp_func_t cmp, size_t hijo){
if (hijo == 0) return;
size_t padre = (hijo-1)/2;
if (cmp(datos[hijo], datos[padre]) > 0){
swap(&datos[hijo], &datos[padre]);
upHeap(datos, cmp, padre);
}
}
bool heap_encolar(heap_t *heap, void *elem) {
if (heap->cantidad == heap->capacidad){
heap_redimensionar_datos(heap, heap->capacidad*2);
if (!heap->datos) return NULL;
}
heap->datos[heap->cantidad] = elem;
upHeap(heap->datos, heap->cmp, heap->cantidad);
heap->cantidad++;
return true;
}
void *heap_ver_max(const heap_t *heap) {
return (!heap_esta_vacio(heap)) ? heap->datos[0] : NULL;
}
void *heap_desencolar(heap_t *heap) {
if (heap_esta_vacio(heap)) return NULL;
void* dato = heap->datos[0];
heap->cantidad--;
// Paso el ultimo al principio
swap(&heap->datos[0], &heap->datos[heap->cantidad]);
downHeap(heap->datos, heap->cmp, heap->cantidad, 0);
if (heap->cantidad <= heap->capacidad/4 && heap->cantidad <= CAPACIDAD_STANDARD){
heap_redimensionar_datos(heap, heap->capacidad/2);
if (heap->datos == NULL) return NULL;
}
return dato;
}
void heap_destruir(heap_t *heap, void (*destruir_elemento)(void *)) {
if (destruir_elemento){
for (int i = 0; i < heap->cantidad; i++)
destruir_elemento(heap->datos[i]);
}
free(heap->datos);
free(heap);
}
void heap_sort(void **elementos, size_t cant, cmp_func_t cmp) {
heapify(elementos, cmp, cant);
for (int i = (int)cant - 1; i >= 0; i--) {
swap(&elementos[0], &elementos[i]);
downHeap(elementos, cmp, (size_t)i, 0);
}
}