堆与堆排序

参考

1 http://www.cnblogs.com/Anker/archive/2013/01/23/2873422.html

2 http://blog.csdn.net/morewindows/article/details/6709644/

3 http://blog.csdn.net/hguisu/article/details/7776068

堆排序的时间复杂度O(N*logN)的排序算法,先看下二叉堆的定义。

实际上就是一颗完全二叉树(Complete Binary Tree:在最后一层,并不是所有的节点都拥有子节点(其他层的节点拥有子节点--而且使用拥有两个子节点)。


二叉堆有两个特点

1 父节点的值大于等于(小于等于)字节点的值

2 每个节点的左子树和右每一个子节点都是一个(最大二叉堆或最小二叉堆)

当父节点的值总是大于等于子节点的值时,称作最大堆。当父节点的值总是小于等于子节点的值的时候,叫做最小堆。

           10个用数组表示节点描述建堆、堆排序过程。

建堆过程

       max-heappify 保持堆

       build-heap 构建堆

       heap-sort 堆排序

1 保持堆的算法源码

	/**
	 * 大顶堆,数组下标从0开始 
	 * @param a       数组
	 * @param length  待排序的元素个数
	 * @param i       当前节点--目标是要把这个节点调整成堆
	 */
	public static void adjustDown(int a[], int length, int i) {
		// 左右孩子
		for (;;) {
			int maxIndex = i;

			int leftIndex = i * 2 + 1;
			int rightIndex = i * 2 + 2;
			// 选择 a[i] 和 左右子节点的中最大的值
			if (leftIndex < length - 1 && a[leftIndex] > a[i]) {
				maxIndex = leftIndex;
			}

			if (rightIndex < length && a[rightIndex] > a[maxIndex]) {
				maxIndex = rightIndex;
			}

			// 当前节点 它的左孩子 右孩子,满足 最大堆
			if (maxIndex == i) {
				break;
			} else {
				// 交换 当前节点和孩子节点中最大的
				int temp = a[i];
				a[i] = a[maxIndex];
				a[maxIndex] = temp;
				i = maxIndex;
				continue;
			}
		}
	}

2 构建堆源码:

	/**
	 * 从下向上,从右到左第一个非叶子结点; 如果数组下标从0开始,start = (a.length - 2 ) / 2
	 * 
	 * @param a
	 */
	public static void buildHeap(int[] a) {
		for (int i = (a.length - 2) / 2; i >= 0; i--) {
			adjustDown(a, a.length, i);
		}
	}

3 堆排序源码:

	/**
	 * a[0] 是最大的元素,和最后一个元素交换位置,即a[length - 1],然后调整a[0] 成为最大堆
	 * 迭代N次,每一次调整时间复杂度最大OlogN,总的时间复杂度 O(NlogN)
	 * @param a 输入参数一个大顶堆
	 */
	public static void heapSort(int[] a) {
		for (int i = a.length; i > 0; i--) {
			int temp = a[0];
			a[0] = a[i - 1];
			a[i - 1] = temp;
			adjustDown(a, i - 1, 0);
		}
	}



       第一步 index=4 先找到最后一个有子结点的结点[max-1] / 2,先让他的两个子结点进行比较,找到大的值再和父结点的值进行比较。如果父结点的值小,则子结点和父结点进行交换,交换之后再往下比较。然后一步步递归上去,直到所在结点的位置是0号位置跳出。


       最后一个有子节点的节点的index等于4。先比较两个孩子节点中比较大的值,和a父节点比较。a[i]比较 a[4] < a[4*2 + 1]、a[4*2 + 2],交换父节点和子节点。

      第二步 index = 3,先比较左孩子,a[3] < a[3 * 2 + 1 ],12 < 32 , 交换。





       第三步 index = 2


堆排序是否是稳定的排序,为什么?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值