数据结构之经典排序(一)

目录

一、选择排序

 1. 算法思路

2. 算法实现

3. 算法分析

二、简单插入排序

1. 算法思路

2. 算法实现

3. 算法分析 

三、冒泡排序

1. 算法思路

2. 算法实现

3. 算法分析


一、选择排序

 1. 算法思路

      首先从第一个元素到最后一个元素中选择一个最小的元素,将最小的元素和第一个元素进行交换;然后从剩下的元素(第二个元素到最后一个元素)选择最小的元素,将第二个元素与最小的元素进行交换,按照这个过程进行直至到达最后一个元素结束。

2. 算法实现

public class SelectSort {

    // min存放最小值的下标,不要直接对数组进行操作
    public static int[] selectSort(int[] arr) {
        int i = 0, j = 0;
        int len = arr.length;
        for (i = 0; i < len - 1; i++) {
            int min = i;
            for (j = (i + 1); j < len; j++) {
                // arr[i]与arr[j]进行比较,设置最小值下标
                if (arr[min] > arr[j]) {
                    min = j;
                }
            }
            // swap
            int temp = arr[i];
            arr[i] = arr[min];
            arr[min] = temp;
        }
        return arr;
    }

}

3. 算法分析

选择排序总共需进行(n - 1)趟排序(n表示数组的长度),其中每一趟需要进行(n - (i + 1))次比较,排序总共进行(n - 1) * n / 2次比较,时间复杂度T(n) = O(n²)时间复杂度S(n)= O(1)

二、简单插入排序

1. 算法思路

    给定一个待排序数组a,确定{a[0]}为已排序序列,{a[1], a[2] ... a[k] }为待排序列,插入排序顾名思义,选择待排序列的第一个元素ele,通过ele与已排序序列按照从尾比较的方式,如果ele < 当前元素(current), 将current元素后移,如果ele >= 当前元素(cuurent), 停止比较并在current元素下标 + 1 处的元素设置ele,这就是一次插入过程,此时已排序序列为{a[0], a[1]},待排序列为{a[2], a[3], ... a[k]}, 按照这个过程直至待排序列没有元素停止。

2. 算法实现

public static int[] insertSort(int[] arr) {
        int i, j;
        // 假设第一个元素为有序序列,接下来的一个元素与有序序列从末尾开始依次比较,并插入到合适的位置
        int len = arr.length;
        for (i = 1; i < len; i++) {
            int temp = arr[i];
            // 插入思路:若插入元素小于当前元素,那么有序序列当前元素后移
            // 如果有序序列元素发生移动,所以(j + 1)处一定是之前的元素,也就是说原来的元素移到了( j + 2)处
            // 故直接在(j + 1)处插入元素就行。
            for (j = i - 1; j >= 0 && temp <= arr[j] ; j--) {
                arr[j + 1] = arr[j];
            }
            arr[j + 1] = temp;
        }
        return arr;
    }

3. 算法分析 

简单插入排序关键在于插入元素与已排序序列的比较过程,考虑最坏情况下,插入元素比任何一个已排序序列中的元素都小,故元素的移动次数为i,此算法时间复杂度为T(n) = O(n²)

空间复杂度S(n) = O(1)

三、冒泡排序

1. 算法思路

      冒泡排序是交换排序的一种,正如冒泡一样,它通过相邻元素的比较交换,将满足条件的元素不断上浮,反过来不符合条件的元素会下沉。假设排序数组元素个数为n,那么需要进行(n - 1) 趟比较,每次比较始终从数组首元素开始,通过一趟比较(正序),数组最后一个元素一定是最大元素,因而下一趟的比较不需要对最后一个元素进行比较。冒泡排序的比较策略是设置两个指针pre, current, 每次比较这两个指针所指向的元素,较大者下沉,同时pre、current指针后移,返回执行这个过程,直至完成所有的趟数。

      算法优化,假设在第k趟完成了正序排序,那么第(k + 1)趟 到(n - 1)趟是没有必要的,因此设置一个哨兵位,如果一趟中没有进行比较交换,那么哨兵位设置为0,若发生交换,哨兵位设置为1,下一趟比较条件除了判断是否趟数已够还需判断哨兵位的状态。

2. 算法实现

// 双指针 k指向pre元素,j指向current元素
    public static int[] bubbleSort(int[] arr) {
        int len = arr.length;
        // 总共(len - 1)趟
        for (int i = 0; i < len - 1; i++) {
            // 定义哨兵,用于探测是否需要下一趟冒泡
            int count = 0;
            int pre = 0;
            for (int j = 1; j < (len - i); j++, pre++) {
                // 比较arr[i] 与 arr[j] 较大者下沉
                if (arr[pre] > arr[j]) {
                       int temp = arr[pre];
                    arr[pre] = arr[j];
                    arr[j] = temp;
                    // 发生交换,count = 1 表示a[i]~a[j]序列仍可能存在无序
                    count = 1;
                }
            }
            if (count == 0) {
                break;
            }
        }
        return arr;
    }

3. 算法分析

冒泡排序 每一趟比较的次数为(n - i - 1), 最坏情况下,每一趟都需进行(n - i - 1)次比较,

时间复杂度T(n) = O(n²), 空间复杂度 S(n) = O(1)


         上面三种排序是很经典的排序,算法实现并不复杂,后续我会更新其他经典的排序算法。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章! 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

弘弘弘弘~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值