zoukankan      html  css  js  c++  java
  • 学习笔记——快速排序

    排序基本概念

    什么是排序

      排序(sorting)的功能是将一个数据元素的任意序列,重写排列成一个按关键字有序的序列。

    内部排序和外部排序

      一类是整个排序过程在内存储器中进行,成为内部排序

      另一类是由于待排序元素数量太大,以至于内存储器无法容纳全部数据,排序需要借助外部存储设备才能完成,这类排序成为外部排序。

    稳定排序和就地排序

      稳定排序:假设在待排序的文件中,存在两个或两个以上的记录具有相同的关键字,在用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序方法是稳定的。

           其中冒泡,插入,基数,归并属于稳定排序,选择,快速,希尔,归属于不稳定排序。

      就地排序:若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间为O(1),则称为就地排序。

    比较排序和非比较排序

      大部分排序都是需要通过比较首先来判断大小,作为排序的依据的。

      但是也有例外的,比如计数排序、基数排序,不需要进行比较。

     排序类型

     

    排序效率

      时间复杂度最高的就是三种基本排序:直接插入、简单选择、冒泡排序。

    快速排序

       冒泡排序的改进版,也是最好的一种内排序,还涉及到分治和递归。

       是由C. A. R. Hoare在1962年提出的一种划分交换排序,它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。

       它的基本思想是:

        通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,

        然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

     

    一趟快速排序的算法是:

    1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;

    2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];

    3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将值为key的项与A[j]交换;

    4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将值为key的项与A[i]交换;

    5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[j]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

        public static void quickSort(int[] arr) {
            int low = 0;
            int high = arr.length-1;
            quickSort(arr,low,high);
        }
        
        private static void quickSort(int[] arr,int low, int high) {
            if(low < high) {
                // 分区操作,将一个数组分成两个分区,返回分区界限索引
                int index = partition(arr,low,high);
                // 对左分区进行快排
                quickSort(arr,low,index-1);
                // 对右分区进行快排
                quickSort(arr,index+1,high);
            }
        }
        
        private static int partition(int[] arr,int low,int high) {
            // 指定左指针i和右指针j
            int i = low;
            int j = high;
            // 将第一个数作为基准值
            int x = arr[low];
            // 使用循环实现分区操作
            while(i < j) {
                // 1.从右向左移动j,找到第一个小于基准值的值 
                while(arr[j] >= x && i < j) {
                    j--;
                }
                // 2.将右侧找到小于基准数的值加入到左边的位置,左指针向中间移动一个位置i++
                if( i < j) {
                    arr[i] = arr[j];
                    i++;
                }
                // 3.从左向右移动i,找到第一个大于等于基准值的值 arr[i]
                while(arr[i] < x && i < j) {
                    i ++;
                } 
                // 4.将左侧找到的大于等于基准的值加入到右边,右指针向中间移动一个位置 j--
                if(i < j) {
                    arr[j] = arr[i];
                    j --;
                }
            }
            // 使用基准值,这就是基准值的最终位置
            arr[i] = x;
            // 返回基准值的位置索引
            return i;
        }



    作者:殇央 © 转载请注明出处。

    -------------------------------------------

    如果有错误或者更优化的解决方案,欢迎大家在评论区留言探讨。

    也可以给我的个人公众号私信留言。

    如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!

查看全文
  • 相关阅读:
    课堂作业04 2017.10.27
    课程作业 03 动手动脑 2017.10.20
    课程作业 03 2017.10.20
    HDU 3974 Assign the task
    POJ 2155 Matrix
    POJ 2481 Cows
    HDU 3038 How Many Answers Are Wrong
    CS Academy Array Removal
    POJ_1330 Nearest Common Ancestors LCA
    CF Round 427 D. Palindromic characteristics
  • 原文地址:https://www.cnblogs.com/shangyang/p/10544171.html
  • Copyright © 2011-2022 走看看