1. 程式人生 > >八大常用排序演算法詳細分析 包括複雜度,原理和實現

八大常用排序演算法詳細分析 包括複雜度,原理和實現

1. 氣泡排序

1.1 演算法原理:

S1:從待排序序列的起始位置開始,從前往後依次比較各個位置和其後一位置的大小並執行S2。 
S2:如果當前位置的值大於其後一位置的值,就把他倆的值交換(完成一次全序列比較後,序列最後位置的值即此序列最大值,所以其不需要再參與冒泡)。 
S3:將序列的最後位置從待排序序列中移除。若移除後的待排序序列不為空則繼續執行S1,否則冒泡結束。

1.2 演算法實現(Java):

1.2.1 基礎實現:

public static void bubbleSort(int[] array) {
    int len = array.length;
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            if (array[j] > array[j + 1]) {
                int temp = array[j + 1];
                array[j + 1] = array[j];
                array[j] = temp;
            }
        }
    }
}

1.2.2 演算法優化:

若某一趟排序中未進行一次交換,則排序結束

public static void bubbleSort(int[] array) {
    int len = array.length;
    boolean flag = true;
    while (flag) {
        flag = false;
        for (int i = 0; i < len - 1; i++) {
            if (array[i] > array[i + 1]) {
                int temp = array[i + 1];
                array[i + 1] = array[j];
                array[i] = temp;
                flag = true;
            }
        }
        len--;
    }
}

2. 快速排序

2.1 演算法原理:

快速排序是對氣泡排序的一種改進。基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此實現整個資料變成有序序列。

2.2 演算法實現(Java):

public static void quickSort(int[] array, int left, int right) {
    if (left < right) {
        int pivot = array[left];
        int low = left;
        int high = right;
        while (low < high) {
            while (low < high && array[high] >= pivot) {
                high--;
            }
            array[low] = array[high];
            while (low < high && array[low] <= pivot) {
                low++;
            }
            array[high] = array[low];
        }
        array[low] = pivot;
        quickSort(array, left, low - 1);
        quickSort(array, low + 1, right);
    }
}

3. 直接插入排序

3.1 演算法原理:

插入排序的基本方法是:每步將一個待排序序列按資料大小插到前面已經排序的序列中的適當位置,直到全部資料插入完畢為止。 
假設有一組無序序列 R0R1, … , Rn1: 
(1) 將這個序列的第一個元素R0視為一個有序序列; 
(2) 依次把 R1R2, … , Rn1 插入到這個有序序列中; 
(3) 將Ri插入到有序序列中時,前 i-1 個數是有序的,將RiR0 ~ Ri1從後往前進行比較,確定要插入的位置。

3.2 演算法實現(Java):

public static void insertSort(int[] array) {
    for (int i = 1, len = array.length; i < len; i++) {
        if (array[i] < array[i - 1]) {
            int temp = array[i];
            int j;
            for (j = i - 1; j >= 0 && temp < array[j]; j--) {
                array[j + 1] = array[j];
            }
            array[j + 1] = temp;
        }

    }
}

4. Shell排序

4.1 演算法原理:

希爾排序是一種插入排序演算法,又稱作縮小增量排序。是對直接插入排序演算法的改進。其基本思想是: 
先取一個小於n的整數h1作為第一個增量,把全部資料分成h1個組。所有距離為h1的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量h2<h1重複上述的分組和排序,直至所取的增量ht=1(ht<ht1<<h2<h1,即所有記錄放在同一組中進行直接插入排序為止。該方法實質上是一種分組插入方法。

4.2 演算法實現(Java):

public static void shellSort(int[] array) {
    int n = array.length;
    int h;
    for (h = n / 2; h > 0; h /= 2) {
        for (int i = h; i < n; i++) {
            for (int j = i - h; j >= 0; j -= h) {
                if (array[j] > array[j + h]) {
                    int temp = array[j];
                    array[j] = array[j + h];
                    array[j + h] = temp;
                }
            }
        }
    }
}

5. 直接選擇排序

5.1 演算法原理:

直接選擇排序是一種簡單的排序方法,它的基本思想是: 
第一次從R[0]~R[n-1]中選取最小值,與R[0]交換, 
第二次從R[1]~R[n-1]中選取最小值,與R[1]交換, 
…., 
第i次從R[i-1]~R[n-1]中選取最小值,與R[i-1]交換, 
….., 
第n-1次從R[n-2]~R[n-1]中選取最小值,與R[n-2]交換, 
共通過n-1次,得到一個從小到大排列的有序序列。

5.2 演算法實現(Java):

public static void selectSort(int[] array) {
    int n = array.length;
    for (int i = 0; i < n; i++) {
        int minIndex = i;
        for (int j = i + 1; j < n; j++) {
            if (array[minIndex] > array[j]) {
                minIndex = j;
            }
        }
        if (i != minIndex) {
            int temp = array[i];
            array[i] = array[minIndex];
            array[minIndex] = temp;
        }
    }
}

6. 堆排序

6.1 演算法原理:

6.1.1 二叉堆定義:

二叉堆是完全二叉樹或近似完全二叉樹。二叉堆滿足兩個特性: 
  1)父結點的鍵值總是大於或等於(小於或等於)任何一個子節點的鍵值。 
  2)每個結點的左子樹和右子樹都是一個二叉堆。 
當父結點的鍵值總是大於或等於任何一個子節點的鍵值時為大根堆。當父結點的鍵值總是小於或等於任何一個子節點的鍵值時為小根堆。下面展示一個小根堆: 
這裡寫圖片描述 
由於其它幾種堆(二項式堆,斐波納契堆等)用的較少,一般將二叉堆就簡稱為堆。

6.1.2 堆的儲存:

一般都用陣列來表示堆,i結點的父結點下標就為(i – 1) / 2。它的左右子結點下標分別為2 * i + 1和2 * i + 2。如第0個結點左右子結點下標分別為1和2。 
這裡寫圖片描述

6.1.3 堆的插入:

每次插入都是將新資料放在陣列最後。可以發現從這個新資料的父結點到根結點必然為一個有序的數列,然後將這個新資料插入到這個有序資料中。

6.1.4 堆排序:

堆排序(Heapsort)是指利用堆積樹(堆)這種資料結構所設計的一種排序演算法,它是選擇排序的一種。可以利用陣列的特點快速定位指定索引的元素。堆分為大根堆和小根堆,是完全二叉樹。大根堆的要求是每個節點的值都不大於其父節點的值,即A[PARENT[i]] >= A[i],小根堆則相反。 
堆排序利用了大根堆(或小根堆)堆頂記錄的關鍵字最大(或最小)這一特徵,使得在當前無序區中選取最大(或最小)關鍵字的記錄變得簡單。 
(1)用大根堆排序的基本思想 
  ① 先將初始陣列R1...Rn建成一個大根堆,此堆為初始的無序區 
  ② 再將最大的元素R1(即堆頂)和無序區的最後一個記錄Rn交換,由此得到新的無序區R1...Rn1和有序區Rn,且滿足

相關推薦

八大常用排序演算法詳細分析 包括複雜原理實現

1. 氣泡排序 1.1 演算法原理: S1:從待排序序列的起始位置開始,從前往後依次比較各個位置和其後一位置的大小並執行S2。  S2:如果當前位置的值大於其後一位置的值,就把他倆的值交換(完成一次全序列比較後,序列最後位置的值即此序列最大值,所以其不需要再參與冒泡)。  S3:將序列的最

常用排序演算法穩定性、時間複雜分析

1、  選擇排序、快速排序、希爾排序、堆排序不是穩定的排序演算法,        氣泡排序、插入排序、歸併排序和基數排序是穩定的排序演算法。 2、研究排序演算法的穩定性有何意義?   首先,排序演算法的穩定性大家應該都知道,通俗地講就是能保證排序前兩個相等的資

常用排序演算法中的時間複雜空間複雜

排序法 最差時間分析 平均時間複雜度 穩定度 空間複雜度 氣泡排序 O(n2) O(n2) 穩定 O(1) 快速排序 O(n2) O(n*log2n) 不穩定 O(log2n)~O(n) 選擇排序 O(n2) O(n2) 不穩定

八大排序演算法及時間空間複雜分析java版

//放在一起感覺又臭又長,所以每排序我單獨放出來了,歡迎大家平均交流指出不足import java.lang.reflect.Array;import java.util.*;public class EightKindOfSort {/*選擇排序    (不穩定演算法) *

淺談直接插入排序演算法思想以及時間複雜分析

研究意義 直接插入排序是最基本的一種排序演算法,其思想簡單,容易掌握,對後期的學習也有一定的幫助。 必備知識(之後不再敘述) 排序:將一組雜亂無章的資料排列成一個按關鍵字有序的序列。 穩定性:關鍵值相

排序演算法 (穩定性時間複雜分析

1、  選擇排序、快速排序、希爾排序、堆排序不是穩定的排序演算法,        氣泡排序、插入排序、歸併排序和基數排序是穩定的排序演算法。 2、研究排序演算法的穩定性有何意義?   首先,排序演算法的穩定性大家應該都知道,通俗地講就是能保證排序前兩個相等的資

常用排序演算法效能分析

在平時寫程式碼時比較常用的幾種演算法,效能表格如下: 排序法 平均時間 最壞 穩定 額外空間 氣泡排序 O(n^2) O(n^2) 穩定 O(1) 選擇排序

演算法複雜分析(時間複雜空間複雜)

前幾天被問到虛擬DOM的時間複雜度,一臉蒙圈,什麼是時間複雜度,我可能大學的資料結構課都在睡覺吧,今天來看看巨人的肩膀。 為什麼要進行演算法分析? 預測演算法所需的資源: 計算時間(CPU消耗) 記憶體空間(RAM消耗) 通訊時間(頻寬消耗) 預測演算法的執行時間: 在給定輸入規

各種排序演算法比較:時間複雜,空間複雜

時間複雜度 n^2表示n的平方,選擇排序有時叫做直接選擇排序或簡單選擇排序 排序方法 平均時間 最好時間 最壞時間 桶排序(不穩定) O(n) O(n) O(n) 基數排序(穩定) O(n) O(n) O(n) 歸併排序(穩定) O(nlogn) O(nlogn) O(nlogn) 快速排序(不穩定)

資料結構與演算法分析 —— 漸進複雜(三個記號)

對於某些問題,一些演算法更適合於用小規模的輸入,而另一些則相反。幸運的是,在評價演算法執行效率時,我們往往可以忽略掉其處理小規模問題時的能力差異,轉而關注其在處理大規模資料時的表現。道理是顯見的,處理大規模的問題時,效率的些許差異都將對實際執行效率產生巨大的影響

資料結構演算法分析排序篇--歸併排序(Merge Sort)常用排序演算法時間複雜比較(附贈記憶方法)

歸併排序的基本思想 歸併排序法是將兩個或以上的有序表合併成一個新的有序表,即把待排序序列分成若干個子序列,每個子序列是有序的。然後再把有序子序列合併為整體有序序列。注意:一定要是有序序列! 歸併排序例項: 合併方法: 設r[i……n]由兩個有序子表r

常用排序演算法的時間複雜空間複雜及特點

一、常用排序演算法的時間複雜度和空間複雜度表格 二、特點 1.歸併排序: (1)n大時好,歸併比較佔用記憶體,記憶體隨n的增大而增大,但卻是效率高且穩定的排序演算法。 (2)歸併排序每次遞迴都要用到一個輔助表,長度與待排序的表長度相同,雖然遞迴次數是O(log2n),但每次

幾種常用排序演算法的思路複雜對比

1、插入排序——直接插入排序、希爾排序 (1)直接插入排序思路:從第1號元素開始,每個元素依次與前面的元素做比較,小的排前面,這樣當比較到最後一 個元 素完即完成排序。 (2)希爾排序思路:     

常用排序演算法以及時間複雜

希爾排序 快速排序 二叉樹排序 氣泡排序 選擇排序 堆排序 #include <iostream.h> #include <conio.h> #include <stdlib.h> #include <time.h>

時間複雜為O(N*logN)的常用排序演算法總結與Java實現

時間複雜度為O(N*logN)的常用排序演算法主要有四個——快速排序、歸併排序、堆排序、希爾排序1.快速排序·基本思想    隨機的在待排序陣列arr中選取一個元素作為標記記為arr[index](有時也直接選擇起始位置),然後在arr中從後至前以下標j尋找比arr[inde

快速排序全面講解(含複雜證明)——即將引出八大排序演算法

全面解析快速排序(包括證明) 1.快速排序簡介: 好看的圖: 快速排序是目前公認的平均狀態下速度最快的一種排序演算法 優點如下: 1.原地排序:空間複雜度為O(1),相對於歸併排序來說,佔用非常小的記憶體便可以實現很高效的排序的效果 2.平均狀態下的時間複雜度始終未O(l

排序算法系列——八大排序演算法對比分析

本系列最後一篇,綜合分析下前面介紹的八種排序演算法的效率,以及各自的適用情況。 下面先看看八種排序演算法的時間複雜度表格: 圖中八種排序被分成了兩組,一組時間複雜度為O(n^2),另一組相對高效些。 下面先對第一組O(n^2)的四種排序演算法進行對比,

python對八大常見排序演算法的總結實現以及時間消耗分析

    昨晚上開始總結了一下常見的幾種排序演算法,由於之前我已經寫了好幾篇排序的演算法的相關博文了現在總結一下的話可以說是很方便的,這裡的目的是為了更加完整詳盡的總結一下這些排序演算法,為了複習基礎的東西,從氣泡排序、直接插入排序、選擇排序、歸併排序、希爾排序、桶排序、堆排

常用排序演算法的python實現效能分析

一年一度的換工作高峰又到了,HR大概每天都塞幾份簡歷過來,基本上一天安排兩個面試的話,當天就只能加班幹活了。趁著面試別人的機會,自己也把一些基礎演算法和一些面試題整了一下,可以階段性的留下些腳印——沒辦法,平時太忙,基本上沒有時間寫部落格。面試測試開發的話,

常用排序演算法時間複雜空間複雜

摘自維基百科: http://zh.wikipedia.org/wiki/%E6%8E%92%E5%BA%8F%E7%AE%97%E6%B3%95#.E7.A8.B3.E5.AE.9A.E6.80.A7 在電腦科學所使用的排序演算法通常被分類為: 計算的時間複雜度(最