您的位置:首页 > 其它

堆排序

2015-06-03 09:45 113 查看

堆的含义

堆是具有下列性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆。或者每个结点的值都小于或等于其左右孩子节点的值,称为小顶堆。

构建大顶堆基本思想

将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(其实就是与其堆数组的末尾元素进行交换,此时末尾元素就是最大值),然后将剩余的n-1个序列重新构造为一个堆,这样就会得到n个元素中的次大值。反复执行,得到有序序列。

实例图

阿里笔试的一题,给定一个数组7 6 3 5 4 1 2,请问3的交换次数是几次?要是熟悉堆排序的思想的话,这一题就轻而易举了。画个交换图来数一数吧。答案是2次。



堆排序实现

堆排序,就是利用堆进行排序的方法。它不是说在排序的过程中真建一棵树,而是利用节点在树中的位置,比如这里我要进行排序的是数组,而是将数组的下标与节点的位置想对应,通过树来完成堆排序。

// 为了与树中节点的位置一一对应,将数值存储的时候可以从下标1的位置开始
	void HeapSort(int[] array)
	{
		int length = array.length;
		int start = length / 2;// 堆排序的过程中,每次都是对有叶子节点的父节点进行排序
		for (int i = start; i > 0; i--)
		{
			HeapAdjust(array, i, length);//进行节点间位置的调整
		}
		//构建大顶堆后,将根节点与最后一个节点进行互换。
		for(int j=length;j>1;j--)
		{
			int tmp=array[j];
			array[j]=array[1];
			array[1]=tmp;
			HeapAdjust(array, 1, j-1);//将1到j-1重新调整为大顶堆
		}
	}

	void HeapAdjust(int[] array, int i, int length)
	{
		// TODO Auto-generated method stub
		int temp=array[i];
		for (int j = 2*i; j <=length; j*=2)//i节点作为父节点时,它的孩子节点是2*i
		{
			if(j<length&&array[j]<array[j++])j++;//如果右孩子节点大于左孩子节点,j++
			//如果父节点的值大于右节点的值,则不用调换,给循环结束
			if(temp>=array[j])break;
			//子节点比父节点的值要大,进行调换,这里使用的是将子节点的值赋给父节点(父节点的值已经放在temp中)
			array[i]=array[j];
			i=j;//如果i值不是叶子节点的位置,它需要继续比较,直至叶子节点
		}
		array[i]=temp;

	}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: