算法讲解004 选择、冒泡、插入排序

一句话总结:

选择排序一句话:[i]~[n-1]范围上,找到最小值并放在i位置,然后[i+1]~[n-1]范围上继续

冒泡排序一句话:[0]~[i]范围上,相邻位置较大的数滚下去,最大值最终来到i位置,然后0~i-1范围上继续
插入排序一句话:[0]~[i]范围上已经有序,新来的数从右到左滑到不再小的位置插入,然后继续

Code:

选择排序

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置(如假定无序的序列中第一个是最小的;

然后扫描后面的数字,发现更小的就交换;

//数组中交换i和j位置的数
public static void swap(int[] arr, int i, int j){
    int temp = arr[i];
    arr[i]   = arr[j];
    arr[j]   = temp;
}

//选择排序
public static void selectionSort(int[] arr){
    if (arr == null || arr.length < 2){
       return;
    }

    int i,j,minIndex;
    for (i=0; i < arr.length; i++) {
         minIndex = i;
         for (j=i+1; j<arr.length; j++){
             if (arr[j] < arr[minIndex]){
                 minIndex = j;
             }
         }
         swap(arr, i, minIndex);
    }
/**
i 控制的是已排序序列的边界,随着 i 的增加,已排序序列逐渐增长。
j 用于在未排序的序列中查找最小元素的索引。
minIndex 用于记录当前找到的最小元素的索引。
   这段代码通过不断地从未排序的序列中找到最小元素,并将其与已排序序列的末尾元素交换 
   位置,从而逐步将整个数组排序。

冒泡排序

每一轮比较都能固定确定一个最大数,谁大谁往右,固定在最后:最大的数往右冒

一轮最大的比完之后跳出内层循环,到外层循环>  end-- > 右移 比第二轮找次大的......

插入排序:像摸牌后插入手中牌

首先0~0范围上我想让它有序,那你0~0范围上只有5,他已经做到有序了,对不对?

接下来我想0~1范围上做到有序,那 i 来到[1]位置的3。他就往前交换。这个3比它左边的数字要小,它就一直往左换,那5是不是比我左边的小?是交换,所以3和5交换,所以3就来到了零位置,5就被换到右边去了。然后你再看这个3,它左边已经没数了,他左边已经没数了,你就可以停了对吧?那此时你0~1范围上有没有做到有序啊?当然做到有序了

3   5    4   1   2

           i

[0] [1] [2] [3] [4]

好,然后在0~2范围上,我继续这么干。现在 i 来到[2]位置的4,那么这个[2]位置的新来的数字4,我往左边看,arr[2]<arr[1] 所以,4跟5交换,4跟5交换之后,5就来到2的位置,4就来到1的位置。

这时 3 4 5 1 2

4再往左看,4再往左看,它有没有比3小呢?不小了对吧?不小就停啊,不小就停后面的事不干了。好,那么345是不是有序了?那0~2范围上做到有序了对不对?

好,我们继续现在来到新来的数是什么呢?是[3]位置的1,我就看我往左看,我小交换

3   4    1   5   2

[0] [1] [2] [3] [4]

3   1    4   5   2

[0] [1] [2] [3] [4]

1   3    4   5   2

[0] [1] [2] [3] [4]

1就来到2位置,5就被换到了3位置,对吧,然后一再往左看,我比四小交换。一就来到了一位置,4就来到了2位置,对吧,然后一再往左看,我比3要小交换。好一再往左看,没数了,停对吧?停的条件两个:

1)arr[i] > arr[i-1]

2)  [i] 到了最左边

好,那么0~2范围上也做到此时,0~3范围上就做到有序了对吧?到最后我想在0~4做到有序,那你现在新来的数字就是2嘛,我往左边看要交换------2跟5交换。我再往左边看,2和4交换。我再往左边看,2和3交换。我再往左边看,我不再小,比他小了,停好,那你整个范围上都做到有序,

1   2    3   5

[0] [1] [2] [3] [4]

就有点像我们手里面已经抓了若干张牌,对吧?手里面已经到了若干张牌,已经给他整成有序的。此时,你新摸了一张牌,那么你怎么把它插进去?你就从右滑到,该来到的位置插进去就行了。就这个过程啊,就跟打牌一样啊。

 // i 是待比较的牌
for (i = 1, i < arr.length, i++){
 // j 是已排队列中被和i比的在i之前的其他牌
     for (int j = i - 1; j>=0 && arr[j] > arr[j+1]; j--){
         swap(arr, j ,j+1)
     }
}

5 1 4 3 2 

0 1 2 3 4

(1)i = 1 进入内层循环

 arr[0] > arr[1] 交换

1 5  4 3 2 

0 1 2 3 4

j   i

j-- =-1 跳出内层循环到外层

(2) i=2 进入内层

14 3 2 

0 1 2 3 4

      i

   j  j+1

arr[1] > arr[2] 交换

1    4    5 3 2 

0    1    2 3 4

            i

j    j+1  

arr[0] < arr[1] 退出循环

·······

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值