1. 程式人生 > >九大排序演算法的手寫實現及時空複雜度分析

九大排序演算法的手寫實現及時空複雜度分析

一、氣泡排序 
氣泡排序是一種簡單的排序方法,演算法如下: 
1. 首先將所有待排序的數字放入工作列表中。 
2. 從列表的第一個數字到倒數第二個數字,逐個檢查:若某一位上的數字大於他的下一位,則將它與它的下一位交換。 
3. 重複2號步驟(倒數的數字加1。例如:第一次到倒數第二個數字,第二次到倒數第三個數字,依此類推…),直至再也不能交換。 
程式碼實現如下:

#include <iostream>
using namespace std;
/*交換函式,作用是交換陣列中的兩個元素的位置*/
void swap(int array[],int i,int j)
{
    int
tmp=array[i]; array[i]=array[j]; array[j]=tmp; } /*氣泡排序*/ void BubbleSort(int array[],int n) { for(int i=0;i<n-1;i++) { for(int j=n-1;j>i;j--) { if(array[j]<array[j-1]) swap(array,j,j-1); } } } int main() { int array[5
]={3,1,2,5,4}; BubbleSort(array,5); for(int i=0;i<5;i++) cout<<array[i]<<" "; cout<<endl; return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

最差時間複雜度 O(n²) 
最優時間複雜度 O(n) 
平均時間複雜度 O(n²) 
最差空間複雜度 O(n) total, O(1) auxiliary

二、插入排序 
插入排序也是一種簡單排序方法,演算法如下: 
1. 從第一個元素開始,認為該元素已經是排好序的。 
2. 取下一個元素,在已經排好序的元素序列中從後向前掃描。 
3. 如果已經排好序的序列中元素大於新元素,則將該元素往右移動一個位置。 
4. 重複步驟3,直到已排好序的元素小於或等於新元素。 
5. 在當前位置插入新元素。 
6. 重複步驟2。 
程式碼實現如下:

#include <iostream>
using namespace std;
/*交換函式,作用是交換陣列中的兩個元素的位置*/
void swap(int array[],int i,int j)
{
    int tmp=array[i];
    array[i]=array[j];
    array[j]=tmp;
}
/*插入排序*/
void InsertSort(int array[],int n)
{
    for(int i=1;i<n;i++)
    {
        for(int j=i;j>0;j--)
        {
            if(array[j]>array[j-1])
                swap(array,j,j-1);
            else
                break;
        }
    }
}

int main()
{
    int array[5]={3,1,2,5,4};
    InsertSort(array,5);
    for(int i=0;i<5;i++)
        cout<<array[i]<<"  ";
    cout<<endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

最差時間複雜度 O(n²) 
最優時間複雜度 O(n) 
平均時間複雜度 O(n²) 
最差空間複雜度 O(n) total, O(1) auxiliary

三、選擇排序 
選擇排序的思想如下: 
1. 設陣列記憶體放了n個待排數字,陣列下標從1開始,到n結束。 
2. i=1 
3. 從陣列的第i個元素開始到第n個元素,尋找最小的元素。(具體過程為:先設arr[i]為最小,逐一比較,若遇到比之小的則交換) 
4. 將上一步找到的最小元素和第i位元素交換。 
5. 如果i=n-1演算法結束,否則回到第3步 
程式碼實現如下:

#include <iostream>
using namespace std;
/*交換函式,作用是交換陣列中的兩個元素的位置*/
void swap(int array[],int i,int j)
{
    int tmp=array[i];
    array[i]=array[j];
    array[j]=tmp;
}
/*選擇排序*/
void SelectionSort(int array[],int n)
{
    for(int i=0;i<n-1;i++)
    {
        int smallest=i;
        for(int j=i+1;j<n;j++)
        {
            if(array[smallest]>array[j])
                smallest=j;
        }
        swap(array,i,smallest);
    }
}

int main()
{
    int array[5]={3,1,2,5,4};
    SelectionSort(array,5);
    for(int i=0;i<5;i++)
        cout<<array[i]<<"  ";
    cout<<endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

最差時間複雜度 О(n²) 
最優時間複雜度 О(n²) 
平均時間複雜度 О(n²) 
最差空間複雜度 О(n) total, O(1) auxiliary 
以上三種排序的時間複雜度都是O(n²)。

四、快速排序 
實踐證明,快速排序是所有排序演算法中最高效的一種。它採用了分治的思想:先保證列表的前半部分都小於後半部分,然後分別對前半部分和後半部分排序,這樣整個列表就有序了。 
快速排序的基本演算法是: 
1. 從數列中挑出一個元素,稱為 “基準”(pivot),也叫作支點, 
2. 重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的後面(相同的數可以到任一邊)。在這個分割之後,該基準是它的最後位置。這個稱為分割(partition)操作。 
3. 遞迴地(recursive)把小於基準值元素的子數列和大於基準值元素的子數列排序。 
遞迴的最底部情形,是數列的大小是零或一,也就是永遠都已經被排序好了。雖然一直遞迴下去,但是這個演算法總會結束,因為在每次的迭代(iteration)中,它至少會把一個元素擺到它最後的位置去。 
程式碼實現如下:

#include <iostream>
using namespace std;
/*交換函式,作用是交換陣列中的兩個元素的位置*/
void swap(int array[],int i,int j)
{
    int tmp=array[i];
    array[i]=array[j];
    array[j]=tmp;
}
/*將軸值放到陣列的適當的位置*/
int partition(int array[],int left,int right)
{
    int mid=(left+right)/2;
    int tmp=array[mid];
    swap(array,mid,right);
    int i=left;
    int j=right;
    while(1)
    {
        /*i指標向右移動,直到找到一個大於軸值的值*/
        while(1)
        {
            /*如果i與j相遇則確定軸值位置,將其返回*/
            if(i==j)
            {
                array[i]=tmp;
                return i;
            }
            if(array[i]>tmp)
            {
                array[j]=array[i];
                j--;
                break;
            }
            i++;
        }
        /*j指標向左移動,直到找到一個小於軸值的值*/
        while(1)
        {
            /*如果i與j相遇則確定軸值位置,將其返回*/
            if(i==j)
            {
                array[j]=tmp;
                return j;
            }
            if(array[j]<tmp)
            {
                array[i]=array[j];
                i++;
                break;
            }
            j--;
        }
    }
}
/*快速排序*/
void quickSort(int array[],int left,int right)
{
    if(right<=left)
        return;
    int pivot=partition(array,left,right);
    quickSort(array,left,pivot-1);
    quickSort(array,pivot+1,right);
}

int main()
{
    int array[8]={6,8,7,3,1,2,5,4};
    quickSort(array,0,7);
    for(int i=0;i<8;i++)
        cout<<array[i]<<"  ";
    cout<<endl;
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28