优先队列(堆)——二叉堆的实现
2013-09-08 19:57
567 查看
一般数据结构中的堆指的是二叉堆(Binary heap)。堆是一棵完全二叉树,可用数组来表示。对于数组中任意位置i上的元素,其左儿子在位置2i上,右儿子在左儿子后的单元(2i+1)中,它的父亲在位置[i/2](整数除法)上。
在堆实现过程中下表为0的元素作为标记(这个值必须小于其中的任何一个值),用标记只是为了减少判断次数。
fatal.h定义错误处理
binheap.h函数声明
运行结果分析
插入法新建堆,如下图所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202005/11/97fec5ecca6ce76572293d1dbb1b311c)
线性时间构建堆,如下图所示:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202005/11/997eba0b28d8b34442b55714fb575897)
程序运行结果,层序输出结果:
在堆实现过程中下表为0的元素作为标记(这个值必须小于其中的任何一个值),用标记只是为了减少判断次数。
fatal.h定义错误处理
#include <stdio.h> #include <stdlib.h> #define Error(Str) fprintf(stderr, "%s\n", Str),exit(1) #define FatalError(Str) Error(Str)
binheap.h函数声明
typedef int ElementType; #ifndef BINHEAP_H #define BINHEAP_H typedef unsigned int Position; struct HeapStruct { int Capacity; int Size; ElementType *Elements; }; typedef struct HeapStruct *PriorityQueue; PriorityQueue Initialize(int MaxElements);//初始化堆 void Destory(PriorityQueue H);//销毁堆 int IsFull(PriorityQueue H);//是否已满 int IsEmpty(PriorityQueue H);//是否为空 void MakeEmpty(PriorityQueue H);//清空堆 void Insert(ElementType X, PriorityQueue H);//插入元素 ElementType DeleteMin(PriorityQueue H);//删除根 ElementType FindMin(PriorityQueue H);//查找最小值 void Delete(Position P, PriorityQueue H);//删除任意节点 void DecreaseKey(Position P, ElementType Delta, PriorityQueue H);//降低关键字值Delta void IncreaseKey(Position P, ElementType Delta, PriorityQueue H);//增加关键字值Delta PriorityQueue BuildHeap(ElementType A[], int N);//构建堆 #endifbinheap.c函数实现
#include "fatal.h" #include "binheap.h" #include <stdlib.h> #define MinPQSize (10) #define MinData (-32767) PriorityQueue Initialize(int MaxElements) { PriorityQueue H; if(MaxElements < MinPQSize) { Error("Priority queue size too small"); return NULL; } H = (PriorityQueue)malloc(sizeof(struct HeapStruct)); if(H == NULL) FatalError("Out of space"); H->Elements = (ElementType *)malloc(sizeof(ElementType) * (MaxElements + 1));//多申请一个空间用用作标记 if(H->Elements == NULL) FatalError("Out of space"); H->Capacity = MaxElements; H->Size = 0; H->Elements[0] = MinData;//0号元素作为标记 return H; } void Destory(PriorityQueue H) { free(H->Elements); free(H); } int IsFull(PriorityQueue H) { return H->Size == H->Capacity; } int IsEmpty(PriorityQueue H) { return H->Size == 0; } void MakeEmpty(PriorityQueue H) { H->Size = 0; } void Insert(ElementType X, PriorityQueue H) { int i; if(IsFull(H)) { Error("Priority queue is full"); return; } for(i = ++H->Size; H->Elements[i/2] > X; i /= 2)//采用上滤法进行插入,插入点到根路径上查找应该插入的位置 H->Elements[i] = H->Elements[i/2]; H->Elements[i] = X; } ElementType DeleteMin(PriorityQueue H) { int i, child; ElementType MinElement, LastElement; if(IsEmpty(H)) { Error("Priority queue is empty"); return H->Elements[0]; } MinElement = H->Elements[1]; LastElement = H->Elements[H->Size--]; for(i = 1; i * 2 <= H->Size; i = child)//采用下滤法。删除根节点后,将根的孩子节点中较小的一个上移,直到到达叶子节点,然后将最后一个元素的值复制给叶子节点。 { child = i * 2; if(child != H->Size && H->Elements[child + 1] < H->Elements[child]) child++; if(LastElement > H->Elements[child]) H->Elements[i] = H->Elements[child]; else break; } H->Elements[i] = LastElement; return MinElement; } ElementType FindMin(PriorityQueue H) { if(IsEmpty(H)) { Error("Priority queue is empty"); return H->Elements[0]; } return H->Elements[1]; } static void PercolateDown(int n, PriorityQueue H)//下滤 { int i, child; ElementType Tmp; Tmp = H->Elements ; for(i = n; i * 2 <= H->Size; i = child) { child = i * 2; if(child != H->Size && H->Elements[child + 1] < H->Elements[child]) child++; if(Tmp > H->Elements[child]) H->Elements[i] = H->Elements[child]; else break; } H->Elements[i] = Tmp; } static void PercolateUp(int n, PriorityQueue H)//上滤 { int i; ElementType Tmp; Tmp = H->Elements ; for(i = n; H->Elements[i] < H->Elements[i/2]; i /= 2) H->Elements[i] = H->Elements[i/2]; H->Elements[i] = Tmp; } void Delete(Position P, PriorityQueue H)//降低关键字的值,使它小于根节点然后删除根节点即可完成该操作 { DecreaseKey(P, H->Elements[P], H); DeleteMin(H); } void DecreaseKey(Position P, ElementType Delta, PriorityQueue H)//降低关键字的值后采用上滤,将节点上调 { H->Elements[P] -= Delta; PercolateUp(P, H); } void IncreaseKey(Position P, ElementType Delta, PriorityQueue H)//增加关键字的值后采用下滤 { H->Elements[P] += Delta; PercolateDown(P, H); } PriorityQueue BuildHeap(ElementType A[], int N) { PriorityQueue H; int i; H = Initialize(N); for(i = 1; i <= N; i++) H->Elements[i] = A[i-1]; H->Size = H->Capacity; for(i = N / 2; i > 0; i--) PercolateDown(i, H); return H; }testmain.c测试
#include <stdio.h> #include <stdlib.h> #include "binheap.h" #define N 15 int main(void) { PriorityQueue H; int arr = {10,12,1,14,6,5,8,15,3,9,7,4,11,13,2}; int i; H = Initialize(N); for(i = 0; i < N; i++)//插入法新建堆 Insert(arr[i], H); for(i = 1; i <= N; i++) printf("%d ", H->Elements[i]); printf("\n"); Delete(3, H);//删除跟的右孩子 printf("after delete(%d):\n", 3); for(i = 1; i < N; i++) printf("%d ", H->Elements[i]); printf("\n"); Destory(H); H = BuildHeap(arr, N);//新建完全二叉树,然后调整为堆,时间复杂度为O(N) for(i = 1; i <= N; i++) printf("%d ", H->Elements[i]); printf("\n"); system("Pause"); return 0; }
运行结果分析
插入法新建堆,如下图所示:
线性时间构建堆,如下图所示:
程序运行结果,层序输出结果:
相关文章推荐
- 优先队列之二叉堆(JAVA实现)
- 优先队列的Java实现(最大二叉堆)
- 自己写GoBinaryHead 二叉堆binaryheap实现优先队列(堆)
- 优先队列二叉堆 C语言实现
- 优先队列(二叉堆)的基本实现
- 二叉堆(binary heap)—— 优先队列的实现
- C#实现优先队列 基于二叉堆 附使用案例
- 【数据结构】实现大小堆也叫二叉堆(类似c++中的优先队列)
- 用有序二叉堆实现优先队列
- 优先队列的数组、二叉堆实现
- (数据结构与算法分析 七)------优先队列中的二叉堆的实现( Java语言描述)
- 二叉堆,堆排序,STL优先队列的底层实现,剑指offer数据流中的中位数
- 算法学习 - 优先队列的二叉堆实现
- 优先队列——二叉堆实现
- [模板] 二叉堆 - 优先队列的二叉堆数组实现
- 排序算法之——优先队列经典实现(基于二叉堆)
- 基于二叉堆实现的优先队列和堆排序
- 数据结构之优先队列--二叉堆(Java实现)
- 使用二叉堆实现优先队列
- 自己实现一个简单的优先队列-二叉堆