zoukankan      html  css  js  c++  java
  • 排序——快速排序

    1.选取枢纽元:三数中值分割法,得到的中间值即作为mid,将数组分为arrays[mid]左边的比它小,右边的比它大

    2.进行划分partition:首先将arrays[mid]放在arrays[high]处,然后对数组范围内的数值进行比较,

    (左右两边分别有一个指针来进行寻找,arrays[left] <= arrays[high],arrays[right] >= arrays[high])找到不符合要求的值,在左右交换位置。

    在left>=right时,终止查找,然后将swap(arrays, left, high);即可将枢纽元放入合适的位置

    3.循环进行左右两侧的选择枢纽元,划分

    注意:在partition之后,传回来的是划分好之后arrays[mid]应该在的位置,而不再是mid处了

    排序中的划分部分可以衍生出很多的问题:

    数据结构--荷兰国旗问题

    利用荷兰国旗问题的解法衍生出的随机快排解法

    注意在生成随机数时,是 (int)(Math.random() * (right - left + 1)) + left  

    快排优化:
    * 1.使用荷兰国旗法进行划分
    * 2.使用随机快排:将一直选取最后一个数进行比较的经典快排,改为随机选取一个数进行比较
    * 生成随机数的方法 int num = (int)(Math.Random()*(high - low + 1) + low);
    * 使用空间复杂度O(logN),用来记录各个递归中的断点,用来进行另外一半的递归
    * 工程上快排是非递归的

    public void quickSort(Integer[] arrays){
            if(arrays.length == 0) return;
            randomQuickSort( arrays, 0, arrays.length - 1 );
        }
    
        //随机快排
        public void randomQuickSort(Integer[] arrays, int left, int right){
            if(left >= right) return;
            swap(arrays, left + (int)(Math.random() * (right - left + 1)), right);
            int[] p = partitionRandom(arrays, left, right);
            randomQuickSort( arrays, left, p[0] - 1 );
            randomQuickSort(arrays, p[1] + 1, right);
        }
    
        public int[] partitionRandom(Integer[] arrays, int left, int right){
            int low = left - 1;
            int high = right;
    
            while(left < high){
                if(arrays[left] < arrays[right]){
                    swap(arrays, ++low, left++);
                } else if(arrays[left] > arrays[right]){
                    swap(arrays, --high, left);
                } else {
                    left++;
                }
            }
            swap(arrays, right, high);
    
            return new int[]{low + 1, high};
        }
    

      

    一般的解法

    package sort;
    import static sort.PrintRes.swap;
    /**
     * Created by Skye on 2018/3/27.
     */
    public class QuickSort {
        public void quickSort(Integer[] arrays){
            if(arrays.length == 0) return;
            quickSort( arrays, 0, arrays.length - 1 );
        }
    
        public void quickSort(Integer[] arrays, int low, int high){
            if(low >= high) return;
            int mid = threeMid(arrays, low, high);
            swap(arrays, mid, high);
            int num = partition(arrays, low, high);
            quickSort( arrays, low, num - 1 );
            quickSort(arrays, num + 1, high);
    
        }
    
        public int threeMid(Integer[] arrays, int low, int high){
            int mid = (low + high) / 2;
            if(arrays[low] > arrays[mid]) swap(arrays, low, mid);
            if(arrays[low] > arrays[high]) swap( arrays, low, high );
            if(arrays[mid] > arrays[high]) swap( arrays, mid, high );
            return mid;
        }
    
        public int partition(Integer[] arrays, int low, int high){
            int left = low;
            int right = high - 1;
    
            //把arrays[mid]放到合适的位置
            while(left < right){
                while(left < right && arrays[left] <= arrays[high]) {
                    left++;
                }
                while(right > left && arrays[right] >= arrays[high]) {
                    right--;
                }
                swap(arrays, left, right);
            }
            swap(arrays, left, high);
            return left;
        }
    }
    

      

    注意:可以将交换改成覆盖,来减少交换次数  将partition方法修改

    对于小数组,可以将排序改为插入排序   quickSort(Integer[] arrays, int low, int high)修改

      还可以将递归改成尾迭代:(不太懂)

    最终版

    package sort;
    import static sort.PrintRes.swap;
    public class QuickSort {
        public void quickSort(Integer[] arrays){
            if(arrays.length == 0) return;
            quickSort( arrays, 0, arrays.length - 1 );
        }
        public void quickSort(Integer[] arrays, int left, int right){
            if(left >= right) return;
            if(right - left > 10){
                int mid = threeMid(arrays, left, right);
                swap(arrays, mid, right);
                int num = partition(arrays, left, right);
                quickSort( arrays, left, num - 1 );
                quickSort(arrays, num + 1, right);
            } else{
                for(int i = left + 1; i <= right; i++){
                    int j = i - 1;
                    int temp = arrays[i];
                    for(; j >= left; j--){
                        if(arrays[j] < temp) break;
                        arrays[j + 1] = arrays[j];
                    }
                    arrays[j + 1] = temp;
                }
            }
        }
        public int threeMid(Integer[] arrays, int left, int right){
            int mid = (left + right) / 2;
            if(arrays[left] > arrays[mid]) swap(arrays, left, mid);
            if(arrays[left] > arrays[right]) swap( arrays, left, right );
            if(arrays[mid] > arrays[right]) swap( arrays, mid, right );
            return mid;
        }
        public int partition(Integer[] arrays, int left, int right){
            int low = left;
            int high = right;
            //把arrays[mid]放到合适的位置
            //枢纽元放在最右边,记录枢纽元的值
            int temp = arrays[right];
            while(low < high){
                while(low < high && arrays[low] <= temp) {
                    low++;
                }
                //相当于交换arrays[left] arrays[right],交换后,right-1(开始时,right处放置的是枢纽元的值,就是将枢纽元覆盖掉)
                arrays[high--] = arrays[low];
                while(high > low && arrays[high] >= temp) {
                    high--;
                }
                //相当于交换arrays[left] arrays[right],交换后,left+1(此时,arrays[left]的值已经存放在arrays[right]中了)
                arrays[low++] = arrays[high];
            }
            //最后再将枢纽元放回到数组中
            arrays[low] = temp;
            return low;
        }
    }
    
  • 相关阅读:
    HDU 4024 Dwarven Sniper’s hunting(数学公式 或者是二分)
    二分图最大匹配总结
    HDU 4022 Bombing (STL应用)
    HDU 1847 Good Luck in CET4 Everybody!(组合博弈)
    HDU 1556 Color the ball(树状数组)
    HDU 4023 Game(博弈)
    HDU 1406 完数(水题)
    HDU 4021 24 Puzzle
    Oracle 多表查询优化
    【编程之美】字符串移位包含的问题(续)
  • 原文地址:https://www.cnblogs.com/SkyeAngel/p/8660466.html
Copyright © 2011-2022 走看看