1. 程式人生 > >資料結構與演算法之美專欄學習筆記-排序(上)

資料結構與演算法之美專欄學習筆記-排序(上)

排序方法

氣泡排序、插入排序、選擇排序、快速排序、歸併排序、計數排序、基數排序、桶排序。

 

複雜度歸類

氣泡排序、插入排序、選擇排序 O(n^2)

快速排序、歸併排序 O(nlogn)

計數排序、基數排序、桶排序 O(n)

 

 

演算法的執行效率

1. 最好、最壞、平均情況時間複雜度。

2. 時間複雜度的係數、常數和低階。

3. 比較次數,交換(或移動)次數。

 

排序演算法的穩定性

穩定性概念

如果待排序的序列中存在值相等的元素,經過排序之後,相等元素之間原有的先後順序不變。

穩定性重要性

可針對物件的多種屬性進行有優先順序的排序。

排序演算法的記憶體損耗

原地排序演算法:特指空間複雜度是O(1)的排序演算法。


氣泡排序

氣泡排序只會操作相鄰的兩個資料。每次冒泡操作都會對相鄰的兩個元素進行比較,看是否滿足大小關係要求,如果不滿足就讓它倆互換。

穩定性

氣泡排序是穩定的排序演算法。

空間複雜度

氣泡排序是原地排序演算法。

時間複雜度

最好情況:O(n)。

最壞情況:O(n^2)。

平均情況:平均時間複雜度為O(n^2)。

C#程式碼演示

public void BubbleSort(int[] data,int n)
{
    if (n <= 1) return;//長度小於1的陣列直接返回
for(int j = 0; j < n; j++)//遍歷陣列 { Boolean flag = false;//設標誌位 for (int i = 0; i < n-j-1; i++)//遍歷陣列未被排序的部分 { if (data[i] > data[i + 1])//比較元素大小 { int temp = data[i];//交換資料 data[i] = data[i + 1]; data[i
+ 1] = temp; flag = true; } } if (!flag) return;//如果一次冒泡無交換說明全部有序,返回 } }

 

插入排序

插入排序將陣列資料分成已排序區間和未排序區間。初始已排序區間只有一個元素,即陣列第一個元素。

在未排序區間取出一個元素插入到已排序區間的合適位置,直到未排序區間為空。

穩定性

插入排序是穩定的排序演算法。

空間複雜度

插入排序是原地排序演算法。

時間複雜度

1. 最好情況:O(n)。

2. 最壞情況:O(n^2)。

3. 平均情況:O(n^2)。

C#程式碼演示

public void InsertionSort(int[] data,int n)
{
    if (n <= 1) return;
    for(int i = 1; i < n; i++)//遍歷陣列
    {
        int value = data[i];//記錄要進行排序的第i個數組成員
        int j = i - 1;//從第i個數組成員前的成員開始遍歷到頭
        for (; j >= 0; --j)
        {
            if (data[j] > value)//如果其比第i個數組成員大,將其前移
                data[j + 1] = data[j];
            else//否則就結束,因為前面的資料必然是有序的
                break;
        }
        data[j + 1] = value;//在前移結束後停下的位置前插入記錄的資料
    }
}

 

選擇排序

選擇排序將陣列分成已排序區間和未排序區間。初始已排序區間為空。

每次從未排序區間中選出最小的元素插入已排序區間的末尾,直到未排序區間為空。

穩定性

選擇排序不是穩定的排序演算法。

空間複雜度

選擇排序是原地排序演算法。

時間複雜度

都是O(n^2))

C#程式碼演示

public static void SelectionSort(int[] data,int n)
{
    if (n <= 1) return;
    for(int i = 0; i < n; i++)//遍歷陣列
    {
        int temp = data[i];//記錄要排序的陣列成員
        int pos = i;//記錄最終的交換位置
        for(int j = i; j < n; j++)//遍歷陣列未交換的部分,找到最小的成員並記錄其位置
        {
            if (data[j]<data[i])//如果未交換的部分比第i個成員小
            {
                data[i] = data[j];//將其提到前面
                pos = j;//記錄交換的位置
            }
        }
        data[pos] = temp;//互換資料
    }
}

 

思考

氣泡排序和插入排序的時間複雜度相同都是O(n^2),為什麼插入排序比氣泡排序更受歡迎?

因為氣泡排序的交換操作需要執行三次操作。

如果資料儲存在連結串列中,三種排序方法的時間複雜會變成怎樣?

假定只能改變節點位置

氣泡排序,比較次數不變,因為指標,交換資料更加複雜。

插入排序,比較次數不變,但可以直接插入資料,不需要一個個地後移資料。

選擇排序,比較次數不變,因為指標,交換資料更加複雜。