排序【2】選擇排序

選擇排序

算法思想:以升序爲例,在整個區間中找出排序碼最小的元素,如果這個元素不是這組序列中的第一個元素,那麼將它和第一個元素進行交換,使得最小的元素就在第一個位置,然後縮小區間,循環執行上述操作,只到區間中只剩下一個元素。
具體步驟(升序)

  1. 在區間中找到關鍵碼最小的元素。
  2. 如果不是待排序區間的第一個元素,則和帶排序區間第一個元素交換。
  3. 縮小待排序區間。這裏寫圖片描述
    代碼實現:
void ChangeSort(int *array, int size)
{
    assert(array);
    for (int i = 1; i < size; ++i)
    {
        int minindex = i;//未排序的最小元素下標
        int start = i - 1;//未排序區間第一個元素下標
        while (minindex<size)
        {
            if (array[minindex] < array[start])
                swap(array[minindex], array[start]);
            ++minindex;
        }

    }
}

算法性能
時間複雜度:最好的情況是已經有序,交換次數爲0,最壞的情況是逆序,交換次數是n-1,比較次數與關鍵字的初始狀態無關。總的比較次數爲N=n*(n-1)/2,所以時間複雜度爲O(N^2)
空間複雜度:O(1)
穩定性:不穩定


堆排序

基本思想:堆排序就是利用堆這種數據結構實現的一種排序算法,堆是完全二叉樹的一種。堆的特點是:

  1. 最大堆:每一個父節點的值都大於兩個子節點
  2. 最小堆:每一個父節點的值都小於兩個子節點
    堆排序的基本思想就是利用了這種結構,如果我們需要升序:
    1.把所有[a1,a2,a3…an]建成大堆。
    2.把堆頂的元素(即數組中最大的元素和堆中最後一個元素交換),此時分爲兩個區域,一個[a1,a2,an–1]無序區和[an]有序區。
    3.因爲交換了元素,有可能會違反了堆的性質,因此無序區的元素進行調整,滿足堆的性質。
    4.重複步驟2,直到有序區的元素有n-1個。
    這裏寫圖片描述
    代碼實現:
void AdJustDown(int *array, int size, int n)
{
    int parent = n;
    int child = parent*+1;
    while (child<n)
    {
        if ((child + 1 < size) && array[child] < array[child + 1])
        {
            ++child;
        }
        if (array[child] > array[parent])
        {
            swap(array[child], array[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {

            break;
        }
    }
}
void HeapSort(int *array, int size)
{
    assert(array);
    for (int i=(size-2)>>1;i>=0;++i)
    {
        AdJustDown(array,size,i);//創建大堆,將所有數據都重新排序
    }
    for (int i = size - 1; i >= 0; ++i)
    {
        swap(array[0], array[size]);//交換堆頂元素和已序序列第一個元素
        AdJustDown(array, i, 0);//縮小區間,調整堆結構
    }

}

算法性能

  1. 時間複雜度:因爲堆中元素的個數是N,所以堆的高度是logN,那麼比較次數就是2logN,交換的次數是N次,所以平均時間複雜度是O(NlogN)
  2. 空間複雜度:O(1)
  3. 穩定性:不穩定

驗證結果:
這裏寫圖片描述

發佈了46 篇原創文章 · 獲贊 16 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章