The LevAWC Project
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Pages
heap.c
Go to the documentation of this file.
1 /*
2  * _____
3  * ANSI / ___/
4  * / /__
5  * \___/
6  *
7  * Filename: heap.c
8  * Author : Kyle Loudon/Dan Levin
9  * Date : Fri Mar 22 12:40:45 GMT 2013
10  * Version : 0.51
11  * ---
12  * Description: A heap ADT - written in ANSI C.
13  *
14  * Date Revision message
15  * 150331 This code ready for version 0.51
16  *
17  */
18 
23 #include <stdio.h>
24 #include <stdlib.h>
25 
26 #include "heap.h"
27 
36 #define HEAP_PRINT_LEVEL_PADDING 4
37 
38 struct Heap_ {
39  int size;
40  int (*compare)(const void *key1, const void *key2);
41  void (*destroy)(void *data);
42  void **tree;
43 };
44 
45 /* STATIC FUNCTION DECLARATIONS */
46 static void print_tree(Heap hp, int ele_idx, int level, void (*callback)(const void *data));
47 static int HEAPparent(int npos);
48 static int HEAPleft(int npos);
49 static int HEAPright(int npos);
50 
51 
52 /* --- PUBLIC FUNCTION DEFINITIONS --- */
53 /* --- Function: Heap HEAPinit(int (*compare)(const void *key1, const void* key2), void (*destroy)(void *data)) --- */
54 Heap HEAPinit(int (*compare)(const void *key1, const void* key2), void (*destroy)(void *data))
55 {
56  Heap hp;
57 
58  if ((hp = (Heap)malloc(sizeof(struct Heap_)))==NULL)
59  return NULL;
60 
61  hp->size = 0;
62  hp->compare = compare;
63  hp->destroy = destroy;
64  hp->tree = NULL;
65 
66  return hp;
67 }
68 
69 /* --- Function: void HEAPdestroy(Heap hp) --- */
70 void HEAPdestroy(Heap hp)
71 {
72  int i;
73 
74  if (hp->destroy != NULL)
75  {
76  for (i = 0; i < HEAPsize(hp); i++)
77  hp->destroy(hp->tree[i]);
78  }
79 
80  free(hp->tree);
81  free(hp);
82 }
83 
84 /* --- Function: int HEAPinsert(Heap hp, const void *data) --- */
85 int HEAPinsert(Heap hp, const void *data)
86 {
87  void *tmp;
88  int currpos, parentpos;
89 
90  /* Allocate storage for the new node */
91  if ((tmp = realloc(hp->tree, (HEAPsize(hp) + 1) * sizeof(void *))) == NULL)
92  return -1;
93  else
94  hp->tree = (void **)tmp;
95 
96  /* Insert the node after the last node */
97  hp->tree[HEAPsize(hp)] = (void *)data;
98 
99  /* Heapify the tree by pushing the contents of the new node upward */
100  currpos = HEAPsize(hp);
101  parentpos = HEAPparent(currpos);
102 
103  while (currpos > 0 && hp->compare(hp->tree[parentpos], hp->tree[currpos]) < 0)
104  {
105  /* Swap the contents of the current node and its parent */
106  tmp = hp->tree[parentpos];
107  hp->tree[parentpos] = hp->tree[currpos];
108  hp->tree[currpos] = tmp;
109 
110  /* Move up one level in the tree to continue heapifying */
111  currpos = parentpos;
112  parentpos = HEAPparent(currpos);
113  }
114 
115  /* Adjust the size of the heap to account for the inserted node */
116  hp->size++;
117 
118  return 0;
119 }
120 
121 /* --- Function: const void *HEAPpeek(Heap hp) --- */
122 const void *HEAPpeek(Heap hp)
123 {
124  return hp->size ? hp->tree[0] : NULL;
125 }
126 
127 /* --- Function: int HEAPextract(Heap hp, void **data) --- */
128 int HEAPextract(Heap hp, void **data)
129 {
130  void *save, *temp;
131  int currpos, leftpos, rightpos, tmppos;
132 
133  /* Do not allow extraction from an empty heap */
134  if (HEAPsize(hp) == 0)
135  return -1;
136 
137  /* Extract and return node data at the top of the heap */
138  *data = hp->tree[0];
139 
140  /* Store/Backup data of the last noded of the heap */
141  save = hp->tree[HEAPsize(hp) - 1];
142 
143  /* Adjust(=Shrink) the size of the heap */
144  if (HEAPsize(hp) - 1 > 0)
145  {
146  if ((temp = (void **)realloc(hp->tree, (HEAPsize(hp) - 1) * sizeof(void *))) == NULL)
147  return -1;
148  else
149  hp->tree = temp;
150 
151  /* Adjust the size of the heap to account for the extracted node */
152  hp->size--;
153  }
154  else
155  {
156  /* Manage the heap when extracting the last node - and return from call */
157  free(hp->tree);
158  hp->tree = NULL;
159  hp->size = 0;
160 
161  return 0;
162  }
163 
164  /* Copy the (earlier saved), last node - to the top */
165  hp->tree[0] = save;
166 
167  /* Heapify the tree by pushing the contents of the new top - downwards... */
168  currpos = 0;
169 
170  /* leftpos = HEAPleft(currpos); */
171  /* rightpos = HEAPright(currpos); */
172 
173  while (1)
174  {
175  /* Select the child to swap with the current node */
176  leftpos = HEAPleft(currpos);
177  rightpos = HEAPright(currpos);
178 
179  if (leftpos < HEAPsize(hp) && hp->compare(hp->tree[leftpos], hp->tree[currpos]) > 0)
180  tmppos = leftpos;
181  else
182  tmppos = currpos;
183 
184  if (rightpos < HEAPsize(hp) && hp->compare(hp->tree[rightpos], hp->tree[tmppos]) > 0)
185  tmppos = rightpos;
186 
187  /* When tmppos is equal to currpos, the heap property has been restored */
188  if (tmppos == currpos)
189  {
190  /* Time to return to caller... */
191  break;
192  }
193  else
194  {
195  /* Swap the contents of the current node and the selected child */
196  temp = hp->tree[tmppos];
197  hp->tree[tmppos] = hp->tree[currpos];
198  hp->tree[currpos] = temp;
199 
200  /* Move down one level in the tree to continue heapifying */
201  currpos = tmppos;
202  }
203  }
204 
205  return 0;
206 }
207 
208 /* --- Function: int HEAPsize(Heap hp) --- */
209 int HEAPsize(Heap hp)
210 {
211  return hp->size;
212 }
213 
214 /* --- Function: void HEAPprint(Heap hp, void (*callback)(const void *data)) --- */
215 void HEAPprint(Heap hp, void (*callback)(const void *data))
216 {
217  int i;
218 
219  if (hp->size)
220  {
221  printf("\nHeap: ");
222 
223  /* Print the heap - in array format.. */
224  for (i = 0; i < hp->size; ++i)
225  callback(hp->tree[i]);
226 
227  /* Now - print the "heap tree"... */
228  printf("\nTree:\n");
229  print_tree(hp, 0, 0, callback);
230  }
231 }
232 
233 /* --- STATIC FUNCTION DEFINITIONS --- */
234 /* --- Function: static void print_tree(Heap hp, int ele_idx, int level, void (*callback)(const void *data)) --- */
235 static void print_tree(Heap hp, int ele_idx, int level, void (*callback)(const void *data))
236 {
237  char *p_msk;
238 
239  /* Recursion condition */
240  if (ele_idx >= hp->size)
241  return;
242 
243  /* Print current element data */
244  p_msk = (char *)malloc((HEAP_PRINT_LEVEL_PADDING*level+1)*sizeof(char));
245  assert(p_msk);
246  memset(p_msk, '-', HEAP_PRINT_LEVEL_PADDING*level);
247  p_msk[HEAP_PRINT_LEVEL_PADDING*level] = '\0';
248  printf("%s", p_msk);
249  callback(hp->tree[ele_idx]);
250  printf("\n");
251  free(p_msk);
252 
253  /* Recursively print "subtrees" of the heap... */
254  print_tree(hp, HEAPleft(ele_idx), level+1, callback);
255  print_tree(hp, HEAPright(ele_idx), level+1, callback);
256 }
257 
258 /* --- Function: static int HEAPparent(int npos) --- */
259 static int HEAPparent(int npos)
260 {
261  return (npos-1)/2;
262 }
263 
264 /* --- Function: static int HEAPleft(int npos) --- */
265 static int HEAPleft(int npos)
266 {
267  return npos*2+1;
268 }
269 
270 /* --- Function: static int HEAPright(int npos) --- */
271 static int HEAPright(int npos)
272 {
273  return npos*2+2;
274 }