• 排序算法入门之快速排序(java实现)


      快速排序也是一种分治的排序算法。快速排序和归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序,会需要一个额外的数组;而快速排序的排序方式是当两个子数组都有序时,整个数组就自然有序了,快速排序可以不产生额外的数组。

    对于小数组(N<=20),快速排序不如插入排序。所以,小数组建议使用其他排序。

      快速排序可以由以下几步组成:

      1.如果数组S中的元素个数是0或1,则返回。

      2.取S中任一元素v,称为枢纽元。

      3.将S中其余元素(除枢纽元)分为两部分,一部分是小于v的,放在v的左边,一部分是大于v的,放在v的右边。

      4.再将左右两部分继续递归快速排序。

    细节:

      1.选取枢纽元

        一种通常的、无知的选择就是选取第一个元素用作枢纽元。如果输入是随机的,那么这也是可以接受的,而如果输入是预排序的或者反序的,这样的分割就毫无意义,因为所有元素都是比第一个元素大或都比它小,这样就只会划分成一部分。此时花费的时间是二次的,而实际上却没有干什么事。

        一般的做法是使用左端、右端和中心位置上的三个元素的中值(中间大小的那个数)作为枢纽元。

      2.分割策略

        在分割阶段要做的就是把小于枢纽元的元素移到数组左边,把大于枢纽元的元素移到数组右边。

         先假设所有元素互异。方法是:将枢纽元与最后一个元素交换位置,使枢纽元离开要被分割的数据段。i 从第一个元素开始,j 从倒数第二个元素开始。当 i 在 j 左边时,将 i 右移,移过那些小于枢纽元的元素(这些元素就该放在数组左边),并将 j 左移,移过那些大于枢纽元的元素。当 i 和 j 停止时,说明此事 i 指向了一个比枢纽元大的元素,j 指向了一个比枢纽元小的元素。如果 i 比 j 小,则交换这两个元素,也就是把i指向的大元素(相对于枢纽元)放到数组右边,j 指向的小元素放到数组左边,然后 i 和 j 继续移动。如果 i 大于 j ,说明已经移动结束,此时i左边都是比枢纽元小的, i 的右边(包括i)都是比枢纽元大的。最后将 i 元素与枢纽元互换。

        如果 i 和 j 遇到了与枢纽元相同的元素,那么也应该停下来。

      代码:

    最好的情况是枢纽元选取得当,每次都能均匀的划分序列, 时间复杂度O(nlogn);最坏情况是枢纽元为最大或者最小数字,那么所有数都划分到一个序列去了 时间复杂度为O(n^2) 

    选取第一个元素为基准

    快速排序是冒泡排序的改进版,也是最好的一种内排序,在很多面试题中都会出现,也是作为程序员必须掌握的一种排序方法。

    思想:1.在待排序的元素任取一个元素作为基准(通常选第一个元素,但最的选择方法是从待排序元素中随机选取一个作为基准),称为基准元素;

           2.将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;

           3.对左右两个分区重复以上步骤直到所有元素都是有序的。

    所以我是把快速排序联想成东拆西补或西拆东补,一边拆一边补,直到所有元素达到有序状态。

    下面再看看示图理解下吧:

                                      

                                      

    6.对元素5两边的元素也重复以上操作,直到元素达到有序状态。

    算法实现:

    复制代码
    public class QuickSort {
    
        public static void quickSort(int arr[],int _left,int _right){
            int left = _left;
            int right = _right;
            int temp = 0;
            if(left <= right){   //待排序的元素至少有两个的情况
                temp = arr[left];  //待排序的第一个元素作为基准元素
                while(left != right){   //从左右两边交替扫描,直到left = right
    while(right > left && arr[right] >= temp) right --; //从右往左扫描,找到第一个比基准元素小的元素 arr[left] = arr[right]; //找到这种元素arr[right]后与arr[left]交换
    while(left < right && arr[left] <= temp) left ++; //从左往右扫描,找到第一个比基准元素大的元素 arr[right] = arr[left]; //找到这种元素arr[left]后,与arr[right]交换
    } arr[right] = temp; //基准元素归位 quickSort(arr,_left,left-1); //对基准元素左边的元素进行递归排序 quickSort(arr, right+1,_right); //对基准元素右边的进行递归排序 } } public static void main(String[] args) { int array[] = {10,5,3,1,7,2,8}; System.out.println("排序之前:"); for(int element : array){ System.out.print(element+" "); } quickSort(array,0,array.length-1);
    System.out.println(" 排序之后:"); for(int element : array){ System.out.print(element+" "); } } }
    复制代码

    本博客参考《数据结构与算法分析java语言描述》、https://www.cnblogs.com/MOBIN/p/4681369.html

  • 相关阅读:
    第7.12节 可共享的Python类变量
    (独孤九剑)--MySQL入门
    (独孤九剑)--错误处理
    PHP图像函数
    (独孤九剑)--图像处理
    (独孤九剑)--文件上传
    (独孤九剑)--文件系统
    (独孤九剑)--正则表达式
    (独孤九剑)--数组与数据结构
    PHP填坑
  • 原文地址:https://www.cnblogs.com/xiaolovewei/p/7573775.html
Copyright © 2020-2023  润新知