• 快速排序


    快速排序的平均时间复杂度是O(nlogn),最坏情况下为O(n^2)。

    法一:

     原始数据如上,并且设置两个指针,以及一个基准pivot = 4(这里采用首元素为基准,基准可以是随机一个元素)。

            在第一次循环中,从right指针开始,让指针指向的元素与基准元素比较,指针指向元素大于等于基准元素时,指针向左移动一位;否则,指针right停止移动,切换到left指针。left指针指向的元素如果小于等于基准元素,指针向右移动,否则指针停止移动,让left指针指向的元素与right指针指向的元素进行交换当left与right指向同一个位置时,将该与元素与基准元素交换位置

           在上面数列中1<4,所以right指针停止移动,切换到left指针,然后进行下一步比较,4=4,所以left指针向右移动,7>4,所以将left指针停止移动,并且将left和right指针指向的元素交换。接下来继续进行下一轮的循环。流程大致如下:

     代码实现如下:

    public static void quickSort(int[] arr,int left,int right){
            int i,j,pivot;
            //递归结束条件
            if(left>=right){
                return;
            }
            i=left;  //左指针
            j=right;  //右指针
            //pivot就是基准位
            pivot = arr[left];
            while (i<j) {
                //先看右边,依次往左递减
                while (pivot<=arr[j]&&i<j) {
                    j--;
                }
                //再看左边,依次往右递增
                while (pivot>=arr[i]&&i<j) {
                    i++;
                }
                //如果满足条件则交换
                if (i<j) {
                    int temp = arr[j];
                    arr[j] = arr[i];
                    arr[i] = temp;
                }
            }
            //最后将基准为与i和j相等位置的数字交换
            arr[left] = arr[i];
            arr[i] = pivot;
            //递归调用左半数组
            quickSort(arr, left, j-1);
            //递归调用右半数组
            quickSort(arr, j+1, right);
        }

    法二:

     

         选择第一个为基准(需要将其先赋值给临时变量,方便覆盖赋值于最终赋值),同样的从right下标开始,如果其下标的值大于基准时,right下标向左移动,反之将right下标对应的值覆盖left下标的值;然后left下标对应的值小于等于基准时,left下标向右移动,反之将left下标对应值覆盖right的值。直到left下标与right下标相等,将将基准赋值到left或者right下标(此时基准元素便不会发生改变),直到最终规模为1,也就是全部有序了。

     

     由于数据特殊,一次居然就有序了,具体就是重复上面的操作。

    /**
         * 划分函数)(每进行一次就会确定一个位置)
         * @param arr
         * @param left
         * @param right
         * @return
         */
        public static int parition(int[] arr,int left,int right){
            int temp = arr[left];//基准
            while (left<right){
    //            从右想左寻找
                while (arr[right] > temp && left<right){
                    right--;
                }
    //            退出上面的循环说明该数比基准小,交换位置
                arr[left] = arr[right];
                //            从左向右寻找
                while (arr[left] <= temp && left<right){
                    left++;
                }
                //            退出上面的循环说明该数比基准大,交换位置
                arr[right] = arr[left];
            }
    //        说明i==j;本轮交换结束
            arr[left] = temp;
            return left;
        }
    
        /**
         * 递归调用,进行排序
         * @param arr
         * @param left
         * @param right
         */
        public static void qucikSort(int[] arr,int left,int right){
            if(left < right){
                int pos = parition(arr,left,right);
                //左边排序
                qucikSort(arr,left,pos-1);
                qucikSort(arr,pos+1,right);
            }
        }

     将上述递归操作变成非递归:

    /**
         * 非递归
         * @param arr
         * @param left
         * @param right
         */
        public static void niceQucikSort(int[] arr,int left,int right){
            Queue<Integer> queue = new LinkedList<>();
            queue.offer(left);
            queue.offer(right);
            while (!queue.isEmpty()) {
                left = queue.poll();
                right = queue.poll();
                int pos = parition(arr, left, right);
                if (left < pos - 1) {
                    queue.offer(left);
                    queue.offer(pos - 1);
                }
                if (pos + 1 < right) {
                    queue.offer(pos + 1);
                    queue.offer(right);
                }
            }
        }

    每次都是存入下标值,通过调用划分函数,来寻找每个基准的位置。

    优化:

          当数据越有序,并且选取的基准不恰当,时间复杂度就会变成O(n^2)。

    采用随机坐标值作为基准:

     /**
         * 随机下标划分
         * @param arr
         * @param left
         * @param right
         * @return
         */
        public static int RandomPartition(int[] arr,int left,int right){
            Random random = new Random();
            int index = random.nextInt(right - left+1) + left;
    //       将随机坐标换到最左边
            int temp = arr[left];
            arr[left] = arr[index];
            arr[index] = temp;
            return parition(arr,left,right);
        }

    另一种是三者取中。

     

  • 相关阅读:
    pillow模块的用法 + 随机验证码
    jquery文件阅读器 显示需要上传图片的预览功能
    pycharm永久激活方式
    pycharm汉化
    10.25网络编程到并发编程
    10.15 迭代器,生成器到常用模块的小结
    10.14 面向对象小结
    十一天学习内容总结大纲
    pip镜像源的替换
    前端jQuery导入方式
  • 原文地址:https://www.cnblogs.com/128-cdy/p/13409101.html
Copyright © 2020-2023  润新知