Java工程师面试1000题154-冒泡、选择、插入排序

154、冒泡、选择、插入排序

冒泡排序:

冒泡排序重复地走访过要排序的元素列,依次比较两个相邻的元素,如果他们的顺序(如从大到小、首字母从A到Z)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素已经排序完成。这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。

   public static void sort(long[] arr){
        long tmp = 0;
        for (int i=0;i<arr.length-1;i++){
            for (int j=arr.length-1;j>i;j--){
                if (arr[j] < arr[j-1]){
                    //进行交换
                    tmp = arr[j];
                    arr[j] = arr[j-1];
                    arr[j-1] = tmp;
                }
            }
        }
    }

示例:排序前数组为:2 4 8 3 5 1

 第一轮交换:此时i等于0
 2    4   8   3   5   1   ——>   此时j等于5, 比较5和1的大小,5>1,交换位置,此时j等于4;
 2    4   8   3   1   5   ——>   此时j等于4, 比较3和1的大小,3>1,交换位置,此时j等于3;
 2    4   8   1   3   5   ——>   此时j等于3, 比较8和1的大小,8>1,交换位置,此时j等于2;
 2    4   1   8   3   5   ——>   此时j等于2, 比较4和1的大小,4>1,交换位置,此时j等于1;
 2    1   4   8   3   5   ——>   此时j等于1, 比较2和1的大小,2>1,交换位置,此时j等于0;
 1    2   4   8   3   5   ——>   j>i 条件不满足,第一轮交换结束。
———————————————————————————————————————————————————————————————————————————————————————
第二轮交换:此时i等于1
1    2   4   8   3   5   ——>    此时j等于5, 比较3和5的大小,3<5,位置不变,此时j等于4;
1    2   4   8   3   5   ——>    此时j等于4, 比较8和3的大小,8>3,交换位置,此时j等于3;
1    2   4   3   8   5   ——>    此时j等于3, 比较4和3的大小,4>3,交换位置,此时j等于2;
1    2   3   4   8   5   ——>    此时j等于2, 比较2和3的大小,2<3,位置不变,此时j等于1;
1    2   3   4   8   5   ——>    j>i 条件不满足,第二轮交换结束。
———————————————————————————————————————————————————————————————————————————————————————
第三轮交换:此时i等于2
1    2   3   4   8   5   ——>    此时j等于5,比较8和5的大小,8>5,交换位置,此时j等于4;
1    2   3   4   5   8   ——>    此时j等于4,比较4和5的大小,4<5,位置不变,此时j等于3;
1    2   3   4   5   8   ——>    此时j等于3,比较3和4的大小,3<4,位置不变,此时j等于2;
1    2   3   4   5   8   ——>    j>i 条件不满足,第三轮交换结束。
————————————————————————————————————————————————————————————————————————————————————————
第四轮交换:此时i等于3
1    2   3   4   5   8   ——>    此时j等于5,比较5和8的大小,5<8,位置不变,此时j等于4;
1    2   3   4   5   8   ——>    此时j等于4,比较4和5的大小,4<5,位置不变,此时j等于3;
1    2   3   4   5   8   ——>    j>i 条件不满足,第四轮交换结束。
————————————————————————————————————————————————————————————————————————————————————————
第五轮交换:此时i等于4
1    2   3   4   5   8   ——>    此时j等于5,比较5和8的大小,5<8,位置不变,此时j等于4;
1    2   3   4   5   8   ——>    j>i 条件不满足,第四轮交换结束。
————————————————————————————————————————————————————————————————————————————————————————
i再次自增之后,变为5,外层循环跳出,整个排序过程结束。

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。

   public static void selectSort(int[]a) {
        int minIndex = 0;
        int temp = 0;

        for(int i = 0;i < a.length;i++) {
            //无序区的最小数据数组下标
            minIndex = i;
            for(int j = i + 1; j < a.length; j++) {
                //在无序区中找到最小数据并保存其数组下标
                if(a[j] < a[minIndex]) {
                    minIndex=j;
                }
            }
            //将最小元素放到本次循环的前端
            temp = a[i];
            a[i] = a[minIndex];
            a[minIndex] = temp;
        }
    }

示例:排序前数组为:2 4 8 3 5 1

第一轮:i = 0; minIndex = 0  数组:2 4 8 3 5 1
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————
进入内层for循环,从j = 1开始到j = 5结束,依次比较,找出数组中最小元素的下标为minIndex = 5
执行最下面的三句交换语句,交换 a[i] 和 a[minIndex]的值,即交换 a[0]和a[5]的值;
交换之后的数组变为:1  4   8   3   5   2
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————
第二轮:i = 1; minIndex = 1;
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————
进入内层for循环,从j = 2开始到j = 5结束,依次比较,找出数组中最小元素的下标为minIndex = 5
执行最下面的三句交换语句,交换 a[i] 和 a[minIndex]的值,即交换 a[1]和a[5]的值;
交换之后的数组变为:1  2   8   3   5   4
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————
第三轮:i = 2; minIndex = 2;
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————
进入内层for循环,从j = 3开始到j = 5结束,依次比较,找出数组中最小元素的下标为minIndex = 3
执行最下面的三句交换语句,交换 a[i] 和 a[minIndex]的值,即交换 a[2]和a[3]的值;
交换之后的数组变为:1  2   3   8   5   4
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————
第四轮:i = 3; minIndex = 3;
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————
进入内层for循环,从j = 4开始到j = 5结束,依次比较,找出数组中最小元素的下标为minIndex = 5
执行最下面的三句交换语句,交换 a[i] 和 a[minIndex]的值,即交换 a[3]和a[5]的值;
交换之后的数组不变,仍为:1  2   3   4   5   8
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————
第四轮:i = 4; minIndex = 4;
—————————————————————————————————————————————————————————————————————————————————————————————————————————————————
进入内层for循环,从j = 5开始到j = 5结束,a[j] < a[minIndex] 即 a[5] < a[4]不成立。minIndex值不变。
数组不变,仍为:1  2   3   4   5   8

排序结束。

插入排序:

插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。插入排序的基本思想是:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

   public int[] insertionSorting(int[] A) {
        for (int i = 1; i < A.length; i++) {
            for (int j = i; j > 0; j--) {
                if (A[j] < A[j - 1]) {
                    //交换数据
                    int temp = A[j];
                    A[j] = A[j - 1];
                    A[j - 1] = temp;
                } else {
                    //此时插入的数据已经到达正确位置
                    break;
                }
            }
        }
        return A;
    }
  2 4 8 3 5 1
  外层第一轮:i = 1
—————————————————————————————————————————————————————————————————————
  j = 1
  判断 A[j] < A[j - 1] 即A[1] < A[0], 不成立, break, j自减为0
  j = 0 跳出内层循环
—————————————————————————————————————————————————————————————————————
  外层第二轮:i = 2
—————————————————————————————————————————————————————————————————————
  j = 2
  判断 A[j] < A[j - 1] 即A[2] < A[1] ,不成立,break,j自减为 1
  判断 A[j] < A[j - 1] 即A[1] < A[0] ,不成立,break,j自减为 0
  j = 0 跳出内层循环
—————————————————————————————————————————————————————————————————————
  外层第三轮:i = 3
—————————————————————————————————————————————————————————————————————
  j = 3
  判断 A[j] < A[j - 1] 即A[3] < A[2] ,成立,交换A[3] 和 A[2]
  数组变为:2 4 3 8 5 1
  j自减为 2
  判断 A[j] < A[j - 1] 即A[2] < A[1] ,成立,交换A[2] 和 A[1]
  数组变为:2 3 4 8 5 1
  j自减为 1
  判断 A[j] < A[j - 1] 即A[1] < A[0],不成立,break,j自减为 0
  j = 0 跳出内层循环
—————————————————————————————————————————————————————————————————————
  外层第四轮:i = 4
—————————————————————————————————————————————————————————————————————
  j = 4
  判断 A[j] < A[j - 1] 即A[4] < A[3] ,成立,交换A[4] 和 A[3]
  数组变为:2 3 4 5 8 1
  j自减为 3
  判断 A[j] < A[j - 1] 即A[3] < A[2],不成立,break,j自减为2
  判断 A[j] < A[j - 1] 即A[2] < A[1],不成立,break,j自减为1
  判断 A[j] < A[j - 1] 即A[1] < A[0],不成立,break,j自减为0
  j = 0 跳出内层循环
—————————————————————————————————————————————————————————————————————
  外层第五轮:i = 5
—————————————————————————————————————————————————————————————————————
  j = 5
  判断 A[j] < A[j - 1] 即A[5] < A[4] ,成立,交换A[5] 和 A[4]
  数组变为:2 3 4 5 1 8
  j自减为 4
  判断 A[j] < A[j - 1] 即A[4] < A[3] ,成立,交换A[4] 和 A[3]
  数组变为:2 3 4 1 5 8
  j自减为 3
  判断 A[j] < A[j - 1] 即A[3] < A[2] ,成立,交换A[3] 和 A[2]
  数组变为:2 3 1 4 5 8
  j自减为 2
  判断 A[j] < A[j - 1] 即A[2] < A[1] ,成立,交换A[2] 和 A[1]
  数组变为:2 1 3 4 5 8
  j自减为 1
  判断 A[j] < A[j - 1] 即A[1] < A[0] ,成立,交换A[1] 和 A[0]
  数组变为:1 2 3 4 5 8
  j自减为 0
  j = 0 跳出内层循环
—————————————————————————————————————————————————————————————————————
  i加1之后为6,跳出外层循环,排序结束。

返回数组:1 2 3 4 5 8

猜你喜欢

转载自blog.csdn.net/qq_21583077/article/details/88847171