免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
數(shù)據(jù)結(jié)構(gòu)與算法——排序算法(5)——快速排序

目錄

1.基本思想

1.1 基本思想

1.2 使用分治策略的三個步驟分析快速排序

1.3 歸并排序與快速排序比較

2.圖解原理

3.代碼實現(xiàn)

3.1 實現(xiàn)方式1:選取中間值作為基準(zhǔn)值

3.2 實現(xiàn)方式2:選取最右邊的值作為基準(zhǔn)值

4.性能分析


1.基本思想

1.1 基本思想

  • 快速排序是基于分治策略的一種排序

  • 基本思想

    • 1.基準(zhǔn):先從數(shù)列中取出一個數(shù)作為基準(zhǔn)數(shù)。

    • 2.分區(qū)過程:將比這個數(shù)大的數(shù)全放到它的右邊,小于或等于它的數(shù)全放到它的左邊。

    • 3.再對左右區(qū)間重復(fù)第一、二步,直到各區(qū)間只有一個數(shù)。  

  • 注意:快速排序在分的時候,就進行了“排序”處理

1.2 使用分治策略的三個步驟分析快速排序

  • 1.分解:將數(shù)組A[p..r]劃分為兩個(可能為空)子數(shù)組A[p...q-1]和A[q 1...r],使得A[p...q-1]中的每一個元素都小于等于A[q],而A[q]也小于等于A[q 1...r]中的每個元素

  • 2.解決:通過遞歸調(diào)用快速排序,對子數(shù)組A[p...q-1]和A[q 1...r]進行排序

  • 3.合并:因為子數(shù)組都是原址排序的,所以不需要合并操作:數(shù)組A[p...r]已經(jīng)有序

1.3 歸并排序與快速排序比較

  • 歸并排序?qū)?shù)組分成連個子數(shù)組分別排序,并將有序的子數(shù)組歸并以將整個數(shù)組排序;而快速排序是當(dāng)兩個子數(shù)組都有序時,整個數(shù)組也就自然有序了

  • 歸并排序在分的時候不進行任何處理,而快速排序在分的時候,要進行元素交換,保正左邊元素小于基準(zhǔn)值,右邊元素大于基準(zhǔn)值

  • 歸并排序遞歸調(diào)用發(fā)生在處理整個數(shù)組之前,快速排序遞歸調(diào)用發(fā)生在處理整個數(shù)組之后

  • 歸并排序在合并的時候完成排序,快速排序在分的時候完成排序,合并時,什么都不做

  • 在歸并排序中,一個數(shù)組被等分為兩半,在快速排序中,切分的位置取決于數(shù)組的內(nèi)容

2.圖解原理

3.代碼實現(xiàn)

關(guān)鍵詞解釋

  • pivot:基準(zhǔn)元素

  • partition:將整個數(shù)組進行切分

3.1 實現(xiàn)方式1:選取中間值作為基準(zhǔn)值

public class QuickSort extends Sort {    /**     * sort方法為外界提供了統(tǒng)一的調(diào)用“接口”     * @param arr     */    @Override    public void sort(Comparable[] arr) {        quickSort(arr,0,arr.length-1);    }        private void quickSort(Comparable[] arr,int left,int right){        if(left >= right){            return;        }        //經(jīng)過切分后基準(zhǔn)值最終索引        int pivot = partition(arr,left,right);        //對pivot左邊進行遞歸切分        quickSort(arr,left,pivot-1);        //對pivot右邊進行遞歸切分        quickSort(arr,pivot 1,right);    }    /**     * 切分數(shù)組,切分為左邊小于pivot,右邊大于pivot     * @param arr     * @param left     * @param right     * @return  返回中間基準(zhǔn)值pivot的索引值     */    private int partition(Comparable[] arr,int left,int right){        //我們這里取中間值基準(zhǔn)值,        Comparable pivot = arr[(left right)/2];        //定義兩個指針指向兩邊        int move_right = left;        int move_left = right;        /**         * 當(dāng)兩個指針相等或向右移動的指針大于向左移動的指針的時候,代表遍歷完所有的元素         *         * while循環(huán)的目的是讓比pivot小的元素在pivot的左邊,比pivot大的元素在右邊         */        while(move_right < move_left){            /**             * 右移指針尋找大于等于pivot的值,             *             *             * 最后的情況就是pivot左邊全部是小于pivot的,這時,找到的是pivot值             * 然后右邊找到的是非pivot的話,就發(fā)生交換,等于pivot的話,move_right不一定等于move_left             *             * 因為有可能有多個重復(fù)的與pivot本身相同的值,所以交換后,我們也要讓指針繼續(xù)移動,             * 確保通過指針的相對大小判斷循環(huán)結(jié)束,否則,在交換后,不移動指針,可能會形成死循環(huán)(兩個指針同時指向兩個相鄰的pivot)             *             */            while(arr[move_right].compareTo(pivot) < 0){                //右移指針指向的值小于pivot的值,不用交換,指針繼續(xù)右移                move_right  ;            }            /**             * 左移指針尋找小于等于pivot的值             *             * 同上,最后的情況就是找到pivot             */            while (arr[move_left].compareTo(pivot) > 0){                //左移指針指向的值大于pivot的值,不用交換,指針繼續(xù)左移                move_left--;            }            //兩個指針遍歷完所有元素,結(jié)束循環(huán)            if(move_right >= move_left)                break;            //交換兩個指針指向的值            swap(arr,move_right,move_left);            /**             * 迭代,讓指針移動             *             * 指針指向的值為pivot的時候,讓另一個指針靠近自己,以最終結(jié)束循環(huán)             */            //如果右移指針指向pivot,左移指針--            if(arr[move_right].compareTo(pivot) == 0){                move_left--;            }            //如果左移指針指向pivot,右移指針--            if(arr[move_left].compareTo(pivot) == 0){                move_right  ;            }        }        /**         * 最終我們需要返回用于切分的基準(zhǔn)值的最終索引         *         * 循環(huán)過后,兩個指針總有一個是指向pivot的,通過以下判斷,最終返回pivot的索引         */        int pivotIndex;        if(arr[move_right] == pivot){            pivotIndex = move_right;        }else{            pivotIndex = move_left;        }        return pivotIndex;    }}
import java.util.Arrays;public class SortTest {    public static void main(String[] args) {        Integer[] arr = new Integer[]{8,9,1,7,2,3,5,5,4,4,5,6,0};        System.out.println("未排序的數(shù)組為:");        System.out.println(Arrays.toString(arr));        QuickSort quickSort = new QuickSort();        quickSort.sort(arr);        System.out.println("排序后的數(shù)組為:");        System.out.println(Arrays.toString(arr));    }}

3.2 實現(xiàn)方式2:選取最右邊的值作為基準(zhǔn)值

public class QuickSort extends Sort {    /**     * sort方法為外界提供了統(tǒng)一的調(diào)用“接口”     *     * @param arr     */    @Override    public void sort(Comparable[] arr) {        quickSort(arr, 0, arr.length - 1);    }        private void quickSort(Comparable[] arr, int left, int right) {        if (left >= right) {            return;        }        //經(jīng)過切分后基準(zhǔn)值最終索引        int pivot = partition(arr, left, right);        //對pivot左邊進行遞歸切分        quickSort(arr, left, pivot - 1);        //對pivot右邊進行遞歸切分        quickSort(arr, pivot   1, right);    }    /**     * 切分數(shù)組,切分為左邊小于pivot,右邊大于pivot     *     * @param arr     * @param left     * @param right     * @return 返回中間基準(zhǔn)值pivot的索引值     */    private int partition(Comparable[] arr, int left, int right) {        //我們這里取最后一個值作為基準(zhǔn)值,        Comparable pivot = arr[right];        //定義一個指針,右移記錄,i指向小于等于pivot的最后一個值的下一個位置        int i = left;  //初始化為起始位置        //遍歷left到right-1之間的元素        for (int j = left; j <= right - 1; j  ) {            if (arr[j].compareTo(pivot) <= 0) {                //當(dāng)前遍歷元素小于等于基準(zhǔn)值                //交換小于等于pivot的最后一個值的下一個位置的值(無所謂它的大?。┡c當(dāng)前遍歷元素                swap(arr, i, j);                //此時小于等于pivot的最后一個值為交換后的值,所以i 1,在i前面的表示都小于等于pivot                i  ;            }        }        //這樣遍歷完,小于等于pivot的值都被交換到了i位置的前面,最終i位置本身指向的是大于pivot的        //這時,交換i位置處的值和pivot,最終pivot左邊是小于等于它的值,pivot右邊是大于它的值        swap(arr, i, right);        //最終返回pivot最終的索引值,即i        return i;    }}
import java.util.Arrays;public class SortTest {    public static void main(String[] args) {        Integer[] arr = new Integer[]{8,9,1,7,2,3,5,5,4,4,5,6,0,0,343,6789};        System.out.println("未排序的數(shù)組為:");        System.out.println(Arrays.toString(arr));        QuickSort quickSort = new QuickSort();        quickSort.sort(arr);        System.out.println("排序后的數(shù)組為:");        System.out.println(Arrays.toString(arr));    }}

4.性能分析

  • 快速排序是一種最壞時間復(fù)雜度為O(n^2)的排序算法,

  • 但是快速排序通常是實際排序應(yīng)用中最好的選擇,因為它的平均性能非常好——它期望的時間復(fù)雜度為O(nlgn),而且O(nlgn)中隱含的常數(shù)因子非常小

  • 快速排序是原址排序的,所以空間復(fù)雜度為O(1)

  • 快速排序再虛存環(huán)境中也能很好地工作

代碼演示示例:

public class SortPerformanceTest {    public static void main(String[] args) {        //創(chuàng)建100000個隨機數(shù)據(jù)        Double[] arr1 = new Double[100000];        for (int i = 0; i < arr1.length; i  ) {            arr1[i] = (Double) (Math.random() * 10000000);  //這里使用10000000是為了讓數(shù)據(jù)更分散        }        //創(chuàng)建排序類的對象        QuickSort quickSort = new QuickSort();        //使用希爾排序?qū)rr1進行排序        long quickSort_start = System.currentTimeMillis();        quickSort.sort(arr1);        long quickSort_end = System.currentTimeMillis();        System.out.println("快速排序所用的時間為:" (quickSort_end - quickSort_start) "ms");    }}

來源:https://www.icode9.com/content-1-442251.html
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Arrays.sort如何實現(xiàn)降序排序
美團面試:請手寫一個快排,被我懟了!
js實現(xiàn)快速排序(in
八十一、最快最優(yōu)的快速排序和優(yōu)化
排序算法---快速排序
python編程,算法難學(xué)?不存在的,這本書讓你想小說一樣入門算法
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服