设为首页 加入收藏

TOP

最小堆 / 优先队列(C语言实现)(一)
2014-11-23 19:52:16 来源: 作者: 【 】 浏览:9
Tags:最小 优先 队列 语言 实现

最近找实习,复习下数据结构方面的内容。

完全二叉树有两种形态,一种是:二叉树的所有子树要么没有孩子,要么一定有左孩子。另一种是:二叉树要么没有子树,要么一定左右子树都有。

堆是一种经过排序的完全二叉树,其中任一非终端节点的数据值均不大于(或不小于)其左孩子和右孩子节点的值。

最大堆和最小堆是二叉堆的两种形式。

最大堆:根结点的键值是所有堆结点键值中最大者。

最小堆:根结点的键值是所有堆结点键值中最小者。

在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高进先出 (largest-in,first-out)的行为特征。优先队列可以用堆来实现。

下面我们用数组来实现一个最小堆。

代码如下:

MinHeap.h

#ifndef DataStructures_MinHeap_h
#define DataStructures_MinHeap_h

struct MinHeap;
typedef struct MinHeap * MinPriorityQueue;
typedef int ElementType;

// 初始化堆
MinPriorityQueue initialize(int maxElements);

// 销毁堆
void destroy(MinPriorityQueue pqueue);

// 清空堆中的元素
void makeEmpty(MinPriorityQueue pqueue);

// 插入操作
void insert(ElementType x, MinPriorityQueue pqueue);

// 删除最小者操作,返回被删除的堆顶元素
ElementType deleteMin(MinPriorityQueue pqueue);

// 查找最小者(堆顶)
ElementType findMin(MinPriorityQueue pqueue);

// 判断堆是否为空
int isEmpty(MinPriorityQueue pqueue);

// 判断堆是否满
int isFull(MinPriorityQueue pqueue);

// 通过一个数组来建堆,相当于将用数组实现的无序树转换为堆序树
MinPriorityQueue buildHeap_insert(int *arr, int n);
MinPriorityQueue buildHeap_percolate(int *arr, int n);

// 打印堆
void printMinPriorityQueue(MinPriorityQueue pqueue);

#endif

MinHeap.c

#include 
  
   
#include 
   
     #include "MinHeap.h" /* 标记节点,类似于链表中的表头节点 * 该值必须小于所有最小堆中的元素,设其值为-1 */ #define SentinelElement -1 /* * 使用数组实现堆 * * capacity 数组的最大容量 * size 数组的长度 * elements 堆中的元素存放的数组 */ struct MinHeap { int capacity; int size; ElementType *elements; // 堆的元素个数为size,实际上用来存储的数组的长度为size + 1,还包括一个sentinel元素 }; void PQueueNULLWarning() { printf("Warning: Minimum Priority Queue is NULL"); } void outOfSpaceFatalError() { printf("Fatal Error: Out of space"); abort(); } MinPriorityQueue initialize(int maxElements) { MinPriorityQueue pqueue; if (maxElements <= 0) { printf("Fail to initialize: maxElements <= 0"); return NULL; } pqueue = malloc(sizeof(struct MinHeap)); if (pqueue == NULL) outOfSpaceFatalError(); // 数组的第0个元素是个sentinel标记节点,计入数组容量中,但不计入capcaity或size中 pqueue->size = 0; pqueue->capacity = maxElements; pqueue->elements = malloc(sizeof(ElementType) * (pqueue->capacity + 1)); if (pqueue->elements == NULL) outOfSpaceFatalError(); else pqueue->elements[0] = SentinelElement; return pqueue; } void destroy(MinPriorityQueue pqueue) { if (pqueue != NULL) { // 在GNU99标准中,free(NULL)什么都不做直接返回,所以不用判断pqueue->elements是否为NULL free(pqueue->elements); free(pqueue); } } void makeEmpty(MinPriorityQueue pqueue) { if (pqueue != NULL) pqueue->size = 0; else PQueueNULLWarning(); } /* * 插入时,堆中的元素执行下滤操作 * 删除时,堆中的元素执行上滤操作 */ /* * 插入的时间复杂度为O(log N),N为最小堆中的元素个数 * 实际上,其平均执行时间为O(1) */ void insert(ElementType x, MinPriorityQueue pqueue) { if (pqueue == NULL) PQueueNULLWarning(); if (isFull(pqueue)) { printf("Fail to insert: Priority Queue is Full"); return; } else { int i; // sentinel element在这里作为elements[0]被比较,是循环的终止条件 for (i = ++pqueue->size; x < pqueue->elements[i / 2]; i /= 2) pqueue->elements[i] = pqueue->elements[i / 2]; // 下滤操作 pqueue->elements[i] = x; } } /* * 删除操作的平均时间为O(log N) */ ElementType deleteMin(MinPriorityQueue pqueue) { if (pqueue == NULL) { PQueueNULLWarning(); return SentinelElement; } if (isEmpty(pqueue)) { printf("Fail to delete: Priority Queue is Empty"); return SentinelElement; } int i, child; ElementType minElement, lastElement; // 注意对某个节点进行上滤操作时,要判断该节点是有两个儿子还是一个儿子 minElement = pqueue->elements[1]; lastElement = pqueue->elements[pqueue->size--]; for (i = 1; i * 2 <= pqueue->size; i = child) { child = i * 2; // 节点i只有一个儿子时必有i * 2 = pqueue->size if (child < pqueue->size && pqueue->elements[child] > pqueue->elements[child + 1]) child++; if (lastElement < pqueue->elements[child]) break; else pqu
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C语言中的柔性数组 下一篇Objective-c史上最全字符串处理

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: