堆排序

  堆:堆是一棵完全二叉树,某个节点的值总是不大于(称为大根堆)或不小于其父节点(称为小根堆)的值。

【算法描述】

  • 将待排序的n个元素按照堆的定义建初堆,并移除堆顶元素
  • 调整剩余的元素序列(也就是去掉了堆顶元素的序列),将这n-1个元素重新建成一个新堆,再移除堆顶元素
  • 重复执行步骤二,进行n-1次筛选,新筛选的堆会越来越小,最后所有的堆顶元素都会被移除,被移除的堆顶元素就是一个有序序列
        这个过程总结起来就是 先建初堆,去掉堆顶元素后重建堆

   下图中,是对{14,98,77,35,62,55}进行升序排列的过程

【算法实现】

public class Sort {
	/* 建堆 */
	public static void sift(int[] r, int k, int m) {// r[k..m]是以r[k]为根的完全二叉树,r[m]是最后一个结点
		int temp = r[k];// 暂存根结点
		int i = k;
		int j = 2 * i + 1;// a[j]是a[i]的左节点
		boolean finished = false;
		while (j < m && !finished) {
			/* 如果存在右子树,并且右子树大,那么就沿右分支筛选 */
			if (j + 1 < m && r[j] < r[j + 1]) {
				j += 1;
			}
			/* 不存在右子树或者根节点比左右子树都大的时候筛选完毕 */
			if (temp > r[j]) {
				finished = true;
			} else {
				r[i] = r[j];
				i = j;
				j = 2 * i + 1;
			} /* 继续筛选 */
		}
		r[i] = temp;
	}/* sift */

	/* 建初堆 */
	public static void heap(int[] r) {
		int len = r.length;
		for (int i = len / 2 - 1; i >= 0; i--) {
			sift(r, i, len);
		}
	}/* heap */

	public static void heapSort(int[] r) {
		int len = r.length;
		heap(r);
		/* 重建堆 */
		for (int m = len - 1; m > 0; m--) {
			/* 堆顶元素与堆尾交换 */
			int b = r[0];
			r[0] = r[m];
			r[m] = b;
			sift(r, 0, m);
		}
	}/* heapSort */

	public static void main(String[] args) {
		int[] r = { 14, 98, 77, 35, 62, 55 };
		Sort.heapSort(r);
		for (int i : r) {
			System.out.print(i + " ");
		}
	}
}

【算法分析】

堆排序是我们所知的唯一能够同时最优地利用空间和时间的方法,他的的时间主要耗费在建初堆和重建堆上,如果有n个元素,建初堆需调整的次数最多为4n次,时间复杂度为O(n),调整堆的次数不超过2n[log2(n)],所以堆排序在最坏情况下,时间复杂度为O(nlog2(n)),空间复杂度为O(1),但它是不稳定排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值