master
  1#include "meldable_heap.h"
  2#include <stddef.h>
  3#include <stdio.h>
  4#include <stdlib.h>
  5
  6/**
  7 * Compares two integers and returns -1, 0, 1.
  8 * If a is equal to b then 0 is returned.
  9 * If a is greater than b then 1 is returned.
 10 * If a is less than b then -1 is returned.
 11 *
 12 * @param a An integer
 13 * @param b Another integer
 14 * @return Returns 0, 1, or -1.
 15 */
 16static int compare(int a, int b) { return (a < b) ? -1 : ((a > b) ? 1 : 0); }
 17
 18/**
 19 * Print a visual representation of a heap.
 20 *
 21 * @param heap The subtree to print
 22 * @param level The level in the heap that this subtree is in
 23 */
 24static void print_tree(MeldableHeap *heap, int level) {
 25  for (int i = 0; i < level; i++)
 26    printf(" ");
 27
 28  if (heap) {
 29    printf("(%d)\n", heap->value);
 30
 31    if (!heap->left && !heap->right)
 32      return;
 33    print_tree(heap->left, level + 1);
 34    print_tree(heap->right, level + 1);
 35  } else {
 36    printf("( )\n");
 37  }
 38}
 39
 40/**
 41 * Initializes an instance of an meldable heap.
 42 *
 43 * @param value The value to assign to the new node in the heap.
 44 * @return Returns the new heap node instance.
 45 */
 46MeldableHeap *meldable_heap_initialize(int value) {
 47  MeldableHeap *heap = malloc(sizeof(MeldableHeap));
 48  heap->left = NULL;
 49  heap->right = NULL;
 50  heap->parent = NULL;
 51  heap->value = value;
 52  return heap;
 53};
 54
 55/**
 56 * Adds a new value into a heap.
 57 *
 58 * @param heap The subtree to attempt to insert a new value into.
 59 * @param value The value to insert.
 60 * @return Returns the new root of the subtree.
 61 */
 62MeldableHeap *meldable_heap_add(MeldableHeap *heap, int value) {
 63  MeldableHeap *root =
 64      meldable_heap_merge(meldable_heap_initialize(value), heap);
 65  root->parent = NULL;
 66  return root;
 67}
 68
 69/**
 70 * Merges to meldable heaps into a single heap and returns the
 71 * root of the new heap.
 72 *
 73 * @param h1 A heap
 74 * @param h2 Another heap
 75 * @return Returns the merged heap
 76 */
 77MeldableHeap *meldable_heap_merge(MeldableHeap *h1, MeldableHeap *h2) {
 78  if (h1 == NULL)
 79    return h2;
 80  if (h2 == NULL)
 81    return h1;
 82
 83  if (compare(h2->value, h1->value) < 0)
 84    return meldable_heap_merge(h2, h1);
 85
 86  if (rand() % 2 == 0) {
 87    h1->left = meldable_heap_merge(h1->left, h2);
 88    h1->left->parent = h1;
 89  } else {
 90    h1->right = meldable_heap_merge(h1->right, h2);
 91    h1->right->parent = h1;
 92  }
 93  return h1;
 94}
 95
 96/**
 97 * Prints a visual inspection of
 98 * a heap for debugging purposes to stdout.
 99 *
100 * @param heap The heap to visualize
101 */
102void meldable_heap_inspect(MeldableHeap *heap) { print_tree(heap, 0); }
103
104/**
105 * Removes a value from a meldable heap.
106 *
107 * @param heap The subtree to remove
108 */
109void meldable_heap_remove(MeldableHeap *heap) {
110  MeldableHeap *replacement = meldable_heap_merge(heap->left, heap->right);
111
112  if (replacement)
113    replacement->parent = heap->parent;
114
115  if (!heap->parent)
116    return;
117
118  if (heap->parent->left == heap)
119    heap->parent->left = replacement;
120  else
121    heap->parent->right = replacement;
122}