堆排序

树结构实际应用堆排序

思路说明

堆排序其实是选择排序的一种,构建大顶堆后,将选择元素放在堆顶再放在数组末尾
堆排序基于顺序化二叉树进行调整
大顶堆
非叶子节点都比其子节点要大
小顶堆:
非叶子节点都比其子节点要小

在这里插入图片描述

当前节点为i ,左子节点:2i+1,右子节点:2i+2。
将树从上自下,从左至右,标记下标,第一个非叶子节点下标为length/2-1;

图解思路

局部构建
在这里插入图片描述

整体构建(== 注意这的指向6的指针,下一步是指向8去判断调整为大顶堆,这样才能满足,从上至下,从左至右调整为大顶堆的过程==)

在这里插入图片描述


选择插入
在这里插入图片描述

代码从局部到整体

注意:每次构建大顶堆是局部构建的,并不是一部构建出的
1.局部构建方法

public static void bigtop(int[]arr,int i,int length) {
		//该方法是对于局部而言的
		int temp=arr[i];//先保存,再插入防止覆盖
		
		for (int k = 2*i+1; k <length; k=2*k+1) {//注意这里的长度为局部长度不是整个数组的长度
			//往下找,直到没有节点
			
			if (arr[k]<arr[k+1]&&k+1<length) {//左节点小于右节点,用右节点比较
				k++;
			}
			if (temp<arr[k]) {//当前节点小于子节点,交换
				arr[i]=arr[k];
				i=k;//将当前节点指向下一层,继续循环比较
			}else {
				break;//当前节点的子节点都比当前节点小
			}
		}
		arr[i]=temp;
		
		
	}
  1. 通过每次局部构建达到整体构建的方法
for (int i =arr.length/2-1; i >=0; i--) {
			//性质,第一个非叶子节点下标为 arr.length/2-1,横向记录下标为例子
			//从第一个非叶子节点从下至上(i--),从左至右排序
			bigtop(arr, i, arr.length);
		}//第一次排成大顶堆
		System.out.println(Arrays.toString(arr));
		

3.堆排序实现

package competion2020;

import java.util.Arrays;

public class 堆排序 {

	public static void main(String[] args) {
		// TODO 自动生成的方法存根
		int arr[]= {4,6,8,5,9};
		//待排序序列构造成一个大顶堆
		heapSort(arr);
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]);
		}
		

	}

	public static void heapSort(int[] arr) {
		for (int i =arr.length/2-1; i >=0; i--) {
			//性质,第一个非叶子节点下标为 arr.length/2-1,横向记录下标为例子
			//从第一个非叶子节点从下至上(i--),从左至右排序
			bigtop(arr, i, arr.length);
		}//第一次排成大顶堆
		System.out.println(Arrays.toString(arr));
		
		int temp;
		//将堆顶元素与末尾元素交换,再重新对剩余子堆进行调整为大顶堆
		for (int i = arr.length-1; i >0;i--) {
			 temp= arr[i];
			arr[i]=arr[0];
			arr[0]=temp;
			bigtop(arr, 0, i);//建立在上一个for循环已经构建成大顶堆的情况下
			//大顶堆已排好,只是交换头顶元素此时将堆底元素与堆顶元素交换后,对顶节点数肯定小于子节点
		}
		System.out.println(Arrays.toString(arr));
		
	}
	
	//注意应用数学抽象,将树抽象为数组,参数length为某一子树的大小
	public static void bigtop(int[]arr,int i,int length) {
		//该方法是对于局部而言的
		int temp=arr[i];//先保存,再插入防止覆盖
		
		for (int k = 2*i+1; k <length; k=2*k+1) {//注意这里的长度为局部长度不是整个数组的长度
			//往下找,直到没有节点
			
			if (arr[k]<arr[k+1]&&k+1<length) {//左节点小于右节点,用右节点比较
				k++;
			}
			if (temp<arr[k]) {//当前节点小于子节点,交换
				arr[i]=arr[k];
				i=k;//将当前节点指向下一层,继续循环比较
			}else {
				break;//当前节点的子节点都比当前节点小
			}
		}
		arr[i]=temp;
		
		
	}

}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值