> 1. 堆:把一组数据按照完全二叉树的顺序储存模式存储在一个二维数组中,
> 若ai<ai+1&&ai<ai+2,则称为小堆,
> 若ai>ai+1&&ai>ai+2,则称为大堆(i=0,1,2...n);
- 堆的特点:
- 大堆:任意一个节点的值都比它的左右孩子节点的值大,且逐级递减;
- 小堆:任意一个节点的值都比它的左右孩子节点的值小,且逐级递增;
在堆中,若设父亲节点为parent,则它的左孩子为2*parent+1,右孩子为2*parent+2;
- > 堆的创建:
void MakeHeap(DataType* a, size_t n)//构建堆
{
int i=(n-1)>>1;
for(;i>=0;i--)
{
AdjustDown(a,n,i);//向下调整函数
}
}
- 向下调整函数:
void AdjustDown(DataType* a, size_t n, int root)//向下调整
{
int parent =root;
int child=2*parent+1;
while(child<n)
{
if((child+1)<n&&a[child+1]<a[child])//右孩子存在且右孩子大于左孩子
{
++child;//指向右孩子
}
if(a[child]<a[parent])
{
DataType tmp;
tmp=a[child];
a[child]=a[parent];
a[parent]=tmp;
parent=child;
child=2*parent+1;
}
else
{
break;
}
}
}
- 向上调整函数
-
void AdjustUp(DataType* a, size_t n, int child)//向上调整
{
int parent=(child-1)>>1;
while(child>0)
{
if(a[child]<a[parent])
{
DataType tmp;
tmp=a[child];
a[child]=a[parent];
a[parent]=tmp;
child=parent;
parent=(child-1)>>1;
}
else
{
break;
}
}
}
堆的应用:
1、海量数据top K问题:
- 代码实现:
void TopK(DataType* a, size_t n, size_t k)
{
int i;
MakeHeap(a,k);//建小堆
for(i=k;i<n;i++)
{
a[0]=a[i];
AdjustDown(a,k,0);
}
for(i=0;i<k;i++)
{
printf("%d ",a[i]);
}
}
2、优先级队列问题
- 1.1 优先级队列的定义 •优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。
- 1.2 优先级队列的特点
- •优先级队列是0个或多个元素的集合,每个元素都有一个优先权或值。 •当给每个元素分配一个数字来标记其优先级时,可设较小的数字具有较高的优先级,这样更方便地在一个集合中访问优先级最高的元素,并对其进行查找和删除操作。
•在最小优先级队列(min PriorityQueue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素。
•在最大优先级队列(maxPriorityQueue)中,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。 •插入操作均只是简单地把一个新的元素加入到队列中。
•注:每个元素的优先级根据问题的要求而定。当从优先级队列中删除一个元素时,可能出现多个元素具有相同的优先权。在这种情况下,把这些具有相同优先权的元素视为一个先来先服务的队列,按他们的入队顺序进行先后处理。
初始化
void PriorityQueueInit(PriorityQueue* q)
{
assert(q);
q->_size=0;
memset(q->_a,0,sizeof(DataType)*N);
}
- 插入
void PriorityQueuePush(PriorityQueue* q, DataType x)
{
assert(q);
if(q->_size>=N)
{
printf("PriorityQueuefull\n");
return;
}
q->_a[q->_size++]=x;
AdjustUp(q->_a,q->_size,q->_size-1);//从最后一个元素开始调
}
- 删除
void PriorityQueuePop(PriorityQueue* q)
{
assert(q);
if(NULL==q)
{
printf("PriorityQueueEmpty\n");
return;
}
q->_a[0]=q->_a[q->_size-1];
q->_size--;
AdjustDown(q->_a,q->_size,0);
}
- 取队首元素
- DataType PriorityQueueTop(PriorityQueue* q)
{
assert(q);
if(NULL==q)
{
printf("PriorityQueueEmpty\n");
return;
}
return q->_a[0];
}
- 判空
size_t PriorityQueueEmpty(PriorityQueue* q)
{
assert(q);
return q->_size;
}
3、堆排序
void HeapSort(DataType* a, size_t n)
{
int i=0;
assert(a);
MakeHeap(a,n);
while(n>0)
{
printf("%d ",a[0]);
a[0]=a[n-1];
n--;
AdjustDown(a,n,0);
}
}
源码:
Heap.h
#ifndef __HEAP_H_
#define __HEAP_H_
#include <stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
void AdjustDown(DataType* a, size_t n, int root) ;//向下调整
void MakeHeap(DataType* a, size_t n) ;//构建堆
void AdjustUp(DataType* a, size_t n, int child);//向上调整
// topk 最大的前K
void TopK(DataType* a, size_t n, size_t k);
#define N 1000
typedef struct PriorityQueue
{
DataType _a[N];
size_t _size;
//DataType* _a;
//size_t _size;
//size_t _capacity;
}PriorityQueue;
void PriorityQueueInit(PriorityQueue* q);
void PriorityQueuePush(PriorityQueue* q, DataType x);
void PriorityQueuePop(PriorityQueue* q);
DataType PriorityQueueTop(PriorityQueue* q);
size_t PriorityQueueSize(PriorityQueue* q);
size_t PriorityQueueEmpty(PriorityQueue* q);
void HeapSort(DataType* a, size_t n) ;
#endif
Heap.c
#include"Heap.h"
void MakeHeap(DataType* a, size_t n)//构建堆
{
int i=(n-1)>>1;
for(;i>=0;i--)
{
AdjustDown(a,n,i);
}
}
void AdjustDown(DataType* a, size_t n, int root)//向下调整
{
int parent =root;
int child=2*parent+1;
while(child<n)
{
if((child+1)<n&&a[child+1]<a[child])//右孩子存在且右孩子大于左孩子
{
++child;//指向右孩子
}
if(a[child]<a[parent])
{
DataType tmp;
tmp=a[child];
a[child]=a[parent];
a[parent]=tmp;
parent=child;
child=2*parent+1;
}
else
{
break;
}
}
}
void AdjustUp(DataType* a, size_t n, int child)//向上调整
{
int parent=(child-1)>>1;
while(child>0)
{
if(a[child]<a[parent])
{
DataType tmp;
tmp=a[child];
a[child]=a[parent];
a[parent]=tmp;
child=parent;
parent=(child-1)>>1;
}
else
{
break;
}
}
}
void TopK(DataType* a, size_t n, size_t k)
{
int i;
MakeHeap(a,k);//建小堆
for(i=k;i<n;i++)
{
a[0]=a[i];
AdjustDown(a,k,0);
}
for(i=0;i<k;i++)
{
printf("%d ",a[i]);
}
}
void PriorityQueueInit(PriorityQueue* q)
{
assert(q);
q->_size=0;
memset(q->_a,0,sizeof(DataType)*N);
}
void PriorityQueuePush(PriorityQueue* q, DataType x)
{
assert(q);
if(q->_size>=N)
{
printf("PriorityQueuefull\n");
return;
}
q->_a[q->_size++]=x;
AdjustUp(q->_a,q->_size,q->_size-1);
}
void PriorityQueuePop(PriorityQueue* q)
{
assert(q);
if(NULL==q)
{
printf("PriorityQueueEmpty\n");
return;
}
q->_a[0]=q->_a[q->_size-1];
q->_size--;
AdjustDown(q->_a,q->_size,0);
}
DataType PriorityQueueTop(PriorityQueue* q)
{
assert(q);
if(NULL==q)
{
printf("PriorityQueueEmpty\n");
return;
}
return q->_a[0];
}
size_t PriorityQueueSize(PriorityQueue* q)
{
assert(q);
return q->_size;
}
size_t PriorityQueueEmpty(PriorityQueue* q)
{
assert(q);
return q->_size;
}
void HeapSort(DataType* a, size_t n)
{
int i=0;
assert(a);
MakeHeap(a,n);
while(n>0)
{
printf("%d ",a[0]);
a[0]=a[n-1];
n--;
AdjustDown(a,n,0);
}
}
test.c
#include"Heap.h"
void TestHeap()
{
int i=0;
DataType NArray[1000];
DataType a[] = {10,11, 13, 12, 16, 18, 15, 17, 14, 19};
HeaapSort(a,sizeof(a)/sizeof(a[0]));
printf("\n");
MakeHeap(a, sizeof(a)/sizeof(DataType));
srand(time(0));
for (i = 0; i < 1000; ++i)
{
NArray[i] = rand()%10000;
}
NArray[30] = 10001;
NArray[350] = 10002;
NArray[999] = 10003;
NArray[158] = 10004;
NArray[334] = 10005;
TopK(NArray, 1000, 5);
}
void TestPriorityQueue()
{
PriorityQueue q;
PriorityQueueInit(&q);
PriorityQueuePush(&q, 5);
PriorityQueuePush(&q, 2);
PriorityQueuePush(&q, 3);
PriorityQueuePush(&q, 7);
PriorityQueuePush(&q, 6);
PriorityQueuePush(&q, 1);
PriorityQueuePush(&q, 4);
while (PriorityQueueEmpty(&q) != 0)
{
printf("%d ", PriorityQueueTop(&q));
PriorityQueuePop(&q);
}
printf("\n");
}
int main()
{
TestHeap();
printf("\n");
TestPriorityQueue();
system("pause");
return 0;
}