冒泡排序和选择排序

135 阅读7分钟

冒泡排序

一个数组里面的元素,拿最左边的和它右边的元素比较,如果左边的大,则交换位置,如果右边的大,则不交换;再拿第二个元素和第三个元素比较,如果第二个大,则交换位置,如果第三个大,则不交换;直到最后一个.

举例来说,数组 int[] arr = {6,1,2,8,0,7}; (0,1,2,3,4,5)

第一次循环:

参与比较的数据:6 1 2 8 0 7(6和1比较,6和1交换位置)

第一次比较的结果:1 6 2 8 0 7(6和2比较,6>2,6和2交换位置)

第二次比较的结果:1 2 6 8 0 7(6和8比较,6<8,不交换位置)

第三次比较的结果:1 2 6 8 0 7(8和0比较,8>0,8和0交换位置)

第四次比较的结果:1 2 6 0 8 7(8和7比较,8>7,8和7交换位置)

第五次比较的结果:1 2 6 0 7 8

第二次循环:

参与比较的数据:1 2 6 0 7(1和2比较,1<2,不交换位置)

第一次比较的结果:1 2 6 0 7(2和6比较,2<6,不交换位置)

第二次比较的结果:1 2 0 6 7(6和0比较,6>0,6和0交换位置)

第三次比较的结果:1 2 0 6 7(6和7比较,6<7,不交换位置)

第四次比较的结果:1 2 0 6 7

第三次循环:

参与比较的数据:1 2 0 6(1和2比较,1<2,不交换位置)

第一次比较的结果:1 2 0 6(2和0比较,2>0,2和0交换位置)

第二次比较的结果:1 0 2 6(2和6比较,2<6,不交换位置)

第三次比较的结果:1 0 2 6

第四次循环:

参与比较的数据:1 0 2(1和0比较,1>0,1和0交换位置)

第一次比较的结果:0 1 2(1和2比较,1<2,不交换位置)

第二次比较的结果:0 1 2

第五次循环:

参与比较的数据:0 1(0和1比较,0<1,不交换)

第一次比较的结果:0 1

if(arr[i] > arr[i+1]){
    int temp = arr[i];
    arr[i] = arr[i+1];
    arr[i+1] = temp;
}

6个数据,外循环是5次,内循环分别是5,4,3,2,1次.

arr长度为6,i从0开始,0,1,2,3,4,共5次外循环.

倒过来想,for循环中,外循环按i--;的方式来,从5到1,也是5次,而内循环j当i=5时从0到4(5次),当i=4时从0到3(4次),当i=1时j=0(1次),也就是:

for(int i = 5; i > 0; i--){//这个5其实是arr.length - 1
    for(int j = 0; j < i; j++){
        if(arr[j] > arr[j+1]){
        int temp = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = temp;
}
    }
}

这种排序方法,比较次数是15次,交换位置次数是7次.

选择排序

每一次从数组中这堆参与比较的数据中找出最小值,拿着这个最小值与最前面的数据交换位置.

举例来说,数组 int[] arr = {6,1,2,8,0,7}; (0,1,2,3,4,5)

参与比较的数据:6 1 2 8 0 7(最小值是0,6和0交换位置)

第一次循环:比较之后的结果:(0) 1 2 8 6 7(0不管了,因为它最小,后面的最小值是1,不交换位置)

第二次循环:比较之后的结果:(0 1) 2 8 6 7(0,1不管了,因为它最小,后面的最小值是2,不交换位置)

第三次循环:比较之后的结果:(0 1 2) 8 6 7(0,1,2不管了,因为它最小,后面的最小值是6,8和6交换位置)

第四次循环:比较之后的结果:(0 1 2 6) 8 7(0,1,2,6不管了,因为它最小,后面的最小值是7,8和7交换位置)

第五次循环:比较之后的结果:(0 1 2 6 7) 8

6个数据,外循环5次,内循环分别是5,4,3,2,1次.

假设arr[0]是最小的,当i=0时,arr[0]和arr[1]比较,6>1,arr[0]并不是最小的,把最小值赋给arr[1],arr[1]再和arr[2]比较,1<2,arr[1]还是最小的,arr[1]和arr[3]比较,1<8,arr[1]还是最小的,arr[1]和arr[4]比较,1>0,arr[1]并不是最小的,把最小值赋给arr[4],arr[4]和arr[5]比较,0<7,所以最小值是arr[4].然后把arr[4]和arr[0]交换位置.第一次循环结束.此时arr[0]的位置是当前的最小值.即(0) 1 2 8 6 7.(0)不再参与比较.

当i=1时,此时的假设最小值是arr[1],arr[1]和arr[2]比较,1<2,arr[1]还是最小的,arr[1]和arr[3]比较,1<8,arr[1]还是最小的,arr[1]和arr[4]比较,1<6,arr[1]还是最小的,arr[1]和arr[5]比较,1<7,arr[1]还是最小的,最小值不变,不需要交换位置.第二次循环结束.此时arr[1]的位置是当前的最小值.即(0 1) 2 8 6 7.(0 1)不再参与比较.

当i=2时,此时的假设最小值是arr[2],arr[2]和arr[3]比较,2<8,arr[2]还是最小的,arr[2]和arr[4]比较,2<6,arr[2]还是最小的,arr[2]和arr[5]比较,2<7,arr[2]还是最小的,最小值不变,不需要交换位置.第三次循环结束.此时arr[2]的位置是当前的最小值.即(0 1 2) 8 6 7.(0 1 2)不再参与比较.

当i=3时,此时的假设最小值是arr[3],arr[3]和arr[4]比较,8>6,arr[3]不是最小的,把最小值赋给arr[4],arr[4]和arr[5]比较,6<7,arr[4]还是最小的,arr[4]和arr[3]交换位置.第四次循环结束.此时arr[3]的位置是当前的最小值.即(0 1 2 6) 8 7.(0 1 2)不再参与比较.

当i=4时,此时的假设最小值是arr[4],arr[4]和arr[5]比较,8>7,arr[4]不是最小的,把最小值赋给arr[5],arr[4]和arr[5]交换位置.第五次循环结束.此时arr[4]的位置是当前的最小值.即(0 1 2 6 7) 8.退出循环.

以上可以看到,当外循环为i时,将i的值赋给最小值min的下标,然后让arr[min]和arr[i+1]比较,如果arr[i+1]<arr[min],则将i+1的值赋给最小值的下标,当一轮循环结束后,如果min没有变,说明最小值就是arr[i],如果变了,则要把arr[i+1]与arr[min]交换位置.

当i的值不变时(比如为0),则只能比较arr[0]和arr[1],无法从arr[0]循环到arr[5],而当i=1时,循环则从arr[1]到arr[5]..当i=4时,循环从arr[4]到arr[5].

内循环需要一个变量j=i+1;j<arr.length;j++

for(int i = 0; i < arr.length - 1; i++){
    int min = i;
    for(int j = i + 1; j < arr.length; j++){
        if(arr[j] < arr[min]){
            min = j;
        }
    }
    if(min != i){
        int temp;
        temp = arr[min];
        arr[min] = arr[i];
        arr[i] = temp;
    }
}

交换位置不太好理解,可以想象是两只手拿着东西,左手拿着6(arr[i]),假设的最小值,右手拿着取到的最小值0(arr[min]),现在int temp,就像一个桌子,先把取到的最小值(右手的东西arr[min])放到桌子上(temp),现在右手空了,再把左手拿的假设的最小值6(arr[i])放到右手(arr[min]),现在左手空了,再把桌子上(temp)的东西(也就是最小值arr[min])放到左手(arr[i]),这样就实现了交换位置.