基于堆排序实现的找出N个数据的前M大数据之Java实现

算法思想:

当有N个数据,而N又是非常大(比如:千万或者亿),需要找出N条数据的排名最前的M条数据时,可以采用的一种策略。

先选前M个元素组成一个小根堆,然后遍历剩下的数据,如果第i个元素key大于小根堆的根结点,就删除这个根结点,并将元素key插入根结点,调整这个堆使其成为小根堆,然后继续遍历剩下的数据; 最后,小根堆中的元素就是最大的M个元素。


代码实现如下:

<span style="font-family:SimHei;"><span style="font-family:SimHei;font-size:14px;"><span style="font-size:14px;">HeapSort Class</span></span></span>

public abstract class HeapSort<E> {
	public abstract boolean compare(E value1, E value2);//value1小于value2则返回true
	
	public boolean heapSort(List<E> list){//排序
		return heapSort(list, list.size());
	}
	
	public boolean heapSort(List<E> list, int n){
		if(null == list || 0 == list.size()){
			return false;
		}
		if(!heapCreate(list, n)){
			return false;
		}
		for(int i = n; i > 0; --i){
			swap(list, 0, i - 1);
			heapAdjust(list, 0, i - 1);
		}
		return true;
	}
	
	public boolean heapCreate(List<E> list, int length){ //创建小根堆
		if(null == list || 0 == list.size()){
			return false;
		}
		for(int i = (length / 2 - 1); i >= 0; --i){
			if(!heapAdjust(list, i, length)){
				return false;
			}
		}
		return true;
	}
	
	public boolean heapAdjust(List<E> list, int middle, int length){//调整堆,使其满足小根堆的条件
		if(null == list || 0 == list.size()){
			return false;
		}
		E temp = list.get(middle);
		for(int i = (2 * middle + 1); i < length; i *= 2){
			if(i < (length - 1) && !this.compare(list.get(i), list.get(i + 1))){
				++i;
			}
			if(this.compare(temp,list.get(i))){
				break;
			}
			list.set(middle, list.get(i));
			middle = i;
		}
		list.set(middle, temp);
		return true;
	}
	
	public void swap(List<E> list, int i, int j){//数据交换
		E temp = list.get(i);
		list.set(i, list.get(j));
		list.set(j, temp);
	}
}

FindFirstNData Class

public abstract class FindFirstNData<E> extends HeapSort<E>{

	public abstract boolean compare(E value1, E value2);
	
	public boolean findFirstNData(List<E> list, int n){
		if(!this.heapCreate(list, n)){
			return false;
		}
		for(int i = n; i < list.size(); ++i){
			if(!this.compare(list.get(0), list.get(i))){
				continue;
			}
			this.swap(list, 0, i);
			if(!this.heapAdjust(list, 0, n)){
				return false;
			}
		}
		return this.heapSort(list, n);
	}
}

测试数据:给出10000000个Integer型的随机数据,找出前3大所用的时间如下图所示(单位:毫秒):


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值