排序算法之---堆排序

本文介绍了堆数据结构,特别是大根堆的应用,通过堆排序算法实现数组排序,并展示了如何利用堆解决最大线段重合问题。通过PriorityQueue实现优先级队列,讨论了堆的性质、插入和调整操作,以及在实际问题中的应用实例。
摘要由CSDN通过智能技术生成

heap堆 -> Priority Queue优先级队列
数组实现完全二叉树
拥有的性质:
任意节点的左孩子: 2 * i + 1
右孩子: 2 * i + 2
父节点: (i - 1) / 2
大根堆: 父节点比子节点大(并不一定是完全有序)

时间复杂度: O(N * log N)

不多废话,代码实现堆排序 :

public static void heapSort(int[] arr) {
	if(arr == null || arr.length < 2) {
		return;
	}
// 这步可以满足数组一个值一个值赋予
//	for(int i = 0; i < arr.length; i++) {
//		heapInsert(arr, i);
//	}
	//这步只能适用于一起给一堆数据排序
	for(int i = arr.length - 1; i >= 0; i--) {
		heapify(arr, i, arr.length);
	}
	int heapSize = arr.length;
	swap(arr, 0, --heapSize);
	while(heapSize > 0) {
		heapify(arr, 0, heapSize);
		swap(arr, 0, --heapSize);
	}
}

//二叉树由下向上升
private void heapInsert(int[] arr, int index) {
	while(arr[index] > arr[(index - 1) / 2]) {
		swap(arr, index, (index - 1) / 2);
		index = (index - 1) / 2;
	}
}

//二叉树由顶向下降
private void heapify(int[] arr, int index, int heapSize) {
	int left = index * 2 + 1;
	while(left < heapSize) {
		int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
		largest = arr[largest] > arr[index] ? largest : index;
		if(largest == index) {
			break;
		}
		swap(arr, largest, index);
		index = largest;
		left = index * 2 + 1;
	}
}

private void swap(int[] arr, int i , int j) {
	int tmp = arr[i];
	arr[i] = arr[j];
	arr[j] = tmp;
}

使用堆解决的题:
最大线段重合问题

public static class Line {
	public int start;
	public int end;
	
	public Line(int s, int e) {
		start = s;
		end = e;
	}
}

public static class StartComparator implements Comparator<Line> {
	
	@Override
	public int compare(Line o1, Line o2) {
		return o1.start - o2.start;
	}
}

public static int maxCover(int[][] m) {
	Line[] lines = new Line[m.length];
	//把数组用类封装,才能用Arrays.sort方法排序
	for(int i = 0; i < m.length; i++) {
		lines[i] = new Line(m[i][0], m[i][1]);
	}
	Arrays.sort(lines, new StartComparator());
	//优先级队列默认小根堆
	PriorityQueue<Integer> heap = new PriorityQueue<>();
	int max = 0;
	for(int i = 0; i < lines.length; i++) {
		while(!heap.isEmpty() && heap.peek() <= lines[i].start) {
			heap.poll();
		}
		heap.add(lines[i].end);
		max = Math.max(max, heap.size());
	}
	return max;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值