/**
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* .
*
* (c) Vincenzo Nicosia 2009-2017 --
*
* This file is part of NetBunch, a package for complex network
* analysis and modelling. For more information please visit:
*
* http://www.complex-networks.net/
*
* If you use this software, please add a reference to
*
* V. Latora, V. Nicosia, G. Russo
* "Complex Networks: Principles, Methods and Applications"
* Cambridge University Press (2017)
* ISBN: 9781107103184
*
***********************************************************************
*
* This is an implementation of binary heaps (both Min-Heap and
* Max-Heap).
*
*/
#include
#include
#include
#include
#include "gen_heap.h"
gen_heap_t * gen_heap_init(unsigned int N, char htype, gen_heap_func_t *funs){
gen_heap_t* h;
h = malloc(sizeof(gen_heap_t));
h->htype = htype;
h->N = N;
h->last = -1;
h->funs = *funs;
h->v = h->funs.alloc_vector(N);
return h;
}
void __gen_heap_sift_up(gen_heap_t *h, int i){
int idx, parent;
void *tmp;
idx = i;
parent = PARENT(idx);
switch(h->htype){
case MAX_HEAP:
while ( idx >0 && h->funs.compare(h->v[idx], h->v[parent]) > 0){
tmp = h->v[idx];
h->v[idx] = h->v[parent];
h->v[parent] = tmp;
idx = parent;
parent = PARENT(idx);
}
break;
case MIN_HEAP:
while ( idx >0 && h-> funs.compare(h->v[idx], h->v[parent]) < 0){
tmp = h->v[idx];
h->v[idx] = h->v[parent];
h->v[parent] = tmp;
idx = parent;
parent = PARENT(idx);
}
break;
}
}
void __gen_heap_sift_down(gen_heap_t *h, int i){
int left, right, largest, smallest;
void *tmp;
switch(h->htype){
case MAX_HEAP:
largest = i;
left = 2 * i + 1;
right = 2 * i + 2;
if (left <= h->last && h->funs.compare(h->v[left], h->v[largest]) > 0){
largest = left;
}
if (right <= h->last && h->funs.compare(h->v[right], h->v[largest]) > 0){
largest = right;
}
if (largest != i){
tmp = h->v[i];
h->v[i] = h->v[largest];
h->v[largest] = tmp;
__gen_heap_sift_down(h, largest);
}
break;
case MIN_HEAP:
smallest = i;
left = 2 * i + 1;
right = 2 * i + 2;
if (left <= h->last && h->funs.compare(h->v[left], h->v[smallest]) < 0){
smallest = left;
}
if (right <= h->last && h->funs.compare(h->v[right], h->v[smallest]) < 0){
smallest = right;
}
if (smallest != i){
tmp = h->v[i];
h->v[i] = h->v[smallest];
h->v[smallest] = tmp;
__gen_heap_sift_down(h, smallest);
}
break;
}
}
void gen_heap_insert(gen_heap_t *h, void *elem){
if (h->last < h->N-1){
h->last += 1;
h->v[h->last] = elem;
}
else{
fprintf(stderr, "Error! Trying to insert more than %d elements in the heap (%s:%d)\n",
h->N, __FILE__, __LINE__);
return;
}
__gen_heap_sift_up(h, h->last);
}
int gen_heap_delete(gen_heap_t *h, void **val){
if (h->last >=0){
*val = h->v[0];
h->v[0] = h->v[h->last];
h->last -= 1;
__gen_heap_sift_down(h,0);
return 0;
}
else{
return 1;
}
}
void* gen_heap_peek(gen_heap_t *h){
return h->v[0];
}
gen_heap_t* gen_heap_from_array(void **v, unsigned int N, unsigned int last,
char htype, gen_heap_func_t *funs){
gen_heap_t *h;
int i;
h = malloc(sizeof(gen_heap_t));
h->N = N;
h->last = last;
h->htype = htype;
h->funs = *funs;
h->v = v;
for (i=last >> 1 ; i>=0; i--){
__gen_heap_sift_down(h, i);
}
return h;
}
void gen_heap_dump(gen_heap_t* h){
int i;
unsigned int N;
N = h->last+1;
printf("N: %d last:%d root:", h->N, h->last);
if (h->last >=0)
h->funs.print_elem(h->v[0]);
else
printf("NULL");
printf("\n");
for(i=0; ifuns.print_elem(h->v[i]);
printf(" (");
h->funs.print_elem(h->v[2*i+1]);
printf(", ");
h->funs.print_elem(h->v[2*i+2]);
printf(")\n");
}
else{
printf("%d: ", i);
h->funs.print_elem(h->v[i]);
printf(" (");
h->funs.print_elem(h->v[2*i+1]);
printf(", NULL)\n");
}
else{
printf("%d: ", i);
h->funs.print_elem(h->v[i]);
printf(" (NULL, NULL)\n");
}
}
else{
printf("%d: ", i);
h->funs.print_elem(h->v[i]);
printf(" (NULL, NULL)\n");
}
}
printf("\n");
}
void gen_heap_destroy(gen_heap_t *h){
int i;
/* First deallocate all the elems */
for(i=0; i<=h->last; i++){
h->funs.dealloc_elem(h->v[i]);
}
/* now we deallocate the array */
h->funs.dealloc_vector(h->v);
h->v = NULL;
free(h);
}
int gen_heap_sort(void *v, unsigned int N, size_t size, char dir,
int (*compar)(const void *, const void *)){
gen_heap_func_t funs;
gen_heap_t *h;
void *val, **new_v=NULL, *tmp_v=NULL;
char htype;
int i;
funs.compare = compar;
htype = MAX_HEAP;
if (dir == SORT_DESC)
htype = MIN_HEAP;
new_v = malloc(N * sizeof(void*));
tmp_v = malloc(N * size);
for (i=0; i