快速排序

快速排序的算法思想是分治算法,分而治之,将对整体的排序转换成对部分的排序,当部分完成了排序,整体排序也就完成了。算法的时间复杂度为O(nlogn)。

双边循环法:设置一个基准元素(一般数组第一位)pivot,两个指针left,right。left指向数组的第一位(不一定是0),right指向数组最后一位(不一定是array.length-1)。

1.首先从right指针开始,如果元素大于pivot则right指针左移,否则right停止,切换到left指针。

2.从left指针开始,如果元素小于pivot则left指针右移,否则left停止。

3.交换left和right的元素。

4.重复1-3步骤直到left,right指针重合。

5.将pivot基准元素替换到指针重合处,此轮排序完成,此时pivot左侧元素均小于pivot,pivot右侧元素均大于pivot。

单边循环法:设置一个基准元素(一般数组第一位)pivot,一个指针mark指向数组的第一位,mark作为分割点。

1.遍历给定数组,索引设置为i。如果i处元素大于pivot,继续遍历,否则进入步骤2。

2.mark指针右移一位,交换i处元素和mark处元素的值。

3.重复步骤1-2。

4.遍历完成时交换pivot和mark处元素值,此轮排序完成,此时pivot左侧元素均小于pivot,pivot右侧元素均大于pivot。

public class MyQuickSort {
    public static void main(String[] args) {
        //分治思想,分而治之
        //从小到大排序
        MyQuickSort myQuickSort = new MyQuickSort();
        int[] array = {8, 4, 3, 5, 6, 2, 9, 7};
//        myQuickSort.quickSort(array, 0, array.length - 1);
        myQuickSort.quickSortByStack(array, 0, array.length - 1);
        System.out.println(Arrays.toString(array));
    }

    //非递归方式-栈
    public void quickSortByStack(int[] array, int startIndex, int endIndex) {
        Stack<Map<String, Integer>> stack = new Stack<>();
        Map<String, Integer> rootMap = new HashMap<>();
        rootMap.put("startIndex", startIndex);
        rootMap.put("endIndex", endIndex);
        stack.push(rootMap);

        while (!stack.isEmpty()) {
            Map<String, Integer> pop = stack.pop();
            //获取基准元素位置,此过程完成了一轮排序
            int pivotIndex = getPivotByOnePointer(array, pop.get("startIndex"), pop.get("endIndex"));
            if (pop.get("startIndex") < pivotIndex - 1) {
                //左半区域入栈
                Map<String, Integer> leftMap = new HashMap<>();
                leftMap.put("startIndex", pop.get("startIndex"));
                leftMap.put("endIndex", pivotIndex - 1);
                stack.push(leftMap);
            }

            if (pivotIndex + 1 < pop.get("endIndex")) {
                //右半区域入栈
                Map<String, Integer> right = new HashMap<>();
                right.put("startIndex", pivotIndex + 1);
                right.put("endIndex", pop.get("endIndex"));
                stack.push(right);
            }
        }
    }

    //递归方式
    public void quickSort(int[] array, int startIndex, int endIndex) {
        //跳出递归
        if (startIndex >= endIndex) {
            return;
        }

        //获取基准元素的索引,此过程也完成了一轮排序
//        int pivotIndex = getPivotByTwoPointer(array, startIndex, endIndex);
        int pivotIndex = getPivotByOnePointer(array, startIndex, endIndex);

        //将数组分成两部分,分别快速排序,当各个部分完成排序,整体也就完成了排序。
        quickSort(array, startIndex, pivotIndex - 1);
        quickSort(array, pivotIndex + 1, endIndex);
    }

    //双边循环法
    public int getPivotByTwoPointer(int[] array, int startIndex, int endIndex) {
        //简化步骤,取数组第一个元素为基准元素
        int pivot = array[startIndex];
        //left指针左侧元素都会比基准元素小
        int left = startIndex;
        //right指针右侧元素都会比基准元素大
        int right = endIndex;

        while (left != right) {
            //从右侧开始找到比基准元素小的值才停下来,指针重合停下来
            while (array[right] >= pivot && left < right) {
                right--;
            }

            //从左侧开始找到比基准元素大的值才停下来,指针重合停下来
            while (array[left] <= pivot && left < right) {
                left++;
            }

            //left==right时不用交换
            if (left < right) {
                //交换left,right指针位置元素,交换后使得较小的元素在左侧,较大的元素在右侧。
                int temp = array[right];
                array[right] = array[left];
                array[left] = temp;
            }
        }

        //pivot和指针重合点交换
        array[startIndex] = array[right];
        array[right] = pivot;
        return right;
    }

    //单边循环法
    public int getPivotByOnePointer(int[] array, int startIndex, int endIndex) {
        //基准元素
        int pivot = array[startIndex];
        //通过基准元素将数组分成两部分,一部分元素小于基准元素,一部分元素大于基准元素,mark是分割点。
        int mark = startIndex;
        int temp;
        for (int i = startIndex + 1; i <= endIndex; i++) {
            //当前元素小于基准元素时,mark右移且交换mark和i处的值
            if (array[i] < pivot) {
                mark++;
                temp = array[i];
                array[i] = array[mark];
                array[mark] = temp;
            }
        }

        //交换startIndex和mark处的值
        array[startIndex] = array[mark];
        array[mark] = pivot;
        return mark;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值