算法(第四版)学习笔记之java实现堆排序

继上一篇实现基于堆的优先队列后,这次将利用上一次完成的基于堆的能够重复删除最大元素操作的优先队列来实现一种经典而优雅的排序算法,称之为堆排序。

堆排序可分为两个阶段:

1.构建堆:在堆的构建过程中,我们将原始数组重新组织安排进一个堆中;

2.下沉排序:从堆中按递减顺序取出所有元素并得到排序结果

具体的思想在下面的代码中有较为详细的注释:

/**
 *
 * @author seabear
 *
 */

public class HeapSort {

	/**
	 * 1.构造大根堆:与上一篇基于堆的优先队列相似,将原始数组重新组织成一个基于堆的拥有重复删除最大元素操作的优先队列;
	 * 2.下沉排序:根据构造出来的大根堆,很容易将堆中的最大元素删除,然后放入堆缩小后数组中空出的位置。
	 * @param a
	 */
	public static void sort(Comparable[] a)
	{
		int len = a.length-1;
		//构造大根堆
		//跳过只有一个结点的堆即大小为1的堆,从数组的中间开始扫描,调用sink()方法,层层递减,最后在1位置上调用sink()方法后结束。
		//此次扫描目的是构造一个堆有序的数组并使最大元素位于数组的开头(次大的元素在附近)
		for(int k = len / 2; k >= 1; k--)
		{
			sink(a,k,len);
			show(a);
		}
		System.out.println("下沉开始");
		//下沉排序
		//1.每次排序都先将最大的元素与最后一个元素交换位置,接着缩小数组,对除去最后一个元素的堆进行下沉排序
		//2.对缩小后的数组进行下沉排序,若数组长度大于1,则跳转到第一步继续执行
		while(len > 1)
		{
			exch(a,1,len--);
			sink(a,1,len);
			show(a);
		}
	}
	//下沉排序
	private static void sink(Comparable[] a,int i,int len)
	{
		while(i*2 <= len)
		{
			int j = i * 2;
			if(j < len && less(a[j],a[j+1]))
			{
				j++;
			}
			if(!less(a[i],a[j]))
			{
				break;
			}
			exch(a,i,j);
			i = j;
		}
	}

	private static boolean less(Comparable v,Comparable w)
	{
		return v.compareTo(w) < 0;
	}

	private static void exch(Comparable[] v,int i, int j)
	{
		Comparable temp = v[i];
		v[i] = v[j];
		v[j] = temp;
	}

	public static void show(Comparable[] a)
	{
		for(int i = 1; i < a.length; i++)
		{
			System.out.print(a[i] + " ");
		}
		System.out.println();
	}

	public static void main(String[] args)
	{
		int N = 12;
		Integer[] a = new Integer[N];
		for(int i = 1; i <= N-1; i++)
		{
			a[i] = (int)(Math.random() * 10 + 1);
		}
		show(a);
		sort(a);
		show(a);
	}

}

堆排序在排序复杂性的研究中有着重要的地位,因为它是我们所知的唯一能够同时最优地利用空间和时间的方法,即使在最坏的情况下,它也能保证使用~2NlgN次比较和恒定的额外空间。常用于嵌入式系统或低成本的移动设备中(空间十分紧缺的系统);但现代系统的许多应用很少使用它,,因为它无法利用缓存。数组元素很少和相邻的其他元素进行比较,因此缓存未命中的次数要远高于大多数比较都在相邻元素间进行的算法,例如快速排序、归并排序,甚至是希尔排序。另一方面,用堆实现的优先队列在现代应用程序中越来越重要,因为它能在插入操作和删除最大元素操作混合的动态场景中保证对数级别的运行时间。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-03 15:01:50

算法(第四版)学习笔记之java实现堆排序的相关文章

算法(第四版)学习笔记之java实现选择排序

选择排序步骤: 1.找到数组中参与遍历比较的所有元素中的最小元素的下标: 2.将最小元素与数组中参与遍历比较的第一个元素进行交换(如果第一个元素就是最小元素的话,那么也会进行一次交换): 3.若数组中还有需要参与遍历比较的元素,则跳转到步骤1:否则排序结束. 在算法第四版中给出的所有排序均是适用于任意实现了Comparable接口的数据类型,若要将数字作为测试用例,请勿使用基本数据类型,改用Integer等实现了Comparable接口的对象. 选择排序代码如下: /** * * @author

算法(第四版)学习笔记之java实现栈和队列(链表实现)

下压堆栈(链表实现): import java.util.Iterator; public class LinkedStack<Item> implements Iterable<Item> { public class Node { Item item; Node next; } private Node frist; private int N = 0; public boolean isEmpty() { return N == 0; } public int size()

算法(第四版)学习笔记之java实现可以动态调整数组大小的栈

下压(LIFO)栈:可以动态调整数组大小的实现 import java.util.Iterator; public class ResizingArrayStack<Item> implements Iterable<Item> { private int N = 0; private Item[] a = (Item[]) new Object[1]; public boolean isEmpty() { return N == 0; } public int size() {

算法(第四版)学习笔记之java实现快速排序

快速排序是一种分治的排序算法.它将一个数组分成两个子数组,将两部分独立地排序.快速排序和归并排序是互补的,归并排序将两个子数组分别排序,并将有序的子数组归并以将整个数组排序:而快速排序则是当两个子数组有序时整个数组也就自然有序了.在快速排序中,切分的位置取决于数组的内容. 优点: 1.实现简单: 2.适用于各种不同的输入数据且在一般应用中比其他排序算法都要快得多: 3.原地排序: 4.时间复杂度为o(nlgn); 5.内循环比大多数排序算法都要短,比较次数少. 缺点:快速排序算法非常脆弱,在实现

算法(第四版)学习笔记之java实现能够动态调整数组大小的栈

下压(LIFO)栈:能够动态调整数组大小的实现 import java.util.Iterator; public class ResizingArrayStack<Item> implements Iterable<Item> { private int N = 0; private Item[] a = (Item[]) new Object[1]; public boolean isEmpty() { return N == 0; } public int size() {

算法(第四版)学习笔记之java实现归并排序

归并排序思想:将一个数组分成两部分分别排序(使用递归),然后将结果合并起来,即将最后两个有序的数组归并成一个更大的有序数组. 时间复杂度O(n) = NlogN 归并排序最吸引人的性质是它能保证将任意长度为N的数组排序所需时间和NlogN成正比,而缺点便是它所需的额外空间和N成正比. 归并排序又分为自顶向下的排序方式和自底向上的排序方式: 自顶向下的排序方式是利用了分治的思想,将一个大问题分割成若干个等价的子问题进行求解: 自底向上的排序方式是先归并那些微型数组,然后再成对归并得到的子数组. 两

算法(第四版)学习笔记之java实现希尔排序

希尔排序思想:使数组中任意间隔为h的元素都是有序的.希尔排序是插入排序的优化,先对数组局部进行排序,最后再使用插入排序将部分有序的数组排序. 代码如下: /** * * @author seabear * */ public class ShellSort { public static void sort(Comparable[] a) { int N = a.length; int h = 1; while(h < N/2) { h = 4 * h + 1; } while(h >= 1)

算法(第四版)学习笔记之java实现二叉查找树

二叉查找树:是一棵二叉树,其中每个结点都含有一个键以及相关联的一个值且每个结点的键都大于其左子树中的任意结点的键而小于其右子树中的任意结点的键. 二叉查找树的每个方法功能原理都在代码中有详细的解释,下面来看代码: /** * * @author seabear * 二叉查找树 * @param <Key> * @param <Value> */ public class BTS<Key extends Comparable<Key>,Value> { //定

算法第四版学习笔记之快速排序 QuickSort

软件:DrJava 参考书:算法(第四版) 章节:2.3快速排序(以下截图是算法配套视频所讲内容截图) 1:快速排序 2: