实现最小堆并进行堆排序(Java)

用java实现最小堆,并且实现以下2个题目:

  • 实现堆排序
  • 实现保留数据流中最大的5个数
    堆排序任何情况下的时间复杂度都是O(nlgn),空间复杂度为O(1)
    是不稳定的
    代码如下:
import java.util.Arrays;

public class MinHeapTest {

	public static void main(String[] args) {
		System.out.println("第一题排序");
		double[] a = new double[] {9.1,1.2,2.5,6,8,3};
		MinHeap mh1 = new MinHeap(a);
		mh1.heapSort();
		System.out.println(Arrays.toString(a));
		
		System.out.println("第二题保留最大的五个数");
		MinHeap mh2 = new MinHeap(5);
		double[] b = new double[] {100,2,5,6,120,43,23,658,250,890};
		for(double i : b)
			mh2.add(i);
		System.out.println(mh2);
	}
}


class MinHeap{
	private double[] data;
	private int size;//size是必须有的,因为堆得尺寸在变,数组的长度是永远不变的,在第二题中size始终等于现有数个数
	
	public  MinHeap(double[] data) {
		this.data = data;
		size = data.length;
	}
	public  MinHeap(int n) {
	    data = new double[n];
		size = 0;
	}
	public String toString() {
		return Arrays.toString(data);
	}
	
	public void add(double x) {
		if(size < data.length) 
			minHeapInsert(x);//下面size加过1了;
		else if(x > data[0]) {
			data[0] = x;
			minHeapify(0);
		}	
	}
	
	public void minHeapInsert(double x) {
		data[size++] = Double.POSITIVE_INFINITY;
		minHeapInsertKey(size - 1, x);
	}
	
	public void minHeapInsertKey(int i, double x) {
		data[i] = x;
		while(i > 0 && data[(i-1)/2] >  data[i]){//注意是while循环,i>0因为找的是父节点(不论是左还是右,(i-1)/2都是父节点下标),子不能为0
			double e = data[(i-1)/2];
			data[(i-1)/2] = data[i];
			data[i] = e;
			i = (i - 1) / 2;//迭代条件
		}
	}
	
	public void heapSort() {
		buildMinHeap();
		for(int i = data.length-1; i > 0; i--){//0不用操作,因为留一个不用取
			double e = data[0];
			data[0] = data[i];
			data[i] = e;
			size--;
			minHeapify(0);
		}
		
	}
	
	public void buildMinHeap() {
		for(int i = data.length/2; i >= 0; i--)
			minHeapify(i);
	}
	
	public void minHeapify(int i) {
		int l = 2 * i + 1;
		int r = 2 * (i + 1);
		int min = i;
		
		if(l < size && data[l] < data[min])//必须是小于size,取不到size下标
			min = l;
		if(r < size && data[r] < data[min])
			min = r;
		
		if(min != i){
			double e = data[i];
			data[i] = data[min];
			data[min] = e;
			minHeapify(min);//别写到if外面了,有变动才需要最小化堆
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值