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,鼓励一下作者~~

小结

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

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

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

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

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

相关文章
|
12天前
|
搜索推荐 算法 Java
sort-01-bubble sort 冒泡排序算法详解
这是一个关于排序算法的系列文章摘要。作者整理了10种不同的排序算法,包括冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、计数排序、桶排序和大文件外部排序。文章详细介绍了冒泡排序的工作原理、流程,并提供了代码实现,强调了在实现中考虑的改进点,如统一接口、实用性增强和日志输出。此外,还提供了一个排序接口和工具类以方便使用,并通过测试代码和日志展示了排序过程。整个系列旨在帮助读者理解和掌握排序算法。相关代码已开源在GitHub。
|
12天前
|
搜索推荐 算法 Java
sort-02-QuickSort 快速排序到底快在哪里?
这是一个关于排序算法的系列文章的摘要。文章详细介绍了各种排序算法,包括冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、计数排序、桶排序以及处理大文件的外部排序。特别强调了快速排序,它是1959年由Tony Hoare发明的,平均时间复杂度为O(n log n),优于其他如合并排序和堆排序。快速排序采用分而治之的策略,选取基准元素,通过分区操作将数组分成两部分,然后递归地对这两部分进行排序。文章还通过示例和Java代码解释了快速排序的步骤和实现。最后,提供了开源项目的链接,供读者进一步学习和研究。
|
12天前
|
搜索推荐 算法 Java
sort-05-insert sort 插入排序算法详解
这是一个关于排序算法的系列文章总结,包括冒泡排序、快速排序、选择排序、堆排序、插入排序等10种排序算法的详细讲解和Java实现。插入排序是一种简单直观的排序算法,通过构建有序序列并逐个插入新元素来排序。提供的Java代码展示了插入排序的实现过程,并附有测试示例。所有算法已开源在GitHub项目[https://github.com/houbb/sort](https://github.com/houbb/sort)中。
|
12天前
|
搜索推荐 算法 Java
sort-08-counting sort 计数排序
这是一个关于排序算法的系列文章摘要。文章详细介绍了多种排序算法,包括冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、计数排序、桶排序以及大文件外部排序。计数排序是一种线性时间复杂度的稳定排序算法,由 Harold H. Seward 在1954年提出。基础版计数排序通过创建一个与最大元素等长的新数组来统计每个元素出现的次数,然后填充排序结果。改良版则考虑了空间浪费问题,通过找出最小值来减少数组长度。此外,还提出了使用 TreeMap 来扩展排序算法以适应非数字元素的情况。
|
10月前
|
存储 算法 搜索推荐
2-路插入排序(Two-Way Insertion Sort)
算法介绍 算法描述 算法分析 代码实现 参考
|
搜索推荐 算法 数据可视化
【基础篇】9 # 排序:冒泡排序(Bubble Sort)、插入排序(Insertion Sort)、选择排序(Selection Sort)
【基础篇】9 # 排序:冒泡排序(Bubble Sort)、插入排序(Insertion Sort)、选择排序(Selection Sort)
76 0
【基础篇】9 # 排序:冒泡排序(Bubble Sort)、插入排序(Insertion Sort)、选择排序(Selection Sort)
|
缓存 搜索推荐 算法
图解插入排序——直接插入排序算法(straight insertion sort)
图解插入排序——直接插入排序算法(straight insertion sort)
165 0
图解插入排序——直接插入排序算法(straight insertion sort)
|
机器学习/深度学习 搜索推荐 算法
图解快排——快速排序算法(quick sort)
图解快排——快速排序算法(quick sort)
174 0
图解快排——快速排序算法(quick sort)
|
机器学习/深度学习 算法 搜索推荐
经典算法之冒泡排序(Bubble Sort)
经典算法之冒泡排序(Bubble Sort)
125 0
经典算法之冒泡排序(Bubble Sort)