Java算法总结(5)_选择排序

1、选择排序

在这里插入图片描述
  在上一篇中初探比较排序,向大家介绍了插值排序,使得大家对比较排序有个大体的了解,那么在接下来的该篇中将为大家介绍选择排序的思想,当然从字面上可以简单的理解,“选择”必然是要在可选范围内,比较出最优值,就好比生活中我们去瓜棚里挑最大的西瓜一样,首先我们会挑相对较大的西瓜拿在手上,然后再去瓜堆中挑更大的西瓜,直到手上拿着的西瓜是最大的为止;下面我将向大家介绍选择包含的简单选择排序和堆排序;

2、简单选择排序
2.1 原理

  从一堆无序元素中,挑出最佳元素,并记住最佳元素的位置,再交换无序元素的首位和最佳位置的元素,通过不断循环以上步骤达到缩小无序范围的目的;

2.2 算法分析

1、 空间复杂度 O(1);
2、 时间复杂度O(N*2)
3、 属于不稳定排序;

2.3 步骤描述

1、 创建临时位置pos指向无序元素的首位;
2、 从左往右遍历无序元素,两两相互比较后,始终让pos指向最优解(最小值位置);
3、 若pos不等于无序元素的首位,那么交换无序首位和pos位置上的元素,否则不动;
4、 循环以上步骤,直到无序范围不断缩小为零为止;

2.4 简单选择排序Java代码
/**
	 * 选择排序
	 * 时间复杂度O(N*2)
	 * @param <T>
	 * @param a
	 */
	public static <T extends Comparable<? super T>> void choiseSort(T[] a) {
		
		int pos;
		for (int i = 0; i < a.length-1; i++) {
			//1、创建临时位置pos指向无序元素的首位;
			pos=i;	
			//2、从左往右遍历无序元素,两两相互比较后,始终让pos指向最优解(最小值位置);
			for (int j = i+1; j < a.length; j++) {				
				if(a[pos].compareTo(a[j])>0) {
					pos=j;					
				}				
			}
			//3、若pos不等于无序元素的首位,那么交换无序首位和pos位置上的元素,否则不动;
			if(pos!=i) {
				T temp=a[i];
				a[i]=a[pos];
				a[pos]=temp;
			}			
		}
		
	}
}

3、堆排序
3.1 原理

  采用max堆或min堆来存储无序元素,利用堆性质,将堆的根元素与最后一个元素调换,在每次调换后缩小堆的范围,然后维持堆序性质不被破坏,直到最后一个元素执行完以上步骤后结束算法;

3.2 堆性质
  • 结构性

  堆是一颗被完全填满的二叉树,有可能例外的是在底层,底层上的元素从左到右填入,这样的数成为完全二叉树;
在这里插入图片描述
具体实现使用数组表示:
在这里插入图片描述
   对于数组中任意位置i上的元素,其左儿子在位置2i上,右儿子在左儿子后的单元(2i+1)中,它的父亲则在位置⌊i/2⌋上。

  • 堆序性

  如果我们考虑任意子树也应该是一个堆,那么任意节点就应该小于(min堆)或者大于(max堆)所有后裔;
  Max堆:
在这里插入图片描述

3.3 算法分析

1、 时间复杂度:O(N*LogN);
2、 空间复杂度O(1);
3、 属于不稳定排序;

3.4 步骤描述

1、 构造max堆或min堆;
2、 调换树根和最后一个元素,并使得堆的大小heapSize=heapSize-1;
3、 维持堆性质,进行下滤;
4、 重复2、3步骤直到堆大小为1为止;

3.5 堆排序Java代码
/**
	 * 堆排序
	 * 时间复杂度O(N*LogN)
	 * @param <T>
	 * @param a
	 */
	public static <T extends Comparable<? super T>> void heapSort(T[] a) {
		//1、构建max堆;
		for(int i=a.length/2-1;i>=0;i--) {
			
			percDown(a,i,a.length);
		}
		
		for(int i=a.length-1;i>0;i--) {
			//2、调换树根和最后一个元素;
			swap(a,0,i);
			//3、维持堆性质,进行下滤;
			percDown(a,0,i);
		}
		
	}
	/**
	 * 下滤 维持堆序性
	 * @param <T>
	 * @param a T数组
	 * @param i 下滤开始位置
	 * @param heapSize 堆的大小
	 */
	private static <T extends Comparable<? super T>> void percDown(T[] a,int i, int heapSize) {
		int child;
		//存放需要下滤的元素
		T temp;
		for(temp=a[i];2*i+1<heapSize;i=child) {
			//左子节点,因为数组是从0索引开始所以左子节点为2*i+1
			child=2*i+1;
			//比较左右子子节点的大小
			if(child!=heapSize-1 && a[child].compareTo(a[child+1])<0) {
				child++;
			} 
			//比较下滤元素与子节点的大小
			if(temp.compareTo(a[child])<0) {
				a[i]=a[child];
			}else {
				break;
			}
		}
		//将下滤元素放入到正确位置;
		a[i]=temp;
	}
	/**
	 * 调换位置
	 * @param <T>
	 * @param a T数组
	 * @param i 位置 i
	 * @param j 位置 j
	 */
	private static <T extends Comparable<? super T>> void swap(T[] a, int i,int j) {
		T temp=a[i];
		a[i]=a[j];
		a[j]=temp;
	}

4、选择算法测试
package xw.zx.algorithm.sort;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class SortTest {
	private static final int ARRAY_LEN=100;
	private static Integer[] arr=new Integer[ARRAY_LEN];
	public static void main(String[] args) {
		List<Integer> l=new ArrayList<>();
		for (int i = 0; i < ARRAY_LEN; i++) {
			l.add(i+1);			
		}
		//乱序列表
		Collections.shuffle(l);
		//列表转换成数组
		arr=l.toArray(new Integer[0]);
		System.out.println("输出原数组");
		printVal(arr);
		//排序
		//AllSorts.choiseSort(arr);
		AllSorts.heapSort(arr);
		System.out.println("输出排序后的数组");
		printVal(arr);
	}
	/**
	 * 打印数组
	 * @param arr
	 */
	private static void printVal(Integer[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i]+" ");
			
		}
		System.out.println("");
	}
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值