📄 gdsl_heap.c
字号:
/* * This file is part of the Generic Data Structures Library (GDSL). * Copyright (C) 1998-2006 Nicolas Darnis <ndarnis@free.fr>. * * The GDSL library 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 2 of * the License, or (at your option) any later version. * * The GDSL library 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 the GDSL library; see the file COPYING. * If not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * * $RCSfile: gdsl_heap.c,v $ * $Revision: 1.13 $ * $Date: 2006/06/21 14:47:24 $ */#include <config.h>#include <assert.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "gdsl_heap.h"struct heap{ char* name; ulong card; gdsl_element_t* nodes; gdsl_alloc_func_t alloc_f; gdsl_free_func_t free_f; gdsl_compare_func_t comp_f;};static gdsl_element_t default_alloc (void* e);static void default_free (gdsl_element_t e);static long int default_comp (gdsl_element_t e, void* key);static gdsl_location_tget_location (gdsl_heap_t heap, int i);static voidtaslacmite (gdsl_element_t* t, ulong k, gdsl_compare_func_t comp_f);static ulongtaslactite (gdsl_element_t* t, ulong n, ulong k, gdsl_compare_func_t comp_f);/******************************************************************************//* Management functions of heaps *//******************************************************************************/extern gdsl_heap_tgdsl_heap_alloc (const char* name, gdsl_alloc_func_t alloc_f, gdsl_free_func_t free_f, gdsl_compare_func_t comp_f){ gdsl_heap_t heap; heap = (gdsl_heap_t) malloc (sizeof (struct heap)); if (heap == NULL) { return NULL; } heap->name = NULL; if (gdsl_heap_set_name (heap, name) == NULL) { free (heap); return NULL; } heap->nodes = (gdsl_element_t*) malloc (sizeof (gdsl_element_t)); if (heap->nodes == NULL) { if (heap->name != NULL) { free (heap->name); } free (heap); return NULL; } heap->nodes [0] = NULL; heap->card = 0; heap->alloc_f = alloc_f ? alloc_f : default_alloc; heap->free_f = free_f ? free_f : default_free; heap->comp_f = comp_f ? comp_f : default_comp; return heap;}extern voidgdsl_heap_free (gdsl_heap_t heap){ ulong i; assert (heap != NULL); if (heap->name != NULL) { free (heap->name); } for (i = 1; i < heap->card; i++) { heap->free_f (heap->nodes [i]); } free (heap);}extern voidgdsl_heap_flush (gdsl_heap_t heap){ ulong i; assert (heap != NULL); for (i = 1; i < heap->card; i++) { heap->free_f (heap->nodes [i]); } heap->card = 0;}/******************************************************************************//* Consultation functions of heaps *//******************************************************************************/extern const char*gdsl_heap_get_name (const gdsl_heap_t heap){ assert (heap != NULL); return heap->name;}extern ulonggdsl_heap_get_size (const gdsl_heap_t heap){ assert (heap != NULL); return heap->card;}extern gdsl_element_tgdsl_heap_get_top (const gdsl_heap_t heap){ assert (heap != NULL); return (heap->card == 0) ? NULL : heap->nodes [1];}extern bool gdsl_heap_is_empty (const gdsl_heap_t heap){ assert (heap != NULL); return (bool) (heap->card == 0);}/******************************************************************************//* Modification functions of heaps *//******************************************************************************/extern gdsl_heap_tgdsl_heap_set_name (gdsl_heap_t heap, const char* name){ if (heap->name != NULL) { free (heap->name); heap->name = NULL; } if (name != NULL) { heap->name = (char*) malloc ((1 + strlen (name)) * sizeof (char)); if (heap->name == NULL) { return NULL; } strcpy (heap->name, name); } return heap;}extern gdsl_element_tgdsl_heap_set_top (gdsl_heap_t heap, void* value){ gdsl_element_t e; assert (heap != NULL); e = (heap->alloc_f) (value); if (e == NULL) { return NULL; } heap->nodes [0] = e; if (taslactite (heap->nodes, heap->card, 0, heap->comp_f) == 0) { (heap->free_f) (e); heap->nodes [0] = NULL; return NULL; } return heap->nodes [0];}extern gdsl_element_tgdsl_heap_insert (gdsl_heap_t heap, void* value){ gdsl_element_t e; assert (heap != NULL); e = (heap->alloc_f) (value); if (e == NULL) { return NULL; } heap->nodes = (gdsl_element_t*) realloc (heap->nodes, (2 + heap->card) * sizeof (gdsl_element_t)); if (heap->nodes == NULL) { (heap->free_f) (e); return NULL; } heap->card++; heap->nodes [heap->card] = e; taslacmite (heap->nodes, heap->card, heap->comp_f); return e;}#if 0extern gdsl_element_tgdsl_heap_remove (gdsl_heap_t heap, void* value){ ulong j; ulong k; ulong n;#warning this method is not finished assert (heap != NULL); k = 1; n = heap->card; while (k <= n / 2) { if (heap->comp_f (value, heap->nodes [k]) == 0) { gdsl_element_t e = heap->nodes [k]; heap->nodes [k] = heap->nodes [heap->card]; heap->card--; taslactite (heap->nodes, heap->card, k, heap->comp_f); return e; } j = k + k; if (heap->comp_f (value, heap->nodes [j]) < 0) k = j; } return NULL;}#endifextern gdsl_element_tgdsl_heap_remove_top (gdsl_heap_t heap){ gdsl_element_t e = NULL; assert (heap != NULL); if (heap->card == 0) { return NULL; } e = heap->nodes [1]; heap->nodes [1] = heap->nodes [heap->card]; heap->card--; taslactite (heap->nodes, heap->card, 1, heap->comp_f); return e;}extern gdsl_heap_tgdsl_heap_delete_top (gdsl_heap_t heap){ gdsl_element_t e = gdsl_heap_remove_top (heap); if (e == NULL) { return NULL; } heap->free_f (e); return heap;}/******************************************************************************//* Parse functions of heaps *//******************************************************************************/extern gdsl_element_tgdsl_heap_map_forward (const gdsl_heap_t heap, gdsl_map_func_t map_f, void* user_data){ ulong i; assert (heap != NULL); assert (map_f != NULL); for (i = 1; i <= heap->card; i++) { gdsl_element_t e = heap->nodes [i]; if (map_f (e, get_location (heap, i), user_data) == GDSL_MAP_STOP) { return e; } } return NULL;}/******************************************************************************//* Input/output functions of heaps *//******************************************************************************/extern voidgdsl_heap_write (const gdsl_heap_t heap, gdsl_write_func_t write_f, FILE* file, void* user_data){ ulong i; for (i = 1; i <= heap->card; i++) { if (write_f != NULL) { write_f (heap->nodes [i], file, get_location (heap, i), user_data); } }}extern voidgdsl_heap_write_xml (const gdsl_heap_t heap, gdsl_write_func_t write_f, FILE* file, void* user_data){ ulong i; fprintf (file, "<GDSL_HEAP REF=\"%p\" NAME=\"%s\" SIZE=\"%ld\">\n", (void*) heap, heap->name == NULL ? "" : heap->name, heap->card); for (i = 1; i <= heap->card; i++) { fprintf (file, "<GDSL_HEAP_ENTRY VALUE=\"%ld\">\n", i); if (write_f != NULL) { write_f (heap->nodes [i], file, get_location (heap, i), user_data); } fprintf (file, "</GDSL_HEAP_ENTRY>\n"); } fprintf (file, "</GDSL_HEAP>\n");}extern voidgdsl_heap_dump (const gdsl_heap_t heap, gdsl_write_func_t write_f, FILE* file, void* user_data){ ulong i; fprintf (file, "<GDSL_HEAP REF=\"%p\" NAME=\"%s\" SIZE=\"%ld\">\n", (void*) heap, heap->name == NULL ? "" : heap->name, heap->card); for (i = 1; i <= heap->card; i++) { fprintf (file, "<GDSL_HEAP_ENTRY VALUE=\"%ld\">\n", i); if (write_f != NULL) { write_f (heap->nodes [i], file, get_location (heap, i), user_data); } fprintf (file, "</GDSL_HEAP_ENTRY>\n"); } fprintf (file, "</GDSL_HEAP>\n");}/******************************************************************************//* Private functions *//******************************************************************************/static gdsl_element_t default_alloc (void* e){ return e;}static void default_free (gdsl_element_t e){ ;}static long int default_comp (gdsl_element_t e, void* key){ return 0;}static voidtaslacmite (gdsl_element_t* t, ulong k, gdsl_compare_func_t comp_f){ gdsl_element_t v; v = t [k]; /* to avoid k != 1 test below, we could * add the instruction t [0] = MAX_POSSIBLE_VALUE * but, we don't know MAX_POSSIBLE_VALUE here. */ while (k != 1 && comp_f (t [k/2], v) <= 0) { t [k] = t [k/2]; k /= 2; } t [k] = v;}static ulongtaslactite (gdsl_element_t* t, ulong n, ulong k, gdsl_compare_func_t comp_f){ ulong j; gdsl_element_t v; v = t [k]; while (k <= n / 2) { j = k + k; if (j < n && comp_f (t [j], t [j+1]) < 0) { j++; } if (comp_f (t [j], v) <= 0) { break; } t [k] = t [j]; k = j; } t [k] = v; return k;}static gdsl_location_tget_location (gdsl_heap_t heap, int i){ gdsl_location_t location = GDSL_LOCATION_UNDEF; if (i == 1) { location |= GDSL_LOCATION_ROOT; } if (i == heap->card) { location |= GDSL_LOCATION_LEAF; } if (i * 2 > heap->card) { location |= GDSL_LOCATION_LEAF; } return location;} /** EMACS ** * Local variables: * mode: c * c-basic-offset: 4 * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -