堆及堆的應用
阿新 • • 發佈:2018-12-10
Heap.h
#ifndef __HEAP_H__
#define __HEAP_H__
typedef int HPDataType;
typedef struct Heap
{
HPDataType* _hp;
int _capacity;
int _size;
}Heap;
typedef struct PriorityQueue
{
Heap hp;
}PriorityQueue;
void CreatHeap(Heap* hp, int* array, int size);//建立堆
void InitHeap(Heap* hp); // 初始化堆
void PrintHeap(Heap hp);//列印堆
void InsertHeap(Heap* hp, HPDataType data);//插入資料
void RemoveHeap(Heap* hp);//刪除堆頂元素
int SizeHeap(Heap*hp);//堆大小
int EmptyHeap(Heap* hp);//判空
HPDataType TopHeap(Heap* hp);//找出堆頂元素
void AdjustDown(Heap* hp, int parent);//向下調整
void AdjustUp(Heap* hp, int child);//向上調整
void _CheakCapacity(Heap* hp);//擴容
void DestroyHeap(Heap* hp); // 銷燬堆
int Less(HPDataType left, HPDataType right); // 小於比較
int Greater(HPDataType left, HPDataType right); // 大於比較
void InitPriorityQueue(PriorityQueue* q);
void PushPriorityQueue(PriorityQueue* q, HPDataType data);
void PopPriorityQueue(PriorityQueue* q);
int TopPriorityQueue(PriorityQueue* q);
int SizePriorityQueue(PriorityQueue* q);
int EmptyPriorityQueue(PriorityQueue* q);
void Topk(Heap* q, int k);//海量資料中的topk問題
void HeapSort(Heap *q);//堆排序
Heap.c
#include "Heap.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
void CreatHeap(Heap* hp, int* array, int size)
{
int i = 0;
int root = (size-2)/2;
assert(hp);
hp->_hp = (HPDataType*)malloc(sizeof(HPDataType)*size);
if(NULL == hp->_hp)
{
assert(hp);
return;
}
hp->_capacity = size;
hp->_size = size;
for(i=0;i<size;i++)
{
hp->_hp[i] = array[i];
}
for(i=root;i>=0;i--)
{
AdjustDown(hp,i);
}
}
void InitHeap(Heap* hp)
{
assert(hp);
hp->_hp = (HPDataType*)malloc(sizeof(HPDataType));
if(NULL == hp->_hp)
{
return;
}
hp->_capacity = 1;
hp->_size = 0;
}
void PrintHeap(Heap hp)
{
int i = 0;
for(i=0;i< hp._size;i++)
{
printf("%d ", hp._hp[i]);
}
}
void Swap(int* left,int* right)
{
int temp = 0;
temp = *left;
*left = *right;
*right = temp;
}
int Greater(HPDataType left, HPDataType right)
{
if (left > right)
return 1;
return 0;
}
int Less(HPDataType left, HPDataType right)
{
if (left < right)
return 1;
return 0;
}
void AdjustDown(Heap* hp, int parent)
{
int child = 2*parent+1;
assert(hp);
while(child < hp->_size)
{
if(Greater(hp->_hp[child],hp->_hp[child+1]) && (child+1) < hp->_size)
{
child = child+1;
}
if(Greater(hp->_hp[parent] , hp->_hp[child]))
{
Swap(&hp->_hp[parent],&hp->_hp[child]);
parent = child;
child = 2*parent+1;
}
else
return;
}
}
void AdjustUp(Heap* hp, int child)
{
int parent = (child-1)/2;
assert(hp);
while(child != 0)
{
if(Greater(hp->_hp[parent],hp->_hp[child]))
{
Swap(&hp->_hp[parent],&hp->_hp[child]);
child = parent;
parent = (child-1)/2;
}
else
return;
}
}
void _CheakCapacity(Heap* hp)
{
int i = 0;
assert(hp);
if(hp->_capacity == hp->_size)
{
hp->_hp = (HPDataType*)realloc(hp->_hp,sizeof(HPDataType)*(hp->_capacity)*2);
if(NULL == hp->_hp)
{
return;
}
hp->_capacity = 2*hp->_capacity;
}
}
void InsertHeap(Heap* hp, HPDataType data)
{
int i = 0;
assert(hp);
_CheakCapacity(hp);
hp->_hp[hp->_size++] = data;
AdjustUp(hp,hp->_size-1);
}
int EmptyHeap(Heap* hp)
{
assert(hp);
if (hp->_size == 0)
return 1;
return 0;
}
void RemoveHeap(Heap* hp)
{
assert(hp);
//判斷堆是否為空
if (EmptyHeap(hp))
return;
//先將堆頂元素和堆尾元素交換,並刪除堆尾元素
Swap(&(hp->_hp[0]), &hp->_hp[hp->_size - 1]);
hp->_size--;
//用向下調整法調整佇列
AdjustDown(hp, 0);
}
int SizeHeap(Heap*hp)
{
assert(hp);
return hp->_size;
}
HPDataType TopHeap(Heap* hp)
{
assert(hp);
if (hp->_size == 0)
{
return 0;
}
return hp->_hp[0];
}
void DestroyHeap(Heap* hp)
{
assert(hp);
hp->_size = 0;
hp->_capacity = 0;
free(hp->_hp);
hp->_hp = NULL;
return;
}
///////////優先順序佇列
void InitPriorityQueue(PriorityQueue* q)
{
InitHeap(&q->hp);
}
void PushPriorityQueue(PriorityQueue* q, HPDataType data)
{
InsertHeap(&q->hp, data);
}
void PopPriorityQueue(PriorityQueue* q)
{
int i = 0;
int root = (q->hp._size-2)/2;
RemoveHeap(&q->hp);
for(i=root;i>=0;i--)
{
AdjustDown(&q->hp,i);
}
}
int TopPriorityQueue(PriorityQueue* q)
{
return TopHeap(&q->hp);
}
int SizePriorityQueue(PriorityQueue* q)
{
return SizeHeap(&q->hp);
}
int EmptyPriorityQueue(PriorityQueue* q)
{
return EmptyHeap(&q->hp);
}
//topk問題
void Topk(Heap* q, int k)
{
int i = 0;
int j = 0;
assert(q);
q->_hp = (HPDataType*)malloc(sizeof(HPDataType)*k);
if(q->_hp == NULL)
{
assert(0);
return;
}
//首先取前K個數,用著K個數來建立一個小堆
for(i=0;i<k;i++)
{
int temp = rand()%10000;
q->_hp[i] = temp;
}
q->_size = k;
for(i=(k-2)/2;i>=0;i--)
{
AdjustDown(q,i);
}
//然後,一個一個的取陣列內剩下的數,取出的數與堆頂的元素比較,如果比堆頂的元素大的話,就用取出的元素
//代替堆頂的元素,代替之後再進行向下的調整,使堆重新滿足小堆的特性,然後再從陣列內取資料,重複上述操作,直到所有的陣列為空時
for(j=k;j<10000;j++)
{
int temp = rand()%10000;
if(temp > q->_hp[0])
{
Swap(&temp,&q->_hp[0]);
AdjustDown(q,0);
}
}
PrintHeap(*q);
}
//堆排序
//如果是降序的話, 建一個小堆
//然後,先將小堆的堆頂的值與堆底的值交換,這樣最小值就到了堆底,然後調整的元素個數-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;
//調整剩下的幾個元素的堆
AdjustDown(q,0);
}
}