数据结构与算法-选择排序与堆排序

选择排序

选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一元素,再依规定交换位置后达到 排序的目的。

选择排序思想

选择排序(select sorting)也是一种简单的排序方法。它的基本思想是:第一次从 arr[0]~arr[n-1]中选取最小值, 与 arr[0]交换,第二次从 arr[1]~arr[n-1]中选取最小值,与 arr[1]交换,第三次从 arr[2]~arr[n-1]中选取最小值,与 arr[2] 交换,…,第 i 次从 arr[i-1]~arr[n-1]中选取最小值,与 arr[i-1]交换,…, 第 n-1 次从 arr[n-2]~arr[n-1]中选取最小值, 与 arr[n-2]交换,总共通过 n-1 次,得到一个按排序码从小到大排列的有序序列。

选择排序思路分析图

在这里插入图片描述
对一个数组的选择排序再进行讲解
在这里插入图片描述

实现

package my.sort;

public class SelectSort {
	public static void main(String[] args) {
		int[] arr= {2,5,12,2,6,22,11,99,3};
		sort(arr);
		for(int data: arr) {
			System.out.println(data);
		}
	}
	private static void sort(int[] arr) {
		int length=arr.length;
		//存最小值
		int min=0;
		// k 用于存最小值的坐标
		for(int i=0; i<length-1;i++) {
			int k=i;
			min=arr[i];
			for(int j=i+1;j<length;j++) {
				if(min>arr[j]) {
					//找到最小值,记录最小值和下标
					min=arr[j];
					k=j;
				}
			} 
			//k与i相等,说明,最小值就是他自己。
			if(k!=i) {
				arr[k]=arr[i];
				arr[i]=min;
			}
		
			
		}

	}
}

堆排序

  • 堆排序是利用堆而设计的一种排序算法,其最好,最坏,平均时间复杂度都是O(nlongn),不稳定排序的;
  • 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆, 注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。
  • 每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆 。
    注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。

大顶推

即父节点永远大于等于两个子节点。前提是二叉树;
在这里插入图片描述

小顶堆

即父节点永远小于等于两个子节点。前提是二叉树;
在这里插入图片描述

堆排序的思想

堆排序的基本思想是:

  • 将待排序序列构造成一个大顶堆(小顶堆)
    此时,整个序列的最大值(最小值)就是堆顶的根节点。

  • 将其与末尾元素进行交换,此时末尾就为最大值(最小值)。

  • 然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小(大)值。重复n-1次上述过程,就能完成了。

这个算法实现使用递归更为方便,更为简洁。

堆排序步骤图解说明

要求:给你一个数组 {4,6,8,5,9} , 要求使用堆排序法,将数组升序排序。

构造初始堆

将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。 原始的数组 [4, 6, 8, 5, 9]。
在这里插入图片描述
从最后一个非叶子结点开始(叶结点自然不用调整,第一个非叶子结点
arr.length/2-1=5/2-1=1,也就是下面的 6 结点)调整;
在这里插入图片描述
调整[4,9,8]
在这里插入图片描述
[4,5,6]混乱,重新调整
在这里插入图片描述
我们就将一个无序序列构造成了一个大顶堆

堆顶元素与末尾元素进行交换
将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换

  • 9与4进行交换
    在这里插入图片描述

重新调整结构
在这里插入图片描述
5与8进行交换;
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210603162520508.png?x-oss-process=image/watermark,type_在这里插入图片描述
继续进行调整,交换,最后就可以获得最大堆了。
在这里插入图片描述

基本思路

1).将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
2).将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
3).重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,重复调整+交换步骤, 直到整个序列有序。

public static void main(String[] args) {
	// TODO Auto-generated method stub
	int[] arr= {
			4,6,8,5,9,10,16,17,13
	};
	heapSort(arr);
	System.out.println(Arrays.toString(arr));
}
public static void heapSort(int arr[]) {
	int temp=0;
	//在这里,将一个无需的数组 转化为一个大顶堆。
	for(int i=arr.length/2-1;i>=0;i--) {
		adjustHeap(arr,i,arr.length);
	}
	//在这里,将数组的最大值,也就是大顶堆的头顶和数组末尾n元素进行交换,
	//每一次交换后,末尾就是最大值,在对剩余的n-1个元素进行排序-->
	//由于交换完后,大顶堆可能变为无需的队。所以需要在此排序,变为大顶堆。
	//然后再将大顶堆的头部最大值与第n-1个元素交换,重复这个过程,直到所有元素的排完
	for(int j=arr.length-1;j>0;j--) {
		temp=arr[j];
		arr[j]=arr[0];
		arr[0]=temp;
		adjustHeap(arr,0,j);
	}
	
	
}
/**
 * 
 * @param arr 数组
 * @param i 非叶子结点的序号
 * @param length 排序的数组的长度
 */
public static void adjustHeap(int[] arr,int i,int length) {
	//先将第i个非叶子结点的值保存
	int temp=arr[i];
	//找到 第i个非叶子结点的两个子节点
	for(int k=2*i+1; k<length;k=2*k+1) {
		//如果左子节点小于又子节点,则k=k+1。
		if(k+1<length && arr[k]<arr[k+1]) {
			k++;
		}
		//将两个子节点中的最大值与temp父节点(也就是第i个非叶子结点)进行比较,
		//若子节点的值大于父节点的值,则进行交换,否则直接退出循环,
		//因为这个循环是从左到右,从下到上进行排序的
		if(temp<arr[k]) {
			arr[i]=arr[k];
			//记录第i个非叶子结点的下一个非叶子结点的值。
			i=k;
		}else {
			break;
		}
		arr[i]=temp;
		//在将叶子结点的值换位非叶子结点的值。
	}
}}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值