doc: sort: give example for sorting on the last field
[coreutils.git] / gl / lib / heap.c
blob577997d84d7890d60014e4826b080642963aee09
1 /* Barebones heap implementation supporting only insert and pop.
3 Copyright (C) 2010-2024 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 /* Full implementation: GDSL (http://gna.org/projects/gdsl/) by Nicolas
19 Darnis <ndarnis@free.fr>. */
21 #include <config.h>
23 #include "heap.h"
24 #include "stdlib--.h"
25 #include "xalloc.h"
27 static int heap_default_compare (void const *, void const *);
28 static size_t heapify_down (void **, size_t, size_t,
29 int (*) (void const *, void const *));
30 static void heapify_up (void **, size_t,
31 int (*) (void const *, void const *));
33 struct heap
35 void **array; /* array[0] is not used */
36 size_t capacity; /* Array size */
37 size_t count; /* Used as index to last element. Also is num of items. */
38 int (*compare) (void const *, void const *);
41 /* Allocate memory for the heap. */
43 struct heap *
44 heap_alloc (int (*compare) (void const *, void const *), size_t n_reserve)
46 struct heap *heap = xmalloc (sizeof *heap);
48 if (n_reserve == 0)
49 n_reserve = 1;
51 heap->array = xnmalloc (n_reserve, sizeof *(heap->array));
53 heap->array[0] = nullptr;
54 heap->capacity = n_reserve;
55 heap->count = 0;
56 heap->compare = compare ? compare : heap_default_compare;
58 return heap;
62 static int
63 heap_default_compare (void const *a, void const *b)
65 return 0;
69 void
70 heap_free (struct heap *heap)
72 free (heap->array);
73 free (heap);
76 /* Insert element into heap. */
78 int
79 heap_insert (struct heap *heap, void *item)
81 if (heap->capacity - 1 <= heap->count)
82 heap->array = x2nrealloc (heap->array, &heap->capacity,
83 sizeof *(heap->array));
85 heap->array[++heap->count] = item;
86 heapify_up (heap->array, heap->count, heap->compare);
88 return 0;
91 /* Pop top element off heap. */
93 void *
94 heap_remove_top (struct heap *heap)
96 void *top;
98 if (heap->count == 0)
99 return nullptr;
101 top = heap->array[1];
102 heap->array[1] = heap->array[heap->count--];
103 heapify_down (heap->array, heap->count, 1, heap->compare);
105 return top;
108 /* Move element down into appropriate position in heap. */
110 static size_t
111 heapify_down (void **array, size_t count, size_t initial,
112 int (*compare) (void const *, void const *))
114 void *element = array[initial];
116 size_t parent = initial;
117 while (parent <= count / 2)
119 size_t child = 2 * parent;
121 if (child < count && compare (array[child], array[child + 1]) < 0)
122 child++;
124 if (compare (array[child], element) <= 0)
125 break;
127 array[parent] = array[child];
128 parent = child;
131 array[parent] = element;
132 return parent;
135 /* Move element up into appropriate position in heap. */
137 static void
138 heapify_up (void **array, size_t count,
139 int (*compare) (void const *, void const *))
141 size_t k = count;
142 void *new_element = array[k];
144 while (k != 1 && compare (array[k / 2], new_element) <= 0)
146 array[k] = array[k / 2];
147 k /= 2;
150 array[k] = new_element;