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;
        }



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

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

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

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

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

查看全文
  • 相关阅读:
    总结一下最近用过的phpcms语法
    phpcms和php格式化时间戳
    为什么使用bootstrap在一个页面同时做两个轮播效果时,只有第一个有效??
    Jquery右击显示菜单事件,运用smartMenu插件。
    流程管理
    权限管理
    文件管理的练习(目录文件的打开,双击返回上一层目录、双击打开子目录文件)
    php部分--文件操作
    php部分--头像上传预览
    PHP部分--图片上传服务器、图片路径存入数据库,并读取
  • 原文地址:https://www.cnblogs.com/shangyang/p/10544171.html
  • Copyright © 2011-2022 走看看