在求前K大数中可以用堆来维护,但是很久没碰堆这个东西了,BS下自己。重新复习一下吧。
插入堆的时候,将元素放在数组尾,破坏堆的规则,使此节点上浮。
删除堆顶元素的时候,首先返回堆顶元素,然后将数组尾元素置于堆顶,破坏规则,使此节点下沉。
规则;数组下标从1开始。
如果当前节点为pos,则父亲节点为pos/2;左子节点为pos*2 ,右子节点为pos*2+1.
小根堆的堆顶元素最小,大根堆堆顶元素最大。且属于完全二叉树,即在一层排满后再从左至右排下一层。
#include <stdlib.h>
#include <stdio.h>
#define MAXSIZE 100
int heap[MAXSIZE];
int heapsize;
int ins_heap(int no) {
heapsize ++;
int pos = heapsize;
int parent = pos/2;
int target = heap[heapsize] = no;
while(parent != 0) {
if(heap[parent] <= target) {
break;
}
else {
heap[pos] = heap[parent];
heap[parent] = target;
pos = parent;
parent = pos /2;
}
}
return heapsize;
}
int del_heap( ) {
int pos = 1;
int ret;
int left ;
int right ;
int mixval, temp, ptr;
ret = heap[pos];
heap[pos] = heap[heapsize];
heapsize -- ;
while(pos*2 <= heapsize) { /**/
left = pos * 2 ;
right = pos *2 +1;
mixval = (heap[left]<heap[right]) ? heap[left]: heap[right];
if(mixval == heap[left])
ptr = left;
else if(mixval == heap[right])
ptr = right;
if(heap[pos] < mixval)
break;
else {
temp = heap[pos];
heap[pos] = heap[ptr];
heap[ptr] = temp;
pos = ptr;
}
}
return ret;
}
void init_heap(int a[], int n) {
}
int main ( ) {
int a[100], n, k, i;
heapsize = 0;
scanf("%d", &n);
for( i = 0 ;i < n ;i++) {
scanf("%d", &a[i]);
ins_heap(a[i]);
}
for( i = 1 ;i <= heapsize; i++) {
printf("%d ", heap[i]);
}
printf("\n");
int t= heapsize;
for(i =1; i<= t;i++)
printf("%d \n",del_heap());
for( i = 1 ;i <= heapsize; i++) {
printf("%d ", heap[i]);
}
printf("\n");
exit(0);
}
/*
9
24 10 90 77 16 25 33 89 67
*/
9
24 10 90 77 16 25 33 89 67
维护后的堆
10 16 25 67 24 90 33 89 77
以下为堆的删除顺序
10
16
24
25
33
67
89
90
77