堆排序

谁都会走 提交于 2019-11-28 23:54:18

堆,完全二叉树

满二叉树属于完全二叉树。

不是满二叉树,新的一层从做往右依次补齐。属于完全二叉树。

堆可以用数组实现。可以把一个数组理解为完全二叉树。

给出一个数组,可以在逻辑上脑补出一个完全二叉树。0 的父节点还是自己。(特殊节点)

某个节点:i 

左孩子:2 * i +1

右孩子:2 * i + 2

父节点:(i-1)/ 2

堆-是撒东西

                大根堆——>就是完全二叉树,在这颗完全二叉树中,任何子树的最大值,都是头部。

                小根堆——>就是完全二叉树,在这颗完全二叉树中,任何子树的最小值,都是头部。

问题来了:怎么用数组,变成大根堆?

heapinsert

你已经形成一个堆,要加入一个新的节点,你要经历向上依次比对,这个值要足够大,就往上跑,跑到一个你不比父节点大的时候,你就停。这个过程就是 heapinsert 过程。-- 这就是形成大根堆的过程。

heapify

一个大根堆,假设数组中有个数变小了,怎么重新调整成大根堆?

这个变化的值,找到他左右两个孩子中最大的值,该最大值比变化的值大,和他交换。

 

当整个完全二叉树是整个数组时,整个 heapsize 就是数组大小。

但也有可能 0 ~ i 范围形成二叉树。堆最大的情况可能是整个数组大小,整个数组从 0~i 这一段才是堆。于是给了他一个参数,heapsize ,是代表堆上一共有多少个数?一定不会比数组的个数大。

如果有越界,说明已经是叶子节点了。停哪儿就可以了。

package suanfa;

public class HeapSort {
	public static void heapSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {     //这里执行完,就是大根堆了
			heapInsert(arr, i);
		}
		int heapSize = arr.length;
		swap(arr, 0, --heapSize);
		while (heapSize > 0) {
			heapify(arr, 0, heapSize);
			swap(arr, 0, --heapSize);
		}
	}

	public static void heapify(int[] arr, int index, int size) {
		int left = index * 2 + 1; // 左孩子,为什么不弄右孩子,两个孩子有一个就行了
		while (left < size) { // 左孩子不越界下,一直执行
			int largest = left + 1 < size && 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; // 判断是否越界
		}
	}

	public static void heapInsert(int[] arr, int index) {
		while (arr[index] > arr[(index - 1) / 2]) { // 只要比父节点大,就一直循环判断
			swap(arr, index, (index - 1) / 2); // 交换,并继续向上判断
			index = (index - 1) / 2; // index 赋值给父节点
		}
	}

	public static void swap(int[] arr, int i, int j) {
		int tmp = arr[i];
		arr[i] = arr[j];
		arr[j] = tmp;

	}
	
	public static void main(String[] args) {
		int[] arr = { 2, 0, 12, -4, 9, 81 };
		System.out.println(java.util.Arrays.toString(arr));
		heapSort(arr);
		System.out.println(java.util.Arrays.toString(arr));
	}
}

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!