Java堆排序超简代码

引入

堆排序写起来是相对比较简单的排序
排序方法有两种
第一种:
每次删除顶部的值存入数组中
缺点:会造成额外的存储空间

第二种:
每次交换顶部与尾部元素,再对顶部进行下滤即可

这里实现的是第二种方法

代码

// 大根堆的堆排序
public class MaxHeapSort {
	// 对一个数组建大根堆
	public void buildMaxHeap(int arr[], int n){
		// 只需要分支结点(非叶子结点)下滤即可
		for(int i = n / 2; i >= 1; i--){
			Down(arr, i, n);
		}
	}
	// 下滤
	/*
	目的:把k下标的值放到适当位置,使得每一个k节点的值大于它的左右节点值
	1. k节点的值大于左右节点的值,代表k节点处理正确位置,不用动了
	2. 否则,对比左右节点值哪个更大
	3. 与k节点的值进行交换
	4. 使k变为子节点的下标,继续向下对比
	*/
	public void Down(int arr[], int k, int n){
		arr[0] = arr[k];// 先用0位置保存要下滤的值
		for(int i = k * 2; i <= n; i *= 2){// 初始i为k的左结点, 每次增长2倍是不断的往子树下面下滤
			if(i + 1 <= n && arr[i] < arr[i + 1]){// 先对左右子结点对比,选出更小子结点的下标
				i++;
			}
			if(arr[0] > arr[i]){ // 如果父结点大于左右结点表示满足大根堆就退出,记住需要用保存的arr[0],不能arr[k]因为k的值会变
				break;
			}
			arr[k] = arr[i];// 交换值,把父结点的值变为子结点的值,子结点i位置的值还是本身,但是要么被下次循环的子结点值覆盖,要么在循环外被一开始要发生下滤的值覆盖
			k = i;// 父结点的下标变为子结点的下标,即可再次发生下滤
		}
		arr[k] = arr[0];// 确定了一开始k结点元素值的位置
	}
	
	// 堆排序
	/*
	1. 因为是最大堆,每次让头结点与末尾节点交换,使得最大值已经有序
	2. 再让头结点下滤,把未排序的最大值放上顶部
	3. 再如此循环即可
	*/
	public void SwapDownSort(int arr[], int n){
		for(int i = n; i > 1; i--){
			// 交换第一个和最后一个
			swap(arr, 1, i);
			// 交换一下代表确定一个排序的值,需要结点数-1,从根结点1开始下滤 
			Down(arr, 1, i - 1);
		}
	}
	// 辅助方法
	public void swap(int arr[], int i, int j){
		int t = arr[i];
		arr[i] = arr[j];
		arr[j] = t;
	}
	// 遍历
	public void disPlay(int arr[]){
		for(int i = 1; i < arr.length; i++){
			System.out.print(arr[i]+" ");
		}
		System.out.println();
	}
	public static void main(String[] args) {
		int arr[] = {0, 53, 17, 78, 9, 45, 65, 87, 32};// 0位置,空出一个位置,为了从编号从1开始,更方便
		MaxHeapSort wh = new MaxHeapSort();
		int n = arr.length - 1;// n是实际多少个元素
		wh.buildMaxHeap(arr, n);// 建堆
		wh.SwapDownSort(arr, n);// 排序
		wh.disPlay(arr);// 遍历
	}
}

建堆的树结构
在这里插入图片描述

堆排序结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘建杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值