八大排序算法--选择排序(动图理解)

选择排序

算法思路

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。

选择排序的步骤:

1>首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

2>再从剩余未排序元素中继续寻找最小(大)元素,然后放到未排序序列的起始位置。

3>重复第二步,直到所有元素均排序完毕。

动画演示

算法代码

java 复制代码
public static void selectSort1(int[] a){

        for (int i = 0; i < a.length; i++) {
            int minIndex = i;
            for (int j = i+1 ; j <a.length ; j++) {
                if(a[j] <= a[minIndex]){
                    minIndex = j;
                }
            }
            if(minIndex == i) continue;  //说明没找到更小的
            int tmp = a[minIndex];
            a[minIndex] = a[i];
            a[i] = tmp;
        }
    }

复杂度分析

时间复杂度 O(n^2) 等差数列

空间复杂度 O(1)

稳定性 不稳定

选择排序优化

选择排序的优化思路一般是在一趟遍历中,同时找出最大值与最小值,放到数组两端,这样就能将遍历的趟数减少一半。第一次选择最大值与最小值,过程如下:

算法代码

java 复制代码
public static void selectSort2(int[] a){

        int left  = 0;
        int right = a.length-1;
        while(left<right) {
            int minIndex = left;
            int maxIndex = right;
            for(int i = left+1;i<=right;i++) {
                if(a[i] < a[minIndex]) {
                    minIndex = i;
                }
                if(a[i] > maxIndex) {
                    maxIndex = i;
                }
            }

            //交换左边
            int tmp1 = a[minIndex];
            a[minIndex] = a[left];
            a[left] = tmp1;

            if(maxIndex == left) {   //很重要的一点细节
                maxIndex = minIndex;
            }

            //交换右边
            int tmp2 = a[maxIndex];
            a[maxIndex] = a[right];
            a[right] = tmp2;

            left++;
            right--;

        }
    }

时间复杂度测试

接下来我们试着用大量数据测试一下。

int[] a = new int[10_0000]; //10万个数据测试

1.orderArray函数实现生成一个基本有序数列,即从小到大排列。

java 复制代码
public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
 }

2.notOrderArray函数生成一个倒序数列,即从大到小排列。

java 复制代码
public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        } 
}

3.randomArray函数生成一个随机无序数列。

java 复制代码
 public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
 }

4.testInsertSort函数测试 System.currentTimeMillis() 返回值单位是毫秒。

java 复制代码
 public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        shellSort(tmpArray);
        long endTime = System.currentTimeMillis();  //返回单位是毫秒
        System.out.println("选择排序耗时:"+(endTime-startTime));
  }

5.main函数调用执行

java 复制代码
public static void main(String[] args) {
 
        int[] a = new int[10_0000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);
 
        //倒序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);
 
        //随机乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);
}

测试结果

从结果来看,对于大量的数据,优化后的反而更慢了,应该是这种排序算法更适合少量数据。

我们放250个数据进行测试。

结果证明耗时上还是有所下降的。

完整代码

java 复制代码
import java.util.Random;


public class sort {
    public static void main(String[] args) {
    
        int[] a = new int[10_0000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);

        //无序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);

        //乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);

    }

    public static void selectSort(int[] a){

        for (int i = 0; i < a.length; i++) {
            int minIndex = i;
            for (int j = i+1 ; j <a.length ; j++) {
                if(a[j] <= a[minIndex]){
                    minIndex = j;
                }
            }
            if(minIndex == i) continue;  //说明没找到更小的
            int tmp = a[minIndex];
            a[minIndex] = a[i];
            a[i] = tmp;
        }
   }


    //生成有序数组  从小到大排列
    public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
    }

    //n无序 其实就是从大到小排列
    public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        }
    }

    //乱序 随机生成序列
    public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
    }

    //大量数据测试
    public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        selectSort(tmpArray);
        long endTime = System.currentTimeMillis();
        System.out.println("选择排序耗时:"+(endTime-startTime));
    }
}

创作不易,如果本篇博客对您有一定的帮助,大家记得留言+点赞哦。

相关推荐
陌上花开࿈1 小时前
调用第三方接口
java
浊酒南街1 小时前
决策树python实现代码1
python·算法·决策树
Aileen_0v01 小时前
【玩转OCR | 腾讯云智能结构化OCR在图像增强与发票识别中的应用实践】
android·java·人工智能·云计算·ocr·腾讯云·玩转腾讯云ocr
冠位观测者2 小时前
【Leetcode 热题 100】208. 实现 Trie (前缀树)
数据结构·算法·leetcode
桂月二二3 小时前
Java与容器化:如何使用Docker和Kubernetes优化Java应用的部署
java·docker·kubernetes
liuxin334455663 小时前
学籍管理系统:实现教育管理现代化
java·开发语言·前端·数据库·安全
小马爱打代码3 小时前
设计模式详解(建造者模式)
java·设计模式·建造者模式
小王爱吃月亮糖3 小时前
C++的23种设计模式
开发语言·c++·qt·算法·设计模式·ecmascript
栗子~~4 小时前
idea 8年使用整理
java·ide·intellij-idea
2301_801483694 小时前
Maven核心概念
java·maven