《数据结构与算法分析——c语言描述》 第六章
代码和二叉堆差不多,有意思的是父亲,儿子编号的推导。
第i行,第j行节点(均从1开始)的编号推导:
前面i-1行的节点加起来:
1+d1+d2+d3+……+di−2=1−di−11−d
然后加上剩下的,就是
1−di−11−d+j
第一个儿子就是
1−di1−d+(j−1)∗d+1
父亲和儿子的关系就是(这个就是强行凑,参考了 让阳光照进心里)
(father−1)∗D+2
binheap.h
#ifndef _BinHeap_H
#define D 4 //d堆的设置
typedef int ElementType;
struct HeapStruct;
typedef struct HeapStruct *PriorityQueue;
PriorityQueue initialize(int maxElements);
PriorityQueue buildHeap(ElementType *arr, int n);
void destroy(PriorityQueue h);
void makeEmpty(PriorityQueue h);
void insert(ElementType X, PriorityQueue h);
ElementType deleteMin(PriorityQueue h);
int isEmpty(PriorityQueue h);
int isFull(PriorityQueue h);
void decreaseKey(int pos, ElementType delta, PriorityQueue h);
void increaseKey(int pos, ElementType delta, PriorityQueue h);
void Delete(int pos, PriorityQueue h);
#endif // !_BinHeap_H
binheap.c
#include"binheap.h"
#include"fatal.h"
#define MinPQSize 4
#define MinData INT_MIN
struct HeapStruct {
int capacity;
int size;
ElementType* elements;
};
static int firstSonCursor(int pos) {
return (pos - 1) * D + 2;//见日志说明
}
static int faterCursor(int pos) {
if (pos == 1)//这个是必须的,否则pos为1的时候还是返回1,那么就不能调用mindata
return 0;
return (pos - 2) / D + 1;
}
PriorityQueue initialize(int maxElements) {
PriorityQueue h;
if (maxElements < MinPQSize)
Error("Priority queue size is too small");
h = malloc(sizeof(struct HeapStruct));
if (h == NULL)
Error("OUT OF MEMORY");
h->elements = malloc(sizeof(ElementType)*(maxElements + 1));//多出来的一个用于存放最小的元素,其用来和堆顶比较
if (h->elements == NULL)
Error("OUT OF MEMORY");
h->capacity = maxElements;
h->size = 0;
h->elements[0] = MinData;
return h;
}
static void percolateDown(int pos, PriorityQueue h) {
ElementType elem = h->elements[pos];
int i, minChild;
for (i = pos; i < h->size; i = minChild) {
int firstChild = firstSonCursor(i);//
minChild = firstChild;
if (firstChild > h->size)
break;
for (int i = 1; (firstChild + i) <= h->size && i < D; i++) {//直接从第二个儿子开始比较
if (h->elements[minChild] > h->elements[firstChild + i])
minChild = firstChild + i;
}
if (elem > h->elements[minChild])
h->elements[i] = h->elements[minChild];
else
break;
}
h->elements[i] = elem;
}
static void percolateUp(int pos, PriorityQueue h) {
int i;
ElementType elem = h->elements[pos];
for (i = pos; h->elements[faterCursor(i)] > elem; i = faterCursor(i)) {
h->elements[i] = h->elements[faterCursor(i)];
}
h->elements[i] = elem;
}
PriorityQueue buildHeap(ElementType *arr, int n) {
PriorityQueue h = initialize(n);
h->size = n;
for (int i = 0; i < n; i++) {
h->elements[i + 1] = arr[i];
}
for (int i = faterCursor(n); i > 0; i--) {
percolateDown(i, h);
}
return h;
}
void destroy(PriorityQueue h) {
free(h->elements);
free(h);
}
void makeEmpty(PriorityQueue h) {
h->size = 0;
}
void insert(ElementType X, PriorityQueue h) {
if (isFull(h))
Error("priority queue is full");
h->elements[++h->size] = X;
percolateUp(h->size, h);
}
ElementType deleteMin(PriorityQueue h) {//
ElementType minElement;
if (isEmpty(h))
Error("priority queue is empty");
minElement = h->elements[1];
h->elements[1] = h->elements[h->size--];//删除右下的元素
percolateDown(1, h);
return minElement;
}
int isEmpty(PriorityQueue h) {
return h->size == 0;
}
int isFull(PriorityQueue h) {
return h->size == h->capacity;
}
void decreaseKey(int pos, ElementType delta, PriorityQueue h) {
if (pos<1 || pos>h->size)
Error("Positon Error");
h->elements[pos] -= delta;
percolateUp(pos, h);
}
void increaseKey(int pos, ElementType delta, PriorityQueue h) {
if (pos<1 || pos>h->size)
Error("Positon Error");
h->elements[pos] += delta;
percolateDown(pos, h);
}
void Delete(int pos, PriorityQueue h) {
if (pos<1 || pos>h->size)
Error("Positon Error");
for (int i = pos; i > 1; i= faterCursor(i)) {
h->elements[i] = h->elements[faterCursor(i)];
}
deleteMin(h);
}
main.c
#include"binheap.h"
#include<stdlib.h>
#include<stdio.h>
#include"fatal.h"
#define N 6
int RandInt(int i, int j) {
int temp;
temp = (int)(i + (1.0*rand() / RAND_MAX)*(j - i));
return temp;
}
void getRandomInt(int *A, int n) {
for (int i = 0; i < n; i++) {
A[i] = i + 1;
}
for (int i = 1; i < n; i++) {
//std::swap(A[i], A[RandInt(0, i)]);
int randAdrr = RandInt(0, i);
int t = A[i];
A[i] = A[randAdrr];
A[randAdrr] = t;
}
}
struct HeapStruct {
int capacity;
int size;
ElementType* elements;
};
int main() {
PriorityQueue h = initialize(N);
int a[N];
getRandomInt(a, N);
for (int i = 0; i < N; i++) {
insert(a[i], h);
}
for (int i = 0; i < N; i++) {
printf("%d ", deleteMin(h));
}
destroy(h);
printf("\n");
h = buildHeap(a, N);
for (int i = 0; i < N; i++) {
printf("%d ", deleteMin(h));
}
destroy(h);
}