堆排序原理

堆是一个完全二叉树;
堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值。

通过数组实现一个堆

  1. 往堆中插入一个元素
public class Heap {
	 private int[] a; // 数组,从下标1开始存储数据
	 private int n; // 堆可以存储的最大数据个数
	 private int count; // 堆中已经存储的数据个数
	 public Heap(int capacity) {
		 a = new int[capacity + 1];
		 n = capacity;
		 count = 0;
	 }
	 public void insert(int data) {
		 if (count >= n) return; // 堆满了
		 ++count;
		 a[count] = data;
		 int i = count;
		 while (i/2 > 0 && a[i] > a[i/2]) { // 自下往上堆化
			 swap(a, i, i/2); // swap()函数作用:交换下标为i和i/2的两个元素
			 i = i/2;
		 }
	 }
 }
  1. 删除堆顶元素
public void removeMax() {
	 if (count == 0) return -1; // 堆中没有数据
	 a[1] = a[count];
	 --count;
	 heapify(a, count, 1);
}
private void heapify(int[] a, int n, int i) { // 自上往下堆化
	 while (true) {
		 int maxPos = i;
		 if (i*2 <= n && a[i] < a[i*2]) maxPos = i*2;
		 if (i*2+1 <= n && a[maxPos] < a[i*2+1]) maxPos = i*2+1;
		 if (maxPos == i) break;
		 swap(a, i, maxPos);
		 i = maxPos;
	 }
}

应用:堆排序
这里是使用1为起始的 i 2i 2i+1
如果用0为起始 i 2i+1 2i+2 (i-1)/2

  1. 建堆 建堆的时间复杂度为O(n)
private static void buildHeap(int[] a, int n) {
	 for (int i = n/2; i >= 1; --i) {
	 	heapify(a, n, i);
	 }
}
private static void heapify(int[] a, int n, int i) {
	 while (true) {
		 int maxPos = i;
		 if (i*2 <= n && a[i] < a[i*2]) maxPos = i*2;
		 if (i*2+1 <= n && a[maxPos] < a[i*2+1]) maxPos = i*2+1;
		 if (maxPos == i) break;
		 swap(a, i, maxPos);
		 i = maxPos;
	 }
}
  1. 排序
    每一次取最大值,也就是堆顶元素与最后一个元素进行交换,然后再把剩余的元素进行堆化 时间复杂度为O(nlogn)
public static void sort(int[] a, int n) {
	 buildHeap(a, n);
	 int k = n;
	 while (k > 1) {
		 swap(a, 1, k);
		 --k;
		 heapify(a, k, 1);
	 }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值