成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

DS&ALGR : 通過簡單排序理解大O表示法

Eirunye / 2755人閱讀

摘要:在上面的三種排序中,它們的效率為用大表示法來表示都是,但實際上按比較的次數(shù)和交換的次數(shù)來考慮,插入排序效率高于選擇排序,選擇排序效率高于冒泡排序。大表示法常見的基于的走勢圖如下圖所示

大O表示法初體驗
身在斯洛文尼亞的阿拉里克得到斯提里科被殺的消息后,仰天大笑:“終于沒有人能阻止我去羅馬了。”
當(dāng)他手下的將軍問:“不知大王打算走哪條路去羅馬?”
西哥特王哈哈大笑,說出了那句千古名言:All roads lead to Rome


條條大路通羅馬,這句著名的英語諺語告訴人們,達到同一目的可以有多種不同的方法和途徑。
在編程中同樣如此,同樣一個編程問題,十個程序員可能會寫出十種程序,算法各不相同,確實是條條大路通羅馬。
但程序員對算法的效率可不會像西哥特王那般豪放和豁達,程序員對于算法的效率十分在乎,盡管算法無論效率高低,均能解決問題,但效率高的算法,除了能解決問題,還可以在問題規(guī)模變大變復(fù)雜時,高效地解決問題。

于是,我們面臨一個問題,那就是如何評價,以及從什么角度去評價一個算法。

通常,我們可能說,這個算法比那個算法更快一點,但這個比較是沒有意義的。當(dāng)算法要處理的數(shù)據(jù)項數(shù)量不同時,誰快誰慢都要重新評價。

評價算法時,應(yīng)該結(jié)合數(shù)據(jù)量來評價,即當(dāng)數(shù)據(jù)量增大時,算法所消耗的時間變化趨勢。

在計算機世界中,這種粗略的評價方式被稱為大O表示法

簡單排序 冒泡排序

冒泡排序先從數(shù)組最左邊開始,比較第1個和第2個元素的值,值比較高的往數(shù)組的高位排,然后依次比較第2和第3個元素,值比較大的往高位排,一直比較到倒數(shù)第2個和倒數(shù)第1個元素,這稱為第一趟排序,這一趟就能確定數(shù)組中值最大的那個元素,并把這個最大的元素排到數(shù)組的最高位。
依次類推,第二趟排序會確定數(shù)組中第二大的元素,并把它排在最大的元素前邊。
假設(shè)數(shù)組有n個元素,那么經(jīng)過n-1趟排序,數(shù)組的元素就是有序的。
因為每一趟中,最大的元素就像水泡一樣,冒到了數(shù)組的高位,冒泡排序因此得名。

/**
 *
 *
 * @author beanlam
 * @date 2016年3月9日 下午11:26:20
 * @version 1.0
 *
 */
public class SimpleSort {

    public static void bubbleSort(final int[] array) {
        if (array == null || array.length == 0) {
            throw new IllegalArgumentException("array");
        }
        
        int length = array.length;
        for (int outLoop = length - 1; outLoop > 0; outLoop-- ) {
            for (int innerLoop = 0; innerLoop < outLoop; innerLoop++) {
                if (array[innerLoop] > array[innerLoop + 1]) {
                    swap(array, innerLoop, innerLoop + 1);
                }
            }
        }
    }
    
    private static void swap(final int[] array, final int left, final int right) {
        int temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }
}
選擇排序

選擇排序的過程是從左向右掃描數(shù)組,并從中找出最小值的元素,把它放在左邊已知的最小位置上,比如第一趟掃描,找出最小的元素后,將該元素放到數(shù)組的下標(biāo)0處。第二趟掃描從下標(biāo)1開始掃描,找出最小元素后,放到下標(biāo)1處。總共需要掃描n-1次,就能使該數(shù)組處于有序狀態(tài)。

/**
 *
 *
 * @author beanlam
 * @date 2016年3月9日 下午11:26:20
 * @version 1.0
 *
 */
public class SimpleSort {

    public static void selectionSort(final int[] array) {
        if (array == null || array.length == 0) {
            throw new IllegalArgumentException("array");
        }
        
        int length = array.length;
        int minIndex;
        for (int outLoop = 0; outLoop < length - 1; outLoop++) {
            minIndex = outLoop;
            for (int innerLoop = outLoop + 1;innerLoop < length; innerLoop++) {
                if (array[innerLoop] < array[minIndex]) {
                    minIndex = innerLoop;
                }
            }
            swap(array, outLoop, minIndex);
        }
    }
    
    private static void swap(final int[] array, final int left, final int right) {
        int temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }
}
插入排序

插入排序的精髓在于先令局部有序,先令左邊一部分?jǐn)?shù)據(jù)有序,然后這部分有序的元素的下一位再與這些有序的元素比較,尋找合適自己站立的位置,插隊排進去,插隊也意味著右邊的有序元素要挪動身子。
一下提供基于for循環(huán)和while循環(huán)的兩種插入排序?qū)崿F(xiàn)方式:

/**
 *
 *
 * @author beanlam
 * @date 2016年3月9日 下午11:26:20
 * @version 1.0
 *
 */
public class SimpleSort {
    public static void insertionSort(final int[] array) {
        if (array == null || array.length == 0) {
            throw new IllegalArgumentException("array");
        }
        
        int length = array.length;
        for (int outLoop = 1; outLoop < length; outLoop++) {
            int temp = array[outLoop];
            for (int innerLoop = outLoop - 1; innerLoop >= 0; innerLoop--) {
                if (array[innerLoop] > temp) {
                    array[innerLoop + 1] = array[innerLoop];
                    if (innerLoop == 0) {
                        array[innerLoop] = temp;
                    }
                } else {
                    array[innerLoop + 1] = temp;
                    break;
                }
            }
        }
    }
    
    public static void insertionSort1(final int[] array) {
        if (array == null || array.length == 0) {
            throw new IllegalArgumentException("array");
        }
        
        int length = array.length;
        int temp;
        int innerLoop;
        for (int outLoop = 1; outLoop < length; outLoop++) {
            temp = array[outLoop];
            innerLoop = outLoop;
            while (innerLoop > 0 && array[innerLoop - 1] >= temp) {
                array[innerLoop] = array[innerLoop-1];
                --innerLoop;
            }
            array[innerLoop] = temp;
        }
    }
     
    private static void swap(final int[] array, final int left, final int right) {
        int temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }
}
三種排序的效率比較

假設(shè)需要比較的數(shù)組中有N個元素,
冒泡排序中,需要掃描N-1趟,每掃描一趟就要多次對兩個元素做比較,并且在必要時需要對兩個元素做位置的交換,由于數(shù)據(jù)是隨機的,所以平均下來,一趟中大概有一半被掃描的數(shù)據(jù)需要作位置的交換。
第1趟需要N-1次比較,第2趟需要N-2次比較,以此類推,總共需要N(N-1)/2趟比較,而元素的交換次數(shù)平均下來需要做NN/4次。

選擇排序和冒泡排序進行了相同次數(shù)的比較N*(N-1)/2,但每一趟只有一次交換,甚至沒有任何交換。因此,選擇排序比冒泡排序更有效率,因為它減少了很多交換。

插入排序卻又要比選擇排序更有效率一點,因為第1趟排序中,它最多比較1次,第2趟排序中,最多比較2次, 依次類推,最后一趟,最多比較N-1次,
平均只有全體數(shù)據(jù)的一半被比較,因此比較的次數(shù)為N*(N-1)/4,與冒泡和選擇排序不同的是,插入排序不需要交換數(shù)據(jù),只是把一個值賦給數(shù)組的某一個下標(biāo),賦值的速度比交換數(shù)據(jù)的速度要快很多,因此插入排序比選擇排序和冒泡排序更有效率。

回到大O表示法

大O表示法只是一個粗略的估算值,它關(guān)注與隨著數(shù)據(jù)量N的增大,算法速度的變化。

對于數(shù)組某個下標(biāo)的賦值,算法消耗的時間是個常數(shù)K
對于線性的查找,算法的消耗時間與N成正比。
對于二分查找,算法消耗時間與log(N)成正比。

大O表示法通常會忽略常數(shù),因為它關(guān)注的是算法的消耗時間隨著N的變化而怎么變化。常數(shù)通常與處理器芯片或者編譯器有關(guān)。

在上面的三種排序中,它們的效率為用大O表示法來表示都是O(N^2),但實際上按比較的次數(shù)和交換的次數(shù)來考慮,插入排序效率高于選擇排序,選擇排序效率高于冒泡排序。

大O表示法常見的基于N的走勢圖如下圖所示:

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/65597.html

相關(guān)文章

  • 排序Java實現(xiàn)(遞歸方式&amp;非遞歸方式)

    摘要:很早就學(xué)習(xí)了堆排序但當(dāng)時沒有用代碼實現(xiàn),現(xiàn)在再去想實現(xiàn)已經(jīng)忘光光啦,于是就去網(wǎng)上搜了一番,發(fā)現(xiàn)沒有一篇我能認(rèn)真看完的文章,沒辦法就是沒耐心,就是笨唄。。。 很早就學(xué)習(xí)了堆排序但當(dāng)時沒有用代碼實現(xiàn),現(xiàn)在再去想實現(xiàn)已經(jīng)忘光光啦┑( ̄Д  ̄)┍,于是就去網(wǎng)上搜了一番,發(fā)現(xiàn)沒有一篇我能認(rèn)真看完的文章,沒辦法就是沒耐心,就是笨唄。。。好了,言歸正傳= ̄ω ̄= 了解概念 首先明白什么是堆,什么是完...

    jzman 評論0 收藏0
  • 泛化&amp;泛化數(shù)據(jù)集&amp;實驗

    摘要:泛化泛化數(shù)據(jù)集實驗泛化過擬合的風(fēng)險泛化泛化能力是指機器學(xué)習(xí)算法對新鮮樣本的適應(yīng)能力。機器學(xué)習(xí)的基本沖突是適當(dāng)擬合我們的數(shù)據(jù),但也要盡可能簡單地擬合數(shù)據(jù)。使用測試集再次檢查該模型。特征通常在正常范圍內(nèi),其中第百分位數(shù)的值約為。 泛化&泛化數(shù)據(jù)集&實驗 泛化 (Generalization):過擬合的風(fēng)險 泛化:泛化能力(generalization ability)是指機器學(xué)習(xí)算法對新...

    SimpleTriangle 評論0 收藏0
  • react+mobx 構(gòu)建H5制作工具項目經(jīng)驗總結(jié)

    摘要:三性能優(yōu)化處理做工具類的項目,性能是非常大的挑戰(zhàn),我總結(jié)了以下幾個常見的性能優(yōu)化點數(shù)據(jù)緩存。防抖,節(jié)流,事件委托內(nèi)存釋放。 內(nèi)容大綱: 1、功能介紹 2、技術(shù)架構(gòu) 3、性能優(yōu)化 4、細(xì)節(jié)分享 5、開源說明 一、項目功能介紹 很久沒寫過技術(shù)類的文章了,這次給大家分享一個近期的項目,采用react+mobx+jquery構(gòu)建的大型工具類項目。查看項目網(wǎng)址。 如果用過易企秀,maka或者...

    用戶84 評論0 收藏0
  • react+mobx 構(gòu)建H5制作工具項目經(jīng)驗總結(jié)

    摘要:三性能優(yōu)化處理做工具類的項目,性能是非常大的挑戰(zhàn),我總結(jié)了以下幾個常見的性能優(yōu)化點數(shù)據(jù)緩存。防抖,節(jié)流,事件委托內(nèi)存釋放。 內(nèi)容大綱: 1、功能介紹 2、技術(shù)架構(gòu) 3、性能優(yōu)化 4、細(xì)節(jié)分享 5、開源說明 一、項目功能介紹 很久沒寫過技術(shù)類的文章了,這次給大家分享一個近期的項目,采用react+mobx+jquery構(gòu)建的大型工具類項目。查看項目網(wǎng)址。 如果用過易企秀,maka或者...

    Aceyclee 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<