Heap.h
#ifndef _HEAP_H_
#define _HEAP_H_
typedef int DataType;
#include<assert.h>
#include<stdlib.h>
typedef int (*Pcompare)(DataType left, DataType right);
typedef struct Heap
{
DataType *hp;
int capacity;
int size;
Pcompare compare;
}Heap;
typedef struct QueuePri
{
Heap Pri;
}QueuePri;
int Less(DataType left, DataType right);
int Greater(DataType left, DataType right);
void CreatHeap(Heap *q, int *arr, int size,Pcompare compare);
void DownAdjust(Heap *q, int parent, int size);
void HeapPush(Heap *q, DataType data);
void RemoveHeap(Heap *q);
void MaxKnum(Heap *q, int K);
void HeapSort(Heap *q);
#endif _HEAP_H_
heap.c
#include"Heap.h"
//判断小于的函数
int Less(DataType left, DataType right)
{
return (left) < (right);
}
//判断大于的函数
int Greater(DataType left, DataType right)
{
return (left) > (right);
}
//交换两个值
void Swap(DataType *ret, DataType *cur)
{
DataType tmp = *ret;
*ret = *cur;
*cur = tmp;
}
//向下调整
void DownAdjust(Heap *q, int parent, int size)
{
int child = (parent<<1)+1;
assert(q);
//当孩子的序号大于元素个数时,调整完成
while(child < size)
{
//判断当前节点有没有右孩子,如果有右孩子,比较左右孩子哪一个较小
//用child记录较小值的序号
if(child+1 < size && q->compare((q->hp[child+1]),q->hp[child]))
{
child +=1;
}
//然后,如果双亲节点大于孩子节点的话,让双亲节点与较小的孩子节点交换值
//然后,将双亲节点等于孩子节点的序号,然后再把左孩子的节点序号复值给孩子节点,这样一直向下调整
if(q->compare((q->hp[child]) , q->hp[parent]))
{
Swap(&q->hp[parent], &q->hp[child]);
parent = child;
child = (parent<<1)+1;
}
//如果双亲节点的值小于孩子节点,那么就不用再调整
else
{
return;
}
}
}
//创建堆
void CreatHeap(Heap *q, int *arr, int size, Pcompare compare)
{
int i = 0;
DataType *ret = NULL;
assert(q);
ret = (DataType *)malloc(sizeof(int)*size);
if(ret == NULL)
{
assert(0);
}
q->hp = ret;
q->compare = compare;
//将数组内的数据拷入堆内
for(i = 0; i < size; i++)
{
q->hp[i] = arr[i];
}
q->capacity = size;
q->size = size;
//对于有孩子节点的节点进行向下调整
for(i = (size-2)/2; i >= 0; i--)
DownAdjust(q, i, size);
}
//堆的增容
void Capacityexpan(Heap *q)
{
int i = 0;
DataType *ret = NULL;
assert(q);
ret = (DataType *)malloc(sizeof(DataType)*(q->capacity<<1));
if(NULL == ret)
{
assert(0);
}
//将原空间的数据拷贝如新空间中
for(i = 0; i < q->size; i++)
{
ret[i] = q->hp[i];
}
free(q->hp);
q->hp = ret;
q->capacity *= 2;
}
//堆的插入
void HeapPush(Heap *q, DataType data)
{
int child = 0;//记录插入节点的下标
int parent = 0;//记录插入节点的双亲的下标
//判断堆是否还有容量
if(q->capacity == q->size)
{
Capacityexpan(q);
}
q->hp[q->size] = data;
q->size += 1;
child = q->size-1;
parent = (child-1)>>1;
//向上调整法
//用插入的节点与自己的双亲节点比较,如果比双亲节点小的话,就交换,然后再与交换后的双亲比较,直到调整到根节点时停止
while(child)
{
//判断孩子节点的值与其双亲的值那个大,如果双亲的值大于孩子的值,交换孩子与双亲的值
if(q->compare((q->hp[child]) , q->hp[parent]))
{
Swap(&q->hp[child], &q->hp[parent]);
child = parent;
parent = (child-1)>>1;
}
//如果双亲的值小于孩子的值的话,代表此时,堆是有序的,不用调整
else
return;
}
}
//删除
//用最后一个节点的值代替堆顶的值,将元素的个数减一
//然后进行向下调整
void RemoveHeap(Heap *q)
{
assert(q);
//将堆顶的元素替换为堆底的元素
q->hp[0] = q->hp[q->size-1];
q->size -= 1;
DownAdjust(q, 0, q->size);
}
//取堆顶的元素
DataType HeapTopCell(Heap *q)
{
assert(q);
return q->hp[0];
}
//取堆底的元素
DataType HeapBase(Heap *q)
{
assert(q);
return q->hp[q->size-1];
}
//判断堆是否为空
int EmptyHeap(Heap *q)
{
assert(q);
return q->size == 0;
}
//堆的销毁
void DestroyHeap(Heap *q)
{
assert(q);
free(q->hp);
q->hp = NULL;
}
//给出海量的数据,求最大的K个数)
//给出海量的数据,求最大的K个数)
void MaxKnum(Heap *q, int K)
{
int i = K;
DataType *ret = NULL;
assert(q);
ret = (DataType *)malloc(sizeof(DataType)*K);
if(ret == NULL)
{
assert(0);
}
q->hp = ret;
//首先取前K个数,用这K个数来创建一个小堆
for(i = 0; i < K; i++)
{
int tmp = rand()%10000;
q->hp[i] = tmp;
}
q->size = K;
q->capacity = K;
for(i = (K-2)/2; i >= 0; i--)
DownAdjust(q, i, K);
//然后,一个一个的取数组内剩下的数,取出的数与堆顶的元素比较,如果比堆顶的元素大的话,就用取出的元素
//代替堆顶的元素,代替之后再进行向下的调整,使堆重新满足小堆的特性,然后再从数组内取数据,重复上述操作,直到所有的数组为空时
for(i = K; i < 10000-K; i++)
{
int tmp = rand()%10000;
if(tmp > q->hp[0])
{
Swap(&tmp, &q->hp[0]);
DownAdjust(q, 0, K);
}
}
}
//堆排序
//如果是降序的话, 建一个小堆
//然后,先将小堆的堆顶的值与堆底的值交换,这样最小值就到了堆底,然后调整的元素个数-1,向下法调整交换后的堆
//调整好的堆最小值又在堆顶,然后再次与最后的元素交换,直到元素个数为0时停止
void HeapSort(Heap *q)
{
int i = q->size;
assert(q);
i = q->size;
while(i)
{
//交换堆底和堆顶的元素
Swap(&q->hp[i-1], &q->hp[0]);
//把最小值放到堆底之后,元素个数-1;
--i;
//调整剩下的几个元素的堆
DownAdjust(q, 0, i);
}
}
//堆的初始化
void HeapInit(QueuePri *q, Pcompare compare)
{
Heap *ret = NULL;
assert(q);
//刚开始给十个元素的空间
ret = (Heap*)malloc(sizeof(DataType)*10);
if(NULL == ret)
{
assert(0);
return ;
}
q->Pri.compare = compare;
q->Pri.size = 0;
q->Pri.capacity = 3;
}
//队列的优先级
//队列的初始化
void InitPriorityQueue(QueuePri* q)
{
assert(q);
HeapInit(q, Less);
}
//队列的插入
void PushPriorityQueue(QueuePri *q, DataType data)
{
assert(q);
HeapPush(&q->Pri, data);
}
//队列的删除
void PopPriorityQueue(QueuePri *q)
{
assert(q);
RemoveHeap(&q->Pri);
}
//队头元素
void PriorityQueueTopNode(QueuePri *q)
{
assert(q);
HeapTopCell(&q->Pri);
}
//队列是否为空
int EmptyPriorityQueue(QueuePri *q)
{
assert(q);
return EmptyHeap(&q->Pri);
}
//队列的元素个数
int SizePriorityQueue(QueuePri *q)
{
assert(q);
return q->Pri.size;
}
Heap.c
#include"Heap.h"
void HeapText()
{
Heap q = {0};
Heap cur = {0};
int a[] = {1,2,3,4,5,6,7,8,9,11,22,41};
int arr[] = {3,4,2,9,7,8,1};
CreatHeap(&q, arr, sizeof(arr)/sizeof(arr[0]), Less);
HeapPush(&q, 5);
RemoveHeap(&q);
MaxKnum(&cur,5);
HeapSort(&q);
DestroyHeap(&q);
}
int main()
{
HeapText();
return 0;
}