⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 heap.c

📁 掌握如何用C来实现各种算法
💻 C
字号:
/*****************************************************************************
*                                                                            *
*  -------------------------------- heap.c --------------------------------  *
*                                                                            *
*****************************************************************************/

#include <stdlib.h>
#include <string.h>

#include "heap.h"

/*****************************************************************************
*                                                                            *
*  Define private macros used by the heap implementation.                    *
*                                                                            *
*****************************************************************************/

#define heap_parent(npos) ((int)(((npos) - 1) / 2))

#define heap_left(npos) (((npos) * 2) + 1)

#define heap_right(npos) (((npos) * 2) + 2)

/*****************************************************************************
*                                                                            *
*  ------------------------------- heap_init ------------------------------  *
*                                                                            *
*****************************************************************************/

void heap_init(Heap *heap, int (*compare)(const void *key1, const void *key2),
   void (*destroy)(void *data)) {

/*****************************************************************************
*                                                                            *
*  Initialize the heap.                                                      *
*                                                                            *
*****************************************************************************/

heap->size = 0;
heap->compare = compare;
heap->destroy = destroy;
heap->tree = NULL;

return;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- heap_destroy -----------------------------  *
*                                                                            *
*****************************************************************************/

void heap_destroy(Heap *heap) {

int                i;

/*****************************************************************************
*                                                                            *
*  Remove all the nodes from the heap.                                       *
*                                                                            *
*****************************************************************************/

if (heap->destroy != NULL) {

   for (i = 0; i < heap_size(heap); i++) {

      /***********************************************************************
      *                                                                      *
      *  Call a user-defined function to free dynamically allocated data.    *
      *                                                                      *
      ***********************************************************************/

      heap->destroy(heap->tree[i]);

   }

}

/*****************************************************************************
*                                                                            *
*  Free the storage allocated for the heap.                                  *
*                                                                            *
*****************************************************************************/

free(heap->tree);

/*****************************************************************************
*                                                                            *
*  No operations are allowed now, but clear the structure as a precaution.   *
*                                                                            *
*****************************************************************************/

memset(heap, 0, sizeof(Heap));

return;

}

/*****************************************************************************
*                                                                            *
*  ------------------------------ heap_insert -----------------------------  *
*                                                                            *
*****************************************************************************/

int heap_insert(Heap *heap, const void *data) {

void               *temp;

int                ipos,
                   ppos;

/*****************************************************************************
*                                                                            *
*  Allocate storage for the node.                                            *
*                                                                            *
*****************************************************************************/

if ((temp = (void **)realloc(heap->tree, (heap_size(heap) + 1) * sizeof
   (void *))) == NULL) {

   return -1;

   }

else {

   heap->tree = temp;

}

/*****************************************************************************
*                                                                            *
*  Insert the node after the last node.                                      *
*                                                                            *
*****************************************************************************/

heap->tree[heap_size(heap)] = (void *)data;

/*****************************************************************************
*                                                                            *
*  Heapify the tree by pushing the contents of the new node upward.          *
*                                                                            *
*****************************************************************************/

ipos = heap_size(heap);
ppos = heap_parent(ipos);

while (ipos > 0 && heap->compare(heap->tree[ppos], heap->tree[ipos]) < 0) {

   /**************************************************************************
   *                                                                         *
   *  Swap the contents of the current node and its parent.                  *
   *                                                                         *
   **************************************************************************/

   temp = heap->tree[ppos];
   heap->tree[ppos] = heap->tree[ipos];
   heap->tree[ipos] = temp;

   /**************************************************************************
   *                                                                         *
   *  Move up one level in the tree to continue heapifying.                  *
   *                                                                         *
   **************************************************************************/

   ipos = ppos;
   ppos = heap_parent(ipos);

}

/*****************************************************************************
*                                                                            *
*  Adjust the size of the heap to account for the inserted node.             *
*                                                                            *
*****************************************************************************/

heap->size++;

return 0;

}

/*****************************************************************************
*                                                                            *
*  ----------------------------- heap_extract -----------------------------  *
*                                                                            *
*****************************************************************************/

int heap_extract(Heap *heap, void **data) {

void               *save,
                   *temp;

int                ipos,
                   lpos,
                   rpos,
                   mpos;

/*****************************************************************************
*                                                                            *
*  Do not allow extraction from an empty heap.                               *
*                                                                            *
*****************************************************************************/

if (heap_size(heap) == 0)
   return -1;

/*****************************************************************************
*                                                                            *
*  Extract the node at the top of the heap.                                  *
*                                                                            *
*****************************************************************************/

*data = heap->tree[0];

/*****************************************************************************
*                                                                            *
*  Adjust the storage used by the heap.                                      *
*                                                                            *
*****************************************************************************/

save = heap->tree[heap_size(heap) - 1];

if (heap_size(heap) - 1 > 0) {

   if ((temp = (void **)realloc(heap->tree, (heap_size(heap) - 1) * sizeof
      (void *))) == NULL) {

      return -1;

      }

   else {

      heap->tree = temp;

   }

   /**************************************************************************
   *                                                                         *
   *  Adjust the size of the heap to account for the extracted node.         *
   *                                                                         *
   **************************************************************************/

   heap->size--;

   }

else {

   /**************************************************************************
   *                                                                         *
   *  Manage the heap when extracting the last node.                         *
   *                                                                         *
   **************************************************************************/

   free(heap->tree);
   heap->tree = NULL;
   heap->size = 0;
   return 0;

}

/*****************************************************************************
*                                                                            *
*  Copy the last node to the top.                                            *
*                                                                            *
*****************************************************************************/

heap->tree[0] = save;

/*****************************************************************************
*                                                                            *
*  Heapify the tree by pushing the contents of the new top downward.         *
*                                                                            *
*****************************************************************************/

ipos = 0;
lpos = heap_left(ipos);
rpos = heap_right(ipos);

while (1) {

   /**************************************************************************
   *                                                                         *
   *  Select the child to swap with the current node.                        *
   *                                                                         *
   **************************************************************************/

   lpos = heap_left(ipos);
   rpos = heap_right(ipos);

   if (lpos < heap_size(heap) && heap->compare(heap->tree[lpos], heap->
      tree[ipos]) > 0) {

      mpos = lpos;

      }

   else {

      mpos = ipos;

   }

   if (rpos < heap_size(heap) && heap->compare(heap->tree[rpos], heap->
      tree[mpos]) > 0) {

      mpos = rpos;

   }

   /**************************************************************************
   *                                                                         *
   *  When mpos is ipos, the heap property has been restored.                *
   *                                                                         *
   **************************************************************************/

   if (mpos == ipos) {

      break;

      }

   else {

      /***********************************************************************
      *                                                                      *
      *  Swap the contents of the current node and the selected child.       *
      *                                                                      *
      ***********************************************************************/

      temp = heap->tree[mpos];
      heap->tree[mpos] = heap->tree[ipos];
      heap->tree[ipos] = temp;

      /***********************************************************************
      *                                                                      *
      *  Move down one level in the tree to continue heapifying.             *
      *                                                                      *
      ***********************************************************************/

      ipos = mpos;

   }

}

return 0;

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -