sort-03-SelectSort 选择排序算法详解

简介: 这是一个关于排序算法的系列文章摘要,包括了各种排序算法的介绍和Java实现。文章列举了冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、计数排序、桶排序以及大文件外部排序的链接和简要说明。其中,选择排序算法被详细解释,它是通过找到未排序序列中的最小元素并将其放到正确位置来逐步构建有序序列的。Java实现中,选择排序的`doSort`方法通过两层循环实现,时间复杂度为`O(N^2)`,是稳定的排序算法。整个排序项目已开源在GitHub。

排序系列

sort-00-排序算法汇总

sort-01-bubble sort 冒泡排序算法详解

sort-02-QuickSort 快速排序到底快在哪里?

sort-03-SelectSort 选择排序算法详解

sort-04-heap sort 堆排序算法详解

sort-05-insert sort 插入排序算法详解

sort-06-shell sort 希尔排序算法详解

sort-07-merge sort 归并排序

sort-08-counting sort 计数排序

sort-09-bucket sort 桶排序

sort-10-bigfile 大文件外部排序

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。

选择排序的主要优点与数据移动有关。

如果某个元素位于正确的最终位置上,则它不会被移动。选择排序每次交换一对元素,它们当中至少有一个将被移到其最终位置上,因此对 n 个元素的表进行排序总共进行至多 (n-1) 次交换。

在所有的完全依靠交换去移动元素的排序方法中,选择排序属于非常好的一种。

图片

原地操作几乎是选择排序的唯一优点,当空间复杂度要求较高时,可以考虑选择排序;实际适用的场合非常罕见。

java 实现

package com.github.houbb.sort.core.api;

import com.github.houbb.log.integration.core.Log;
import com.github.houbb.log.integration.core.LogFactory;
import com.github.houbb.sort.core.util.InnerSortUtil;

import java.util.List;

/**
 * 选择排序
 * @author binbin.hou
 * @since 0.0.3
 */
public class SelectSort extends AbstractSort {
   
   

    private static final Log log = LogFactory.getLog(SelectSort.class);

    @Override
    @SuppressWarnings("all")
    protected void doSort(List<?> original) {
   
   
        // 遍历,从 0,n-1
        final int size = original.size();
        for(int i = 0; i < size-1; i++) {
   
   
            int minIndex = i;

            // 比较,找到最小的一个。
            for(int j = i+1; j < size; j++) {
   
   
                if(InnerSortUtil.lt(original, j, minIndex)) {
   
   
                    minIndex = j;
                }
            }

            // 进行交换
            if(minIndex != i) {
   
   
                InnerSortUtil.swap(original, i, minIndex);
            }
        }
    }

}

可见选择排序的实现其实非常简单,也很容易理解。

直接一个循环,找到后面最小的一个元素,如果不是当前位置的元素,则进行一次交换即可。

比较方法

为了便于复用,我们把小于的比较方法抽成工具方法,实现如下:

/**
 * 是否小于元素
 * @param original 原始
 * @param i 索引
 * @param j 指定元素索引
 * @since 0.0.3
 */
@SuppressWarnings("all")
public static boolean lt(List original, int i, int j) {
   
   
    Comparable source = (Comparable) original.get(i);
    Comparable target = (Comparable) original.get(j);
    return source.compareTo(target) < 0;
}

静态化

为了让这个排序使用起来更加方便,我们将其封装为静态方法:

/**
 * 选择排序
 * @param <T> 泛型
 * @param list 列表
 * @since 0.0.3
 */
public static <T extends Comparable<? super T>> void select(List<T> list) {
   
   
    Instances.singleton(SelectSort.class).sort(list);
}

测试

测试代码

List<Integer> list = RandomUtil.randomList(5);
System.out.println("开始排序:" + list);
SortHelper.select(list);
System.out.println("完成排序:" + list);

测试日志

日志如下:

开始排序:[6, 11, 79, 77, 50]
完成排序:[6, 11, 50, 77, 79]

复杂度与稳定性

从代码中可以看出一共遍历了n + n-1 + n-2 + … + 2 + 1 = n (n+1) / 2 = 0.5 n ^ 2 + 0.5 * n,那么时间复杂度是 O(N^2)

所以性能还是比较差的,一般不建议使用。

因为在无序部分最大元素和有序部分第一个元素相等的时候,可以将无序部分最大元素放在前面,所以选择排序是稳定的。

开源地址

为了便于大家学习,上面的排序已经开源,开源地址:

https://github.com/houbb/sort

欢迎大家 fork/star,鼓励一下作者~~

小结

快速排序之所比较快,因为相比冒泡排序,每次交换是跳跃式的。

每次排序的时候设置一个基准点,将小于等于基准点的数全部放到基准点的左边,将大于等于基准点的数全部放到基准点的右边。这样在每次交换的时候就不会像冒泡排序一样每次只能在相邻的数之间进行交换,交换的距离就大的多了。

只能说,分治算法,永远滴神!

希望本文对你有帮助,如果有其他想法的话,也可以评论区和大家分享哦。

各位极客的点赞收藏转发,是老马持续写作的最大动力!

相关文章
|
1月前
|
算法 搜索推荐
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
本文介绍了冒泡排序、选择排序和插入排序三种基础排序算法的原理、实现代码和测试结果。
17 0
数据结构与算法学习十一:冒泡排序、选择排序、插入排序
|
1月前
|
搜索推荐 Java Go
深入了解选择排序算法
深入了解选择排序算法
20 4
|
1月前
|
搜索推荐 算法
【排序算法(一)】——插入排序,选择排序 —> 深层解析
【排序算法(一)】——插入排序,选择排序 —> 深层解析
|
1月前
|
算法 Python
Python算法编程:冒泡排序、选择排序、快速排序
Python算法编程:冒泡排序、选择排序、快速排序
|
3月前
|
搜索推荐 算法 Java
经典排序算法之-----选择排序(Java实现)
这篇文章通过Java代码示例详细解释了选择排序算法的实现过程,包括算法的基本思想、核心代码、辅助函数以及测试结果,展示了如何通过选择排序对数组进行升序排列。
经典排序算法之-----选择排序(Java实现)
|
5月前
|
机器学习/深度学习 算法 搜索推荐
数据结构算法--2 冒泡排序,选择排序,插入排序
**基础排序算法包括冒泡排序、选择排序和插入排序。冒泡排序通过相邻元素比较交换,逐步将最大值“冒”到末尾,平均时间复杂度为O(n^2)。选择排序每次找到剩余部分的最小值与未排序部分的第一个元素交换,同样具有O(n^2)的时间复杂度。插入排序则类似玩牌,将新元素插入到已排序部分的正确位置,也是O(n^2)复杂度。这些算法适用于小规模或部分有序的数据。**
|
5月前
|
搜索推荐
排序算法---选择排序-----详解&&代码
排序算法---选择排序-----详解&&代码
|
5月前
|
算法 搜索推荐
数据结构与算法-选择排序
数据结构与算法-选择排序
30 4
|
5月前
|
搜索推荐 算法
【C/排序算法】:堆排序和选择排序
【C/排序算法】:堆排序和选择排序
34 0
|
5月前
|
算法 搜索推荐 Java
JavaSE——算法(1/2):认识、冒泡排序、选择排序及优化(介绍、详细图解、代码)
JavaSE——算法(1/2):认识、冒泡排序、选择排序及优化(介绍、详细图解、代码)
34 0