算法6-堆排序算法

堆排序算法思想:

假设数组arr中有N个数:
(1)将整个数组大根堆结构,大根堆的heapSize就是整个数组arr的length;
(2)将大根堆结构的头节点的值和最后一个节点的值交换位置,大根堆的size减1,在此时的size约束下,调整头结点位置,将其变成大根堆结构。不断重复步骤(2),直至size变成1,此时size = 1说明,堆中待排序的元素只有一个,自然就不需要再排序了。

堆排序代码:

public class HeapSort {
	public void heapSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		
		// 让整个数组变成大根堆方法一:
		// 下面这个for循环整体复杂度是O(N*log(N))
		for (int i = 0; i < arr.length; i++) { // O(N)
			heapInsert(arr, i);// O(logN)
		}

		// 让整个数组变成大根堆方法二:
		// 下面这个for循环整体复杂度为O(N),但整个算法的时间复杂度仍然是O(N*log(N)),heapify的特性决定了遍历的时候,要倒着遍历,保证之前形成的子树的最大值都在顶部
		// for (int i = arr.length - 1; i >= 0; i--) {// O(N)
		// heapify(arr, i, arr.length);
		// }

		int size = arr.length;
		swap(arr, 0, --size);

		// 这个while循环决定了,这个算法的时间复杂度是O(N*log(N))
		while (size > 1) {// O(N)
			heapify(arr, 0, size);// O(log(N))
			swap(arr, 0, --size);// O(1)
		}
	}

	// 某个数现在处在index位置,往上继续移动
	public void heapInsert(int[] arr, int index) {
		while (arr[index] > arr[(index - 1) / 2]) {//  0 / -1 =0
			swap(arr, index, (index - 1) / 2);
			index = (index - 1) / 2;
		}
	}

	// heapify 堆化
	// 某个数在index位置,能否往下移动
	// size限制堆的大小
	public void heapify(int[] arr, int index, int size) {
		int left = index * 2 + 1;// 左孩子的下标
		while (left < size) {// 下方还有孩子的时候
			// 两个孩子中,谁的值大,把下标给largest
			int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
			// 父和孩子之间,谁的值大,把下标给largest
			largest = arr[largest] > arr[index] ? largest : index;
			if (largest == index) {
				break;
			}
			swap(arr, largest, index);
			index = largest;
			left = index * 2 + 1;
		}
	}

堆排序的时间复杂度:

O(N*log(N))

堆排序的额外空间复杂度:

O(1)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值