数据结构+算法篇-01:冒号排序;选择排序;插入排序代码,关系,及其内蕴的共同算法逻辑

01-开始的故事:

相信每一个接触数据结构和算法最开始接触的一定是排序,但是我问一下计算机系的学弟(大二)他们有时候完全说不清楚,都有哪些排序,甚至数据结构都没有办法说清楚;但是最让人痛苦的是一些,知道,但是写不出代码苦逼孩子。
希望这篇文章可以给哪些知道,但是写不出代码孩子一些思考,我始终认为,真正的教育和思考,是要起于灵魂深处共鸣,只有灵魂深处共鸣,才可以触及灵魂的思考。
只有这样你们才能够在笔试的时候,手写排序(其他另外篇章再说)

02-三种排序:

第一次看的时候,请不要死扣代码,特别是初学小白!!!

1,三种排序共同逻辑

我们先抓住所有线头,三种排序算法共同逻辑,这样你们看后面代码,就会好很多了。

(1)三种排序都是O(n^2)算法

(a)首先我们要知道一个问题?什么O(n^2)

不做官方解释,我本人粗糙理解,就是在最差的情况下,使用这一类算法{O(n^2)}需要花费长度
n^2次的时间,n在我们排序中数组长度, n ^2则表示你花费的多少次的运算才能把这个数组排好。

(b)那么又来一个问题了?为什么三种排序算法是O(n^2)?

后面附有三种排序的代码,但是看完这一句话你们再跳下去看,
因为他们都是采取双重循环,遍历来进行排序,
也就说里面最复杂的情况下,其中一个语句他执行了两个循环。
所以,三种排序算法都是O(n^2)复杂度。
这个时候你们可以到后面去看我的一个代码,只需要去看,
在短短几行代码之间,他们都是被两种循环。

(c)好了,再挖深一点,他为什么要两重循环?(重点)

第一重循环,是为了将整个数组都排好,
第二重循环,是为了将某个数组位置下的数字排到正确的位置。

冒号排序:

冒号排序可以说是最经典的算法了,

基本思想:

是前后两个数两两交换。

代码:

public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 如果左边的数大于右边的数,则交换,保证右边的数字最大
                    Swap.swap(arr, j, j + 1);
                }
            }
        }
    }

//简单的交换代码
public  class Swap {
    public static void swap(int[] arr,int i,int j)
    {
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
}

选择排序:

在诞生冒号排序之后,人们觉得,每一次都跑一遍交换,这样是不是太浪费时间了?
能不能有选择性,交换或者不交换呢?
所以由此诞生了选择排序:

基本思想:

双重循环遍历数组,每经过一轮比较,找到最小元素的下标,将其交换至首位。

代码:

 public static void SelectSort(int[] arr)
    {
        int minIndex;
        for (int i = 0; i < arr.length - 1; i++) {
            minIndex = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    // 记录最小值的下标
                    minIndex = j;
                }
            }
            // 将最小元素交换至首位
            int temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }

插入排序

但是选择排序又会出现一个问题,那就是他不稳定,关于排序算法的稳定性,请看这篇文章:
八大排序算法稳定性分析,原来稳定性是这个意思…
简而言之,那就是有一个数组,[2,8,6,7,8,9],我们看到有两个数字8,前面的8叫做A8,后面8叫做B8。
如果排好序之后是[2,6,7,A8,B8,9]那么这个排序就是稳定的,如果是:[2,6,7,B8,A8,9]那么这个算法就是不稳定。
算法的稳定性,对于纯粹的数字,是没有意义的,但是当你数字背后携带其他关联的时候,才会出现意义。
比如说,按分数选择座位,那么如果两个人分数都相同,想要选一个同一个位置,谁先选?
这个时候,就要参考其他了,比如说上一次考试的分数,本次考试分数相同,则上次考试分数高的先选。
这个时候就体现出算法稳定性重要性。
好了,现在我们已经知道了上面一种选择排序的缺陷了,那么有没有一种及稳定,又不需要想冒号排序那样两两交互浪费时间的算法呢?
于是出现了插入排序。

基本思想:

在新数字插入过程中,不断与前面的数字交换,直到找到自己合适的位置。

代码:

public static void insertSort2(int[] arr) {
        //从第二个数字开始插入:
        for (int i = 1; i < arr.length; i++) {
            //记录当前数组下标
            for (int curr=i;curr>0;curr--)
            {
                if (arr[curr]<arr[curr-1])
                {
                    Swap.swap(arr,curr,curr-1);
                }
            }
        }
    }
//简单的交换代码
public  class Swap {
    public static void swap(int[] arr,int i,int j)
    {
        int temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值