java学习24

90 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情

快速排序

基本思路

需要一个基准值,在这个基准值的右边的数都比这个基准值大,左边的数都比这个基准值小。一趟排序就可以确定一个数的最终位置,这个快速排序是在两头同时进行比较,若左边指针high若大于基准值,则移动指针,若小于基准值,则low开始移动指针,若大于基准值,则交换数据.下面模拟了快速排序的过程。

image.png

 思考

快速排序,会在左右两边各设置一个指针low和hight,上面模拟的时候是从hight开始,则是否可以从low开始呢?hight是遇到比基准值小的数会停下来,low是遇到基准值比自己大的会停下来,所以low与hight相遇时需要交换基准值,而相遇时的那个值可能大于基准值(因为low先移动指针,而low是找最大的值停下来),在最后与基准值交换数据时,会把比基准值较大的数据交换,导致不满足左边小右边大。最后的递归也将出错。(这里模拟的是从小到大的升序排序)

递归思想

每一趟排序后就会有基准值的左右两边,对左右两边又进行同样的快速排序操作操作,所以这个是有递归思想在里面的,用递归算法解决。

 代码实现

方法中的两个递归分别是对基准值左边和右边分别又进行快速排序

quickSortRecursive(paraStart, tempLeft - 1);

quickSortRecursive(tempLeft + 1, paraEnd);

(这里先移动指针是移动的左边,因为我们可以看到他选的基准值是待排序的最后一个)

    public void quickSortRecursive(int paraStart, int paraEnd) {
        // Nothing to sort.
        if (paraStart >= paraEnd) {
            return;
        } // Of if
 
        int tempPivot = data[paraEnd].key;
        DataNode tempNodeForSwap;
 
        int tempLeft = paraStart;
        int tempRight = paraEnd - 1;
 
        // Find the position for the pivot.At the same time move smaller elements to the left and bigger one to the right.
        while (true) {
            //左边指针要先移动
            while ((data[tempLeft].key < tempPivot) && (tempLeft < tempRight)) {
                tempLeft++;
            }
 
            while ((data[tempRight].key >= tempPivot) && (tempLeft < tempRight)) {
                tempRight--;
            }
 
            if (tempLeft < tempRight) {
                // Swap.
                System.out.println("Swapping " + tempLeft + " and " + tempRight);
                tempNodeForSwap = data[tempLeft];
                data[tempLeft] = data[tempRight];
                data[tempRight] = tempNodeForSwap;
            } else {
                break;
            }
        }
 
        // Swap
        if (data[tempLeft].key > tempPivot) {
            tempNodeForSwap = data[paraEnd];
            data[paraEnd] = data[tempLeft];
            data[tempLeft] = tempNodeForSwap;
        } else {
            tempLeft++;
        } 
 
        System.out.print("From " + paraStart + " to " + paraEnd + ": ");
        System.out.println(this);
 
        quickSortRecursive(paraStart, tempLeft - 1);
        quickSortRecursive(tempLeft + 1, paraEnd);
    }// Of quickSortRecursive

测试结果:

-------quickSortTest-------
I am a data array with 7 items.
(1, if)  (3, then)  (12, else)  (10, switch)  (5, case)  (7, for)  (9, while)  
Swapping 2 and 5
Swapping 3 and 4
From 0 to 6: I am a data array with 7 items.
(1, if)  (3, then)  (7, for)  (5, case)  (9, while)  (12, else)  (10, switch)  
From 0 to 3: I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (12, else)  (10, switch)  
From 0 to 1: I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (12, else)  (10, switch)  
From 5 to 6: I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (10, switch)  (12, else)  
Result
I am a data array with 7 items.
(1, if)  (3, then)  (5, case)  (7, for)  (9, while)  (10, switch)  (12, else)  

总结

今天学习了快速排序,快速排序要注意的是那个指针先移动。其次是对比昨天学习的冒泡排序,冒泡排序是从一边开始,并且交换的是相邻两个元素,他也会确定一个最终位置,但是这个最终位置是从下到上依次确定(或从上到下),而快速排序,他也是交换数据,但是他是两边同时开始比较,每次也会确定一个数的最终位置,但是这个位置并不是有规律的,需要结合排序的数据来看,相比冒泡,快速排序的基准值要选好才是关键。