Advertisement
SteelCrow

Heap

Jun 27th, 2017
501
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.95 KB | None | 0 0
  1. /* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
  2.  *
  3.  * Permission to use, copy, modify, and/or distribute this software for any
  4.  * purpose with or without fee is hereby granted, provided that the above
  5.  * copyright notice and this permission notice appear in all copies.
  6.  *
  7.  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8.  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9.  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  10.  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  12.  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  13.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  14.  */
  15.  
  16. #include <stddef.h>  /* NULL */
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19.  
  20. struct heap_node {
  21.   int id;
  22.   struct heap_node* left;
  23.   struct heap_node* right;
  24.   struct heap_node* parent;
  25. };
  26.  
  27. /* A binary min heap.  The usual properties hold: the root is the lowest
  28.  * element in the set, the height of the tree is at most log2(nodes) and
  29.  * it's always a complete binary tree.
  30.  *
  31.  * The heap function try hard to detect corrupted tree nodes at the cost
  32.  * of a minor reduction in performance.  Compile with -DNDEBUG to disable.
  33.  */
  34. struct heap {
  35.   struct heap_node* min;
  36.   unsigned int nelts;
  37. };
  38.  
  39. /* Return non-zero if a < b. */
  40. typedef int (*heap_compare_fn)(const struct heap_node* a,
  41.                                const struct heap_node* b);
  42.  
  43. /* Public functions. */
  44. void heap_init(struct heap* heap);
  45. struct heap_node* heap_min(const struct heap* heap);
  46. void heap_insert(struct heap* heap,
  47.                              struct heap_node* newnode,
  48.                              heap_compare_fn less_than);
  49. void heap_remove(struct heap* heap,
  50.                              struct heap_node* node,
  51.                              heap_compare_fn less_than);
  52. void heap_dequeue(struct heap* heap, heap_compare_fn less_than);
  53.  
  54. /* Implementation follows. */
  55.  
  56. void heap_init(struct heap* heap) {
  57.   heap->min = NULL;
  58.   heap->nelts = 0;
  59. }
  60.  
  61. struct heap_node* heap_min(const struct heap* heap) {
  62.   return heap->min;
  63. }
  64.  
  65. /* Swap parent with child. Child moves closer to the root, parent moves away. */
  66. static void heap_node_swap(struct heap* heap,
  67.                            struct heap_node* parent,
  68.                            struct heap_node* child) {
  69.   printf("heap_node_swap: parent=%d - child=%d\n", parent->id, child->id);
  70.   struct heap_node* sibling;
  71.   struct heap_node t;
  72.  
  73.   t = *parent;
  74.   *parent = *child;
  75.   *child = t;
  76.  
  77.   parent->parent = child;
  78.   if (child->left == child) {
  79.     child->left = parent;
  80.     sibling = child->right;
  81.   } else {
  82.     child->right = parent;
  83.     sibling = child->left;
  84.   }
  85.   if (sibling != NULL)
  86.     sibling->parent = child;
  87.  
  88.   if (parent->left != NULL)
  89.     parent->left->parent = parent;
  90.   if (parent->right != NULL)
  91.     parent->right->parent = parent;
  92.  
  93.   if (child->parent == NULL)
  94.     heap->min = child;
  95.   else if (child->parent->left == parent)
  96.     child->parent->left = child;
  97.   else
  98.     child->parent->right = child;
  99.  
  100.   struct heap_node *h = heap_min(heap);
  101.   printf("AFTER_SWAP: %d %d\n", h->id, h->left->id);
  102. }
  103.  
  104. void heap_insert(struct heap* heap,
  105.                              struct heap_node* newnode,
  106.                              heap_compare_fn less_than) {
  107.   struct heap_node** parent;
  108.   struct heap_node** child;
  109.   unsigned int path;
  110.   unsigned int n;
  111.   unsigned int k;
  112.  
  113.   newnode->left = NULL;
  114.   newnode->right = NULL;
  115.   newnode->parent = NULL;
  116.  
  117.   /* Calculate the path from the root to the insertion point.  This is a min
  118.    * heap so we always insert at the left-most free node of the bottom row.
  119.    */
  120.   path = 0;
  121.   for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2)
  122.     path = (path << 1) | (n & 1);
  123.  
  124.   /* Now traverse the heap using the path we calculated in the previous step. */
  125.   parent = child = &heap->min;
  126.   while (k > 0) {
  127.     parent = child;
  128.     if (path & 1)
  129.       child = &(*child)->right;
  130.     else
  131.       child = &(*child)->left;
  132.     path >>= 1;
  133.     k -= 1;
  134.   }
  135.  
  136.   /* Insert the new node. */
  137.   newnode->parent = *parent;
  138.   *child = newnode;
  139.   heap->nelts += 1;
  140.  
  141.   /* Walk up the tree and check at each node if the heap property holds.
  142.    * It's a min heap so parent < child must be true.
  143.    */
  144.   while (newnode->parent != NULL && less_than(newnode, newnode->parent))
  145.     heap_node_swap(heap, newnode->parent, newnode);
  146. }
  147.  
  148. void heap_remove(struct heap* heap,
  149.                              struct heap_node* node,
  150.                              heap_compare_fn less_than) {
  151.   struct heap_node* smallest;
  152.   struct heap_node** max;
  153.   struct heap_node* child;
  154.   unsigned int path;
  155.   unsigned int k;
  156.   unsigned int n;
  157.  
  158.   if (heap->nelts == 0)
  159.     return;
  160.  
  161.   /* Calculate the path from the min (the root) to the max, the left-most node
  162.    * of the bottom row.
  163.    */
  164.   path = 0;
  165.   for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2)
  166.     path = (path << 1) | (n & 1);
  167.  
  168.   /* Now traverse the heap using the path we calculated in the previous step. */
  169.   max = &heap->min;
  170.   while (k > 0) {
  171.     if (path & 1)
  172.       max = &(*max)->right;
  173.     else
  174.       max = &(*max)->left;
  175.     path >>= 1;
  176.     k -= 1;
  177.   }
  178.  
  179.   heap->nelts -= 1;
  180.  
  181.   /* Unlink the max node. */
  182.   child = *max;
  183.   *max = NULL;
  184.  
  185.   if (child == node) {
  186.     /* We're removing either the max or the last node in the tree. */
  187.     if (child == heap->min) {
  188.       heap->min = NULL;
  189.     }
  190.     return;
  191.   }
  192.  
  193.   /* Replace the to be deleted node with the max node. */
  194.   child->left = node->left;
  195.   child->right = node->right;
  196.   child->parent = node->parent;
  197.  
  198.   if (child->left != NULL) {
  199.     child->left->parent = child;
  200.   }
  201.  
  202.   if (child->right != NULL) {
  203.     child->right->parent = child;
  204.   }
  205.  
  206.   if (node->parent == NULL) {
  207.     heap->min = child;
  208.   } else if (node->parent->left == node) {
  209.     node->parent->left = child;
  210.   } else {
  211.     node->parent->right = child;
  212.   }
  213.  
  214.   /* Walk down the subtree and check at each node if the heap property holds.
  215.    * It's a min heap so parent < child must be true.  If the parent is bigger,
  216.    * swap it with the smallest child.
  217.    */
  218.   for (;;) {
  219.     smallest = child;
  220.     if (child->left != NULL && less_than(child->left, smallest))
  221.       smallest = child->left;
  222.     if (child->right != NULL && less_than(child->right, smallest))
  223.       smallest = child->right;
  224.     if (smallest == child)
  225.       break;
  226.     heap_node_swap(heap, child, smallest);
  227.   }
  228.  
  229.   /* Walk up the subtree and check that each parent is less than the node
  230.    * this is required, because `max` node is not guaranteed to be the
  231.    * actual maximum in tree
  232.    */
  233.   while (child->parent != NULL && less_than(child, child->parent))
  234.     heap_node_swap(heap, child->parent, child);
  235. }
  236.  
  237. void heap_dequeue(struct heap* heap, heap_compare_fn less_than) {
  238.   heap_remove(heap, heap->min, less_than);
  239. }
  240.  
  241. int less_then(const struct heap_node *a, const struct heap_node *b) {
  242.   int result = a->id < b->id ? 1 : 0;
  243.   printf("less_then: a=%d < b=%d ---> %d\n", a->id, b->id, result);
  244.   return result;
  245. }
  246.  
  247. int main(int argc, char *argv[]) {
  248.  
  249.   struct heap *heap = malloc(sizeof(*heap));
  250.   heap_init(heap);
  251.  
  252.   int i;
  253.   for(i = 2; i > 0; --i) {
  254.     struct heap_node *heap_node = malloc(sizeof(*heap_node));
  255.     heap_node->id = i;
  256.     heap_insert(heap, heap_node, less_then);
  257.     printf("heap_min: %d\n", heap_min(heap)->id);
  258.   }
  259.  
  260.   // struct heap_node *h = heap_min(heap);
  261.   // printf("heap: %d %d %d %d %d\n", h->id, h->left->id, h->right->id, h->left->left->id, h->left->right->id);
  262.  
  263.   // struct heap_node *heap_node = malloc(sizeof(*heap_node));
  264.   // heap_node->id = 0;
  265.   // heap_insert(heap, heap_node, less_then);
  266.   // h = heap_min(heap);
  267.   // printf("heap: %d %d %d %d %d %d\n", h->id, h->left->id, h->right->id, h->left->left->id, h->left->right->id, h->right->left->id);
  268.  
  269.   return EXIT_SUCCESS;
  270. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement