在求前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


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值