堆排序的Java实现(简化代码+详细说明)

本文详细介绍了一种高效的排序算法——堆排序。通过两个主要步骤:构建初始堆和调整堆,实现数组的排序。以大顶堆为例,展示了如何将无序数组转化为有序数组,适用于需要高效排序的大规模数据处理。

关于堆排序已经有很多算法原理的讲解文章,这里就不多说了。

本文将堆排序分成两个过程来实现:

  • 堆调整过程
  • 排序过程

以大顶堆为例,实现对数组从小到大进行排序:

public class Heap_Sort {
	public static void main(String[] args) {
		int[] arr = { 54, 26, 93, 17, 77, 31, 44, 55, 20 };

		System.out.println("original statement:");
		for (int i = 0; i < arr.length; i++)
			System.out.print(arr[i] + " ");
		System.out.println();

		heapSort(arr); 

		System.out.println("heapsort finished:");
		for (int i = 0; i < arr.length; i++)
			System.out.print(arr[i] + " ");
		System.out.println();
	}

	private static void heapAdjust(int[] arr, int s, int m) {
		// 建立大顶堆
		// 注意如果堆的根节点的索引是从0开始的,那么下标为i的节点,其父节点的下标就是(i-1)/2
		// 第i个节点的左右子节点,它们的下标分别为2i+1和2i+2
		int rc = arr[s];    // 定义当前的根节点
		for (int j = s * 2 + 1; j <= m; j = s * 2 + 1) { // 这里注意是j<=m,当最后只剩2个节点(0号和1号)时,仍然work。j从第一个叶结点开始
			if (j < m && arr[j] < arr[j + 1])    // 比较两个子结点的大小,使指针保持指向子结点中值较大的那个
				j++;
			if (rc >= arr[j])    // 比较当前的根节点和最大的子结点的值的大小,如果根节点较大,那这个局部的子树已经是一个大顶堆了
				break;
			arr[s] = arr[j];   // 如果子结点的值较大,那就将此子结点的值赋给根节点
			s = j;    // 将较大的子结点的索引赋给s,保持s指向较大值的索引值
		}
		arr[s] = rc;   // 出循环之后,将根节点的值回赋给数组中索引值为s的元素
	}

	private static void heapSort(int[] arr) {
		// 建堆(大顶堆)
		for (int i = arr.length / 2 - 1; i >= 0; i--)  // i是最后一个非叶结点,且为arr.length/2-1,从最后一个非叶结点开始向前逐步建堆,直到堆顶的根节点(下标为0)
			heapAdjust(arr, i, arr.length - 1);

		System.out.println("heap has been built:");
		for (int i = 0; i < arr.length; i++)
			System.out.print(arr[i] + " ");
		System.out.println();

		for (int i = arr.length - 1; i > 0; i--) {   // 输出堆顶元素,并在输出后重新调整堆
			int tmp = arr[0];
			arr[0] = arr[i];
			arr[i] = tmp;
			heapAdjust(arr, 0, i - 1);
			
			System.out.println("i=" + i);
			for (int j = 0; j < arr.length; j++)
				System.out.print(arr[j] + " ");
			System.out.println();
		}
	}
}

输出结果:

original statement:
54 26 93 17 77 31 44 55 20 
heap has been built:
93 77 54 55 26 31 44 17 20 
i=8
77 55 54 20 26 31 44 17 93 
i=7
55 26 54 20 17 31 44 77 93 
i=6
54 26 44 20 17 31 55 77 93 
i=5
44 26 31 20 17 54 55 77 93 
i=4
31 26 17 20 44 54 55 77 93 
i=3
26 20 17 31 44 54 55 77 93 
i=2
20 17 26 31 44 54 55 77 93 
i=1
17 20 26 31 44 54 55 77 93 
heapsort finished:
17 20 26 31 44 54 55 77 93 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值