算法 简单来说就是用有限步骤解决问题的方法,而描述解决问题的步骤,可以用各类计算机语言,java,c,python等,甚至用流程图或者数学符号等抽象的语言,只要可以在有限个步骤能完成即可

排序算法不会以问题直接出现,而是会在算法题目中用到,甚至不会连算法都不会出现,只是出现排序算法的思想,比如求某n长数列第k大的数,虽然直观感觉很简单,但是如果只是对数列进行冒泡排序,再取第k大的数,其时间复杂度可能会无法接受,就这个问题来说,刚才提到的算法是不好的,因为其实我们只是求第k大,k以后的排序其实是浪费的

算法问题更多的会以上面的形式出现,所以需要我们学会几个排序算法的思想,然后根据不同的问题去选择,下面提到的排序规则都是按照从小到大,这对算法本身正误是没有影响的,这样做只是为了说明方便节省时间

回忆下冒泡排序,直接给出数列

    23   23   23   23

       90   9     9     9

       9     90   25   25

       25   25   90   16

       16   16   16   90   通过第一轮冒泡 最大的元素90到达了末尾

    9     9     9

       23   23   23

       25   25   16

       16   16   25          通过第二轮冒泡 25到达了末尾

       90   90   90

    9     9

       23   16

       16   23                 通过第三轮冒泡 23到达了末尾

       25   25

       90   90

    9                          完成排序

       16

       23

       25

       90

对于n长的数组我们需要(n*n-1)/2次比较 时间复杂度为O(n^2)

再给出快速排序示例

6 1 2 7 9 3 4 5 10 8

                ⇩

6 1 2 7 9 3 4 5 10 8

                   ⇩

6 1 2 7 9 3 4 5 10 8

           ⇩

6 1 2 7 9 3 4 5 10 8

  ⇩

5 1 2 7 9 3 4 6 10 8

 

   ⇩

5 1 2 7 9 3 4 6 10 8

     ⇩

5 1 2 7 9 3 4 6 10 8

          ⇩

5 1 2 6 9 3 4 7 10 8

          ⇩

5 1 2 4 9 3 6 7 10 8

              ⇩

5 1 2 4 6 3 9 7 10 8

             

5 1 2 4 3 6 9 7 10 8      比较了10次 而6左边的数都小于6 6右边的数都大于6

然后数组分成了两部分 6左边 6右边即

5 1 2 4 3和 9 7 10 8

我们对这两个数组分别进行快速排序,这里就是用的递归的思想,只给出左边的后续步骤

5 1 2 4 3

       ⇩

5 1 2 4 3

3 1 2 4 5

  ⇩

3 1 2 4 5

   ⇩

3 1 2 4 5

     ⇩

3 1 2 4 5

 

3 1 2 4 5

 

新数组变成5左边 3124 右边没有

3 1 2 4

     ⇩

3 1 2 4

   ⇩

3 1 2 4

  ⇩

2 1 3 4

 

2 1 3 4

新数组变成 3左边 21 右边4

 

4

2 1

  ⇩

1 2

新数组变成2左边1 右边没有

1

回到第一次的递归

 

就是123456 9 7 10 8

9 7 10 8留做作业,做为思考

 

直观感觉每进行一次快速排序,数组都被分为两部分,而下一次排序只会遍历被拆分的部分,所以直观来看,确实比冒泡排序要更加有效,考虑一般情况,每次等分两部分,则时间复杂度为o(n log(n))而最极端的情况 即完全倒序,快速排序退化为冒泡排序 时间复杂度为o(n^2)

 

给出java的快速排序的实现,给出关键代码

class Solution{

       static void quicksort(int[] arr,int i,int j) {

              int a=i;

              int b=j;

              if(a==b) {

                     return;

              }

              int temp=arr[a];

              while(a!=b) {

                     while(temp<arr[b]&&a<b) {

                            b--;

                     }

                     if(a==b) {

                            break;

                     }

                     arr[a]=arr[b];

                     a++;

                     while(arr[a]<temp&&a<b) {

                            a++;

                     }

                     if(a==b) {

                            break;

                     }

                     arr[b]=arr[a];

              }

              arr[a]=temp;

              if(a>i) {

                     quicksort(arr,i,a-1);

              }

              if(a<j) {

                     quicksort(arr,a+1,j);     

              }

       }

}

编写主函数使用测试数据数组测试上述代码,留做作业

刚才提到的求n长数组第k大元素,可以用快速排序的思想,进行一次快速排序,判断如果k>a,对(i,a-1)进行递归,如果k<a,对(a+1)进行递归,具体实现留做作业