Loading [MathJax]/extensions/TeX/AMSsymbols.js
LALPulsar 7.1.1.1-5e288d3
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
HeapToplist.c
Go to the documentation of this file.
1/*
2* Copyright (C) 2007 Bernd Machenschalk
3*
4* This program is free software; you can redistribute it and/or modify
5* it under the terms of the GNU General Public License as published by
6* the Free Software Foundation; either version 2 of the License, or
7* (at your option) any later version.
8*
9* This program is distributed in the hope that it will be useful,
10* but WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12* GNU General Public License for more details.
13*
14* You should have received a copy of the GNU General Public License
15* along with with program; see the file COPYING. If not, write to the
16* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17* MA 02110-1301 USA
18*/
19
20/* This module keeps a "toplist", i.e. a list of the top n elements (accoding to an externally
21 supplied comparison function) in a standard heap structure.
22
23 A Heap is a partially sorted structure that is typically represented as a (binary) tree.
24 A tree is a heap if for all nodes the value of the node is smaller than that of all its
25 successors according to a given comparison function.
26 Footnote: in most other implementation of a heap the order is different from here, i.e.
27 replace "smaller" with "greater" in the above.
28
29 The nice thing about such a heap for our application (and others) is that this heap property
30 doesn't imply any special relation between two nodes in different branches of the tree, so no
31 effort is necessary to keep such a relation. This allows to perform all operations on the heap
32 (including removal and insertion of elements) with O(log n), i.e. at most the depth of the tree.
33
34 Here the tree is a binary tree and stored in an array where the successors succ(n) of a node
35 with index n have indices 2*n+1 and 2*n+2:
36
37 0
38 1 2
39 3 4 5 6
40 7 8 9 10 11 12 13 14
41
42 There's nothing special about that - look for "Heapsort" in the WWW or an algorithms book.
43
44 Bernd Machenschalk
45*/
46
47
48#include <stdlib.h>
49#include <string.h>
50#include "HeapToplist.h"
51
52/* this function gets a "partial heap", i.e. a heap where only the top
53 element (potentially) violates the heap property. It "bubbles
54 down" this element so that the heap property is restored */
55static void down_heap( toplist_t *list )
56{
57 size_t node = 0;
58 size_t succ;
59 char *exch;
60 while ( ( succ = node + node + 1 ) < list->elems ) {
61 if ( succ + 1 < list->elems )
62 if ( ( list->smaller )( ( list->heap )[succ + 1], ( list->heap )[succ] ) > 0 ) {
63 succ++;
64 }
65 if ( ( list->smaller )( ( list->heap )[succ], ( list->heap )[node] ) > 0 ) {
66 exch = ( list->heap )[node];
67 ( list->heap )[node] = ( list->heap )[succ];
68 ( list->heap )[succ] = exch;
69 node = succ;
70 } else {
71 break;
72 }
73 }
74}
75
76
77/* this function gets a "partial heap", i.e. a heap where only an element on
78 the lowest level (potentially) violates the heap property. "node" is the
79 index of this element. The function "bubbles up" this element so that the
80 heap property is restored */
81static void up_heap( toplist_t *list, size_t node )
82{
83 size_t pred;
84 char *exch;
85 while ( node > 0 ) {
86 pred = ( node - 1 ) / 2;
87 if ( ( list->smaller )( ( list->heap )[node], ( list->heap )[pred] ) > 0 ) {
88 exch = ( list->heap )[node];
89 ( list->heap )[node] = ( list->heap )[pred];
90 ( list->heap )[pred] = exch;
91 node = pred;
92 } else {
93 break;
94 }
95 }
96}
97
98
99/* creates a toplist with length elements,
100 returns -1 on error (out of memory), else 0 */
102 size_t length,
103 size_t size,
104 int ( *smaller )( const void *, const void * ) )
105{
106 toplist_t *listp;
107
108 if ( !( listp = malloc( sizeof( toplist_t ) ) ) ) {
109 return ( -1 );
110 }
111 if ( !( listp->data = malloc( size * length ) ) ) {
112 free( listp );
113 return ( -1 );
114 }
115 if ( !( listp->heap = malloc( sizeof( char * ) * length ) ) ) {
116 free( listp->data );
117 free( listp );
118 return ( -1 );
119 }
120
121 listp->length = length;
122 listp->elems = 0;
123 listp->size = size;
124 listp->smaller = smaller;
125
126 *list = listp;
127 return ( 0 );
128}
129
130
131/* clears an existing toplist of all elements inserted so far */
133{
134 list->elems = 0;
135}
136
137
138/* frees the space occupied by the toplist */
140{
141 free( ( *list )->heap );
142 free( ( *list )->data );
143 free( *list );
144}
145
146
147/* Inserts an element in to the toplist either if there is space left
148 or the element is larger than the smallest element in the toplist.
149 In the latter case, remove the smallest element from the toplist.
150 Returns 1 if the element was actually inserted, 0 if not. */
151int insert_into_toplist( toplist_t *list, void *element )
152{
153
154 /* if there is room left, add it at the end (and update the heap) */
155 if ( list->elems < list->length ) {
156 list->heap[list->elems] = list->data + list->elems * list->size;
157 memcpy( list->heap[list->elems], element, list->size );
158 list->elems++;
159 up_heap( list, list->elems - 1 );
160 return ( 1 );
161
162 /* if it is smaller than the smallest element, simply drop it.
163 if it is bigger, replace the smallest element (root of the heap)
164 and update the heap */
165 } else if ( ( list->smaller )( element, ( list->heap )[0] ) < 0 ) {
166 memcpy( list->heap[0], element, list->size );
167 down_heap( list );
168 return ( 1 );
169
170 } else {
171 return ( 0 );
172 }
173}
174
175
176/* apply the function "handle" to all elements of the list in the current order */
177void go_through_toplist( toplist_t *list, void ( *handle )( void * ) )
178{
179 size_t i;
180 for ( i = 0; i < list->elems; i++ ) {
181 handle( list->heap[i] );
182 }
183}
184
185void *toplist_elem( toplist_t *list, size_t ind )
186{
187 if ( list == NULL ) {
188 return ( NULL );
189 }
190 if ( ind >= list->elems ) {
191 return ( NULL );
192 }
193 return ( list->heap[ind] );
194}
195
197{
198 size_t i = 0;
199 int res = 0;
200 if ( ( list1 == NULL ) || ( list2 == NULL ) ) {
201 return ( 2 );
202 }
203 if ( ( list1->smaller != list2->smaller ) ||
204 ( list1->size != list2->size ) ) {
205 return ( 2 );
206 }
207 while ( ( i < list1->elems ) &&
208 ( i < list2->elems ) &&
209 ( res == 0 ) ) {
210 res = list1->smaller( toplist_elem( list1, i ), toplist_elem( list2, i ) );
211 i++;
212 }
213 if ( res == 0 ) {
214 if ( list1->elems < list2->elems ) {
215 return ( 1 );
216 } else if ( list1->elems > list2->elems ) {
217 return ( -1 );
218 }
219 }
220 return ( res );
221}
222
223
224/* using qsort requires some "global" help */
225
226/* global function pointer for qsort */
227static int ( *_qsort_compare1 )( const void *, const void * );
228/* wrapper function for qsort */
229static int _qsort_compare2( const void *a, const void *b )
230{
231 return ( _qsort_compare1( *( void *const * )a, *( void *const * )b ) );
232}
233/* inverse wrapper */
234static int _qsort_compare3( const void *b, const void *a )
235{
236 return ( _qsort_compare1( *( void *const * )a, *( void *const * )b ) );
237}
238
239/* sorts the toplist with an arbitrary sorting function
240 (potentially) destroying the heap property */
241void qsort_toplist( toplist_t *list, int ( *compare )( const void *, const void * ) )
242{
243 /* point the global function pointer to compare, then call qsort with the wrapper */
244 _qsort_compare1 = compare;
245 qsort( list->heap, list->elems, sizeof( char * ), _qsort_compare2 );
246}
247
248/* qsort function that gives the reverse ordering of the previous */
249void qsort_toplist_r( toplist_t *list, int ( *compare )( const void *, const void * ) )
250{
251 /* point the global function pointer to compare, then call qsort with the wrapper */
252 _qsort_compare1 = compare;
253 qsort( list->heap, list->elems, sizeof( char * ), _qsort_compare3 );
254}
static int _qsort_compare2(const void *a, const void *b)
Definition: HeapToplist.c:229
int create_toplist(toplist_t **list, size_t length, size_t size, int(*smaller)(const void *, const void *))
Definition: HeapToplist.c:101
void free_toplist(toplist_t **list)
Definition: HeapToplist.c:139
void qsort_toplist(toplist_t *list, int(*compare)(const void *, const void *))
Definition: HeapToplist.c:241
static void down_heap(toplist_t *list)
Definition: HeapToplist.c:55
void * toplist_elem(toplist_t *list, size_t ind)
Definition: HeapToplist.c:185
void qsort_toplist_r(toplist_t *list, int(*compare)(const void *, const void *))
Definition: HeapToplist.c:249
int insert_into_toplist(toplist_t *list, void *element)
Definition: HeapToplist.c:151
static void up_heap(toplist_t *list, size_t node)
Definition: HeapToplist.c:81
int compare_toplists(toplist_t *list1, toplist_t *list2)
Definition: HeapToplist.c:196
void go_through_toplist(toplist_t *list, void(*handle)(void *))
Definition: HeapToplist.c:177
void clear_toplist(toplist_t *list)
Definition: HeapToplist.c:132
static int _qsort_compare3(const void *b, const void *a)
Definition: HeapToplist.c:234
static int(* _qsort_compare1)(const void *, const void *)
Definition: HeapToplist.c:227
static int smaller(const void *a, const void *b)
static const INT4 a
size
char ** heap
Definition: HeapToplist.h:40
size_t length
Definition: HeapToplist.h:36
size_t elems
Definition: HeapToplist.h:37
size_t size
Definition: HeapToplist.h:38
char * data
Definition: HeapToplist.h:39
int(* smaller)(const void *, const void *)
Definition: HeapToplist.h:41