排序>>选择排序

目录

一、直接选择排序

1)直接选择排序的优化

二、堆排序(从小到大排序)


本文详细讲解了选择排序,有需求的伙伴可以观看。

一、直接选择排序

选择排序的思想:每一轮从待排序区间里选出最小(或最大)的元素,放到待排序区间的最前面,逐步缩小待排序区间。

步骤:

  1. 初始:已排序区为空,整个数组都是待排序区。
  2. 第 1 轮:在全部待排序元素中找到最小值的下标,和待排序区第一个元素交换,此时第一个位置排好(最小的数)。
  3. 第 2 轮:在剩下的待排序元素里继续找最小值,和待排序区第一个位置交换,前两个位置有序。
  4. 不断重复,待排序区间不断缩小,直到只剩 1 个元素,排序结束。

图例:

代码示例:

java 复制代码
/**
     * 直接选择排序
     * Time complexity :O(N^2)
     * Space complexity :O(1)
     * Stability : unstable
     * @param array
     */
    public static void selectSort(int[] array){
        for(int i = 0; i < array.length; i++){
            int minIndex = i;
            for(int j = i + 1; j < array.length; j++){
                if(array[minIndex] > array[j]){
                    minIndex = j;
                }
            }
            swap(array,i,minIndex);
        }
    }
    public static void swap(int[] array,int i,int j ){
            int tmp = array[i];
            array[i] = array[j];
            array[j] = tmp;
    }

【直接选择排序的特性总结】

  • 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

1)直接选择排序的优化

在上面这个选择排序中,只是将最小值的下标进行了交换,而优化后的可以同时对最小值和最大值的下标进行同时交换。

思想:

数组依然划分:[left ... right] 待排序区间

  1. 在 left ~ right 里同时找到最小值下标 minIdx、最大值下标 maxIdx
  2. 把最小值交换到 low 位置
  3. 把最大值交换到 high 位置
  4. left++,right--,缩小区间,直到 left >= right

坑点:如果最大值下标刚好等于 low(最小值原来在 max 的位置,交换 min 之后 max 的位置变了!),要特殊处理

下面是图例:

代码示例:

java 复制代码
 public static void selectSort2(int[] array){
        int left = 0;
        int right = array.length - 1;
        while(left < right){
            int minIndex = left;
            int maxIndex = left;
            for(int i = left + 1; i <= right;i++){
                if(array[i] > array[maxIndex]){
                    maxIndex = i;
                }
                if (array[i] < array[minIndex]) {
                    minIndex = i;
                }
            }
            swap(array,left,minIndex);
            if(maxIndex == left){
                maxIndex = minIndex;
            }
            swap(array,right,maxIndex);
            left++;
            right--;
        }
    }

二、堆排序(从小到大排序)

思路:堆排序需要我们先建大根堆,此时堆顶的元素一定是最大值,使堆顶的元素和最后一个元素的位置进行交换,此时最大值就跑到最后面了,这个时候我们再把有效长度减一,从堆顶继续向下调整重复这个操作。

图例:

代码示例:

java 复制代码
public static void heapSort(int[] array){
        createHeap(array);
        int end = array.length - 1;
        while(end > 0){
            swap(array,0,end);
            shiftDown(array,0,end);
            end--;
        }
    }
private static void createHeap(int[] array) {
        for(int parent = (array.length - 1 -1) / 2; parent &gt;= 0;parent--){
            shiftDown(array,parent,array.length);
        }
}

private static void shiftDown(int[] array, int parent, int length) {
    int child = parent * 2 + 1;
    while(child &lt; length){
        if(child + 1 &lt; length &amp;&amp;array[child] &lt;array[child + 1]){
            child++;
        }
        if(array[child] &gt; array[parent]){
            swap(array,child,parent);
            parent = child;
            child = 2 * parent +1;
        }else{
            break;
        }
    }

}

public static void swap(int[] array,int i,int j ){
    int tmp = array[i];
    array[i] = array[j];
    array[j] = tmp;
}
}

【堆排序的特性总结】

    1. 堆排序使用堆来选数,效率就高了很多。
    1. 时间复杂度:O(N*logN)
    1. 空间复杂度:O(1)
    1. 稳定性:不稳定
相关推荐
二十七日秋19 分钟前
算法刷题笔记「Day 1|四道 OJ 入门题里的深坑」
c语言·汇编·数据结构·c++·笔记·python·算法
晚风叙码33 分钟前
Linux 进程概念(下):程序地址空间与虚拟内存
linux·服务器·算法
silvamux_1 小时前
微头条爆款体平台适配实测:把交付要求变成可计算的指标
java·线性代数·算法·决策树·矩阵
重生之小比特1 小时前
【算法拾光】前缀和|连续的子数组和 + 和相同的二元子数组
算法·leetcode·哈希算法
一去不复返的通信er2 小时前
力扣15:盛最多水的容器
算法·leetcode
Navigator_Z2 小时前
LeetCode //C - 1309. Decrypt String from Alphabet to Integer Mapping
c语言·算法·leetcode
潇湘秦2 小时前
SQL Server 2016+ 整数类型元数据扩宽(秒级变更)完整说明
数据库·算法
小白起 v2 小时前
02-数组与链表
数据结构·链表
Figo_Cheung3 小时前
Figo基于结构空间算法假设(SSAH)的生成式大模型优化范式与工程实现边界研究——提出适应AGI架构演化的自适应拓扑感知表征机制
算法·架构·agi
旖旎夜光3 小时前
LCR 170:交易逆序对的总数(归并排序) —— 题解
c++·学习·算法·leetcode·排序算法