zoukankan      html  css  js  c++  java
  • 数组的几种排序方式

      由于面试几次均遇到过数组排序,自己只擅长选择排序,所以写篇博客对排序做一个总结,加深记忆和理解(排序的复杂度涉及到算法等问题,本人菜鸟就不深入了,等掌握一些算法知识后,再回头把这些知识点补上)。主要总结三种方式:(1)冒泡排序(2)选择排序(3)快速排序

    (一)冒泡排序:

          原理:是相邻的两个数进行比较,符合条件的进行交换位置;

          举例解析:比如数组  int[] arr = {22,36,18,43,14,19,6};

          我们升序来排第一遍:最大数第一遍排完会放在最后一位

          arr[0]与arr[1]比较之后的顺序:{22,36,18,43,14,19,6}(22<36,不交换)

          arr[1]与arr[2]比较之后的顺序:{22,18,36,43,14,19,6}(18<36,交换)

          arr[2]与arr[3]比较之后的顺序:{22,18,36,43,14,19,6}(36<43,不交换)

          arr[3]与arr[4]比较之后的顺序:{22,18,36,14,43,19,6}(14<43,交换)

          arr[4]与arr[5]比较之后的顺序:{22,18,36,14,19,43,6}(19<43,交换)

          arr[5]与arr[6]比较之后的顺序:{22,18,36,14,19,6,43}(6<43,交换)

         第一遍排完43是最大数,放在了最后,这就像水泡往上升一样,慢慢升到了水平面上;第一遍比较了6次,数组长度为7;接着{22,18,36,14,19,6,43}进行第二遍遍历比较:

         arr[0]与arr[1]比较之后的顺序:{18,22,36,14,19,6,43}(18<22,交换)

           arr[1]与arr[2]比较之后的顺序:{18,22,36,14,19,6,43}(22<36,不交换)

         arr[2]与arr[3]比较之后的顺序:{18,22,14,36,19,6,43}(14<36,不交换)

         arr[3]与arr[4]比较之后的顺序:{18,22,14,19,36,6,43}(19<36,交换)

         arr[4]与arr[5]比较之后的顺序:{18,22,14,19,6,36,43}(6<36,交换)

          第二遍走完,36排到了正确的位置,比较了5次(下面交不交换就不写了),接着{18,22,14,19,6,36,43}进行第三遍比较:

           arr[0]与arr[1]比较之后的顺序:{18,22,14,19,6,36,43}

           arr[1]与arr[2]比较之后的顺序:{18,14,22,19,6,36,43}

         arr[2]与arr[3]比较之后的顺序:{18,14,19,22,6,36,43}

         arr[3]与arr[4]比较之后的顺序:{18,14,19,6,22,36,43}

          第三遍走完,22排到了正确的位置,比较了4次,接着{18,14,19,6,22,36,43}进行第四遍比较:

          arr[0]与arr[1]比较之后的顺序:{14,18,19,6,22,36,43}

          arr[1]与arr[2]比较之后的顺序:{14,18,19,6,22,36,43}

          arr[2]与arr[3]比较之后的顺序:{14,18,6,19,22,36,43}

          第四遍走完,19排到了正确的位置,比较了3次,接着{14,18,6,19,22,36,43}进行第五遍比较:

          arr[0]与arr[1]比较之后的顺序:{14,18,6,19,22,36,43}

            arr[1]与arr[2]比较之后的顺序:{14,6,18,19,22,36,43}

          第五遍走完,18排到了正确的位置,比较了2次,接着{14,6,18,19,22,36,43}进行第六遍比较:

          arr[0]与arr[1]比较之后的顺序:{6,14,18,19,22,36,43}

                 第六遍终于排完了(汗!!!(⊙﹏⊙))。数组长度为7,排了6遍,第一遍比较6次,第二遍5次....第六遍1次;下面看代码:

     1 public class ArraySortDemo {
     2     
     3     public static void main(String[] args) {
     4         
     5         int[] arr = {22,36,18,43,14,19,6};
     6         MaoPaoSort(arr);
     7         printArray(arr);
     8         
     9     }
    10     
    11     //冒泡排序的方法
    12     public static void MaoPaoSort(int[] arr){
    13         //排了六遍,所以外层循环六次
    14         for(int i=0;i<arr.length-1;i++){
    15             //内层循环,每次比较的次数都在递减,所以可以得出如下的条件
    16             for (int j = 0; j < arr.length-1-i; j++) {
    17                 if(arr[j]>arr[j+1]){
    18                     int temp = arr[j];
    19                     arr[j] = arr[j+1];
    20                     arr[j+1] = temp;
    21                 }
    22             }
    23         }
    24     }
    25     
    26     //打印数组的方法
    27     public static void printArray(int[] arr){
    28         System.out.print("[");
    29         for (int i = 0; i < arr.length; i++) {
    30             if(i<arr.length-1) 
    31                 System.out.print(arr[i]+",");
    32             else
    33                 System.out.print(arr[i]+"]");
    34         }
    35     }
    36     
    37 }
    View Code

         结果如下:

    (二)选择排序:原理是arr[0],与余下的所有数比较,符合条件的进行交换,这样,第一遍就把最小(或最大)的数固定在了第一个位置;然后第二遍是从arr[1],与arr[2],arr[3].....进行比较,然后把第二小的(或次大的)数固定在第二个位置了;然后第三遍,第四遍....依次这样排下去;

      举例解析:比如数组  int[] arr = {22,36,18,43,14,19,6};

      第1遍:arr[0]与arr[1]比较之后顺序:{22,36,18,43,14,19,6};

          arr[0]与arr[2]比较之后顺序:{18,36,22,43,14,19,6};

          arr[0]与arr[3]比较之后顺序:{18,36,22,43,14,19,6};

            arr[0]与arr[4]比较之后顺序:{14,36,22,43,18,19,6};

          arr[0]与arr[5]比较之后顺序:{14,36,22,43,18,19,6};

          arr[0]与arr[6]比较之后顺序:{6,36,22,43,18,19,14};

      第1遍结束,比较6次,6到了第一位,接着{6,36,22,43,18,19,14}从arr[1]开始比较第1遍:

          arr[1]与arr[2]比较之后顺序:{6,22,36,43,18,19,14};

          arr[1]与arr[3]比较之后顺序:{6,22,36,43,18,19,14};

          arr[1]与arr[4]比较之后顺序:{6,18,36,43,22,19,14};

          arr[1]与arr[5]比较之后顺序:{6,18,36,43,22,19,14};

          arr[1]与arr[6]比较之后顺序:{6,14,36,43,22,19,18};

      第2遍结束,比较5次,14到了第2位,接着{6,14,36,43,22,19,18}从arr[2]开始比较第3遍:

                 arr[2]与arr[3]比较之后顺序:{6,14,36,43,22,19,18};

          arr[2]与arr[4]比较之后顺序:{6,14,22,43,36,19,18};

          arr[2]与arr[5]比较之后顺序:{6,14,19,43,36,22,18};

          arr[2]与arr[6]比较之后顺序:{6,14,18,43,36,22,19};

      第3遍结束,比较4次,18到了第3位,接着{6,14,18,43,36,22,19}从arr[3]开始比较第4遍:

          arr[3]与arr[4]比较之后顺序:{6,14,18,36,43,22,19};

          arr[3]与arr[5]比较之后顺序:{6,14,18,22,43,36,19};

          arr[3]与arr[6]比较之后顺序:{6,14,18,19,43,36,22};

      第4遍结束,比较3次,19到了第4位,接着{6,14,18,19,43,36,22}从arr[4]开始比较第5遍:

          arr[4]与arr[5]比较之后顺序:{6,14,18,19,36,43,22};

          arr[4]与arr[6]比较之后顺序:{6,14,18,19,22,43,36};

      第5遍结束,比较2次,22到了第5位,接着{6,14,18,19,22,43,36}从arr[5]开始比较第6遍:

          arr[5]与arr[6]比较之后顺序:{6,14,18,19,22,36,43}

      第6遍结束,总共比排序排了6遍,第一遍比较6次,第二遍5次....第六遍1次,每一遍的比较次数,依次比上一遍少一次,代码方法如下

     1 //选择排序的方法
     2     public static void selectSort(int[] arr){
     3         //外层循环依旧是排六次
     4         for (int i = 0; i < arr.length-1; i++) {
     5             //内层循环,每次开始的角标在增加,注意i+1,后i=6,i+1等于7,角标会越界,所以外层i < arr.length-1
     6             for (int j = i+1; j < arr.length; j++) {
     7                 if(arr[i]>arr[j]){
     8                     int temp = arr[i];
     9                     arr[i] = arr[j];
    10                     arr[j] = temp;
    11                 }
    12             }
    13         }
    14     }
    View Code

     (三)快速排序:这个理解的不是很透彻,思路是,要定一个中间值,第一遍排序,要将这个数组分成左右两部分,左半部分全部小于这个中间值,右半部分全部大于这个中间值,

        举例解析:比如数组  int[] arr = {22,36,18,43,14,19,6},这个数组以第一个22为中间值,那么左半部分就是6,14,18,19(当然顺序不是这样排好的,顺序依旧是散乱的),右半部分应该是36,43,这样第一遍分了两部分之后,再分别对这两部分递归调用该函数;

        第一遍排序:

              从左往右比较:arr[0]=22与arr[6]=6比较,arr[0]>arr[6],交换{6,36,18,43,14,19,22},接着进行,

              从右往左比较:arr[0]与arr[6]已比较过,所以,arr[6]=22与arr[1]=36比较,arr[6]<arr[1],交换{6,22,18,43,14,19,36},接着进行

              从左往右比较:arr[1]与arr[6]已比较过,所以,arr[1]=22与arr[5]=19比较,arr[1]>arr[5],交换{6,19,18,43,14,22,36},接着进行

              从右往左比较:arr[1]与arr[5]已比较过,所以,arr[5]=22与arr[2]=18比较,arr[5]>arr[2],不交换{6,19,18,43,14,22,36},接着进行

              因为没交换,所以还是从从右往左比较:即还是arr[5]=22与arr[3]=43比较,arr[3]>arr[5],交换{6,19,18,22,14,43,36},接着进行

              从左往右比较:arr[3]与arr[5]已比较过,所以,arr[3]=22与arr[4]=14比较,arr[2]>arr[4],交换{6,19,18,14,22,43,36},接着进行

        第一遍比较结束:这时候数组以22这个中间值就分层了左右两个部分{6,19,18,14} 与{43,36};然后分别对这两部分采用第一遍的方式进行排序,即是递归调用了;显然右半部分来一次就完成了,左半部分进行排序{6,19,18,14},arr[0]=6显然以这个为中间值排完后左半部分没有,右半部分为{19,18,14},然后再以arr[0]=19这个中间值开始排:

                从左往右比较:arr[0]=19与arr[2]=14比较,arr[0]>arr[2],交换{14,18,19},接着进行,

              从右往左比较:arr[2]=19与arr[1]=18比较,显然,不用交换,结果{14,18,19},排序结束;

    整个排序到此就算结束,这样排下来整合就是想要的结果:{6,14,18,19,22,36,43};关键点:定arr[0]为中间值,先从左往右比较,arr[0]与arr[6],交换了(比较之后,arr[0]就不参与比较了,下次比较arr[0]的下一个索引,即arr[1]),就换成从右往左比较了,就依然是拿中间值(这时候arr[6]=中间值了)与左边的刚比较过的下一个索引的值比较(即arr[1]),若是交换了(arr[6]就不参与了,arr[6]的前一个索引值arr[5],参与比较)依次这样进行下去,当碰到索引在中间的时候就算结束了(即是left++>=right--)所以,需要定义左右两个角标;

    终于要上代码了:

     1        //快速排序
     2     public static void quickSort(int[] arr,int start,int end){
     3         //首先判断,start>=end,就不用比较,即所数组里就一个元素的情况
     4         if(start>=end) return;
     5         //定义一个boolen值,确定是从左往右还是从右往左比较
     6         boolean flag = true;
     7         //然后start<end
     8         while(start<end){
     9             //从左往右比较
    10             if(flag){
    11                 if(arr[start]>=arr[end]){
    12                     int temp = arr[start];
    13                     arr[start]=arr[end];
    14                     arr[end] = temp;
    15                     start++;
    16                     flag=false;
    17                 }else{
    18                     //不交换,那么与倒数第二个比较
    19                     end--;
    20                 }
    21             }else{
    22                 //从右往左开始比较
    23                 if(arr[start]>=arr[end]){
    24                     int temp = arr[start];
    25                     arr[start]=arr[end];
    26                     arr[end] = temp;
    27                     end--;
    28                     flag=true;
    29                 }else{
    30                     //不交换,与索引加1
    31                     start++;
    32                 }
    33             }
    34             quickSort(arr,0,start-1);
    35             quickSort(arr,start+1,end);
    36         }
    37     }    
    View Code

    我靠,竟然写出来了,看来慢慢分析还是有用的,代码有可待优化的地方,暂时这样,更好理解,写的有点啰嗦!

              

  • 相关阅读:
    巴洛克式和哥特式的区别
    推荐阅读书籍,是时候再行动起来了。
    AtCoder ABC 159F Knapsack for All Segments
    AtCoder ABC 159E Dividing Chocolate
    AtCoder ABC 158F Removing Robots
    AtCoder ABC 158E Divisible Substring
    AtCoder ABC 157F Yakiniku Optimization Problem
    AtCoder ABC 157E Simple String Queries
    AtCoder ABC 157D Friend Suggestions
    AtCoder ABC 156F Modularness
  • 原文地址:https://www.cnblogs.com/huaxueyihao/p/6521988.html
Copyright © 2011-2022 走看看