各排序演算法總結

2021-07-04 19:55:27 字數 3973 閱讀 7846

下面先來介紹內部排序:

內部排序主要有八大排序演算法:氣泡排序,快速排序,直接插入排序,希爾排序,簡單選擇排序,堆排序,歸併排序,基數排序。

以下討論均預設為公升序排序。

氣泡排序:第一次排序,從第乙個元素到第n - 1個,依次比較與下一元素的大小,若比下一元素大則交換兩元素位置。每次排序確定乙個最大值。這樣依次比較,第i次排序時,從第乙個元素比較到第n - i 個。直到排序n - 1次結束。

氣泡排序的時間複雜度是o(n2),空間負責度是o(1).

演算法實現如下:

void bubblesort(int *a, int

len)

}}

快速排序:快速排序是冒泡的深度改進版,其思想是:首先,選擇乙個元素作為標準,遍歷整個陣列與其進行比較,把所有比它小的元素移動到其左邊,比它大的元素移動到其右邊。然後再分別對其左右兩邊的元素進行同樣的操作,直到整個序列有序。

快速排序的時間複雜度是o(nlogn),空間複雜度是o(nlogn).

演算法實現如下:

/**遞迴結束條件,序列中只有乙個值即left == right時結束

每次迴圈,只要begin還沒有等於end,則begin都是乙個哨兵,且其值大於key,而且已經和end交換過。

判斷條件有begin

< end是為了防止begin和end錯開導致begin > end,而且保證最後begin是和end重合的

重合點就是key的最終位置。

**/void quicksort(int *s, int low, int high)

s[begin] = key;

quicksort(s, low, begin - 1);

quicksort(s, begin+1, high);

}}

直接插入排序:直接插入排序是,首先把序列的第乙個元素當成有序的,每次排序都從後面序列中取出第乙個元素並按順序插入前面的有序序列中。迴圈執行,直到後面子串行為空,待排序列全部有序為止。

直接插入排序的時間複雜度是o(n2),空間複雜度是o(1).

其演算法實現如下:

void insertsort(int *s, int

len)

s[j + 1] = key;

}}

希爾排序:希爾排序是1959 年由d.l.shell 提出來的,相對直接插入排序有較大的改進。希爾排序又叫縮小增量排序。

希爾排序的思想是:

為排序設定乙個增量,按增量把待排序列分成幾個子串行,相隔距離長度為增量整數倍的是乙個子串行。

分別對每個子串行進行直接插入排序。

縮小增量,重複第1、2步。直到增量為1時,排序完成。

其演算法實現如下:

void shellsort(int *s, int

len, int dk)

s[pre + dk] = key;}}

}}

簡單選擇排序:簡單選擇排序的思想是,把待排序列看作兩個部分,乙個是已排有序部分,乙個是待排無序部分。開始時,有序部分為空,整個待排序列都是無序部分。每次排序從待排無序部分選擇乙個最小值放入有序部分的最後,知道所有元素都進入有序部分,排序結束。

簡單選擇排序的時間複雜度是o(n2),空間複雜度是o(1).

其**實現如下:

void ******selectsort(int *s, int len)

swap(s[i], s[min]);

}}

堆排序:

在介紹堆排序之前,要首先介紹一下堆的概念。

堆是乙個完全二叉樹,其具有以下特點:

父結點的鍵值總是大於或等於(小於或等於)任何乙個子節點的鍵值。

每個結點的左子樹和右子樹都是乙個二叉堆(都是最大堆或最小堆)。

當父結點的鍵值總是大於或等於任何乙個子節點的鍵值時為大根堆。當父結點的鍵值總是小於或等於任何乙個子節點的鍵值時為小根堆。

堆排序的思想是利用堆的有序性,對待排序列進行排序。以大根堆為例,其思想是,

把整個待排序列看作乙個待排序序列和乙個已排序序列,把待排序序列整理為乙個大根堆。(剛開始整個序列都是待排序序列)

每次把堆頂元素和堆尾元素交換,每次都是取堆的最大元素放到堆的末尾。則堆頂元素進入已排序序列。

然後把剩下的元素重新整理成大根堆,重複第二步。直到堆裡只剩乙個元素,則排序結束。

堆排序比簡單選擇排序的優越之處在於:雖然都是選擇排序,但選擇排序每次選擇都要做o(n)次比較,而堆排序是通過堆進行選擇,當大根堆建立之後,每次交換元素之後,堆的調整只需要o(logn)的時間複雜度,而簡單選擇需要o(n)次比較。

所以堆排序的時間複雜度是o(nlogn),空間複雜度是o(1).

其演算法實現如下:

void adjustheap(int *s, int len)

if(max == j) break;}}

}void heapsort(int *s, int len)

}

歸併排序:歸併排序是首先把待排序列中每乙個元素看成乙個有序的序列,然後把相鄰的有序序列成對進行歸併排序,得到n/2個有序序列。再對他們進行相鄰成對的歸併排序,得到n/4個有序序列,如此反覆歸併,直到真個序列有序。

歸併排序中,把長度為n的序列分成n份小序列需要logn步,每步的歸併時間複雜度為o(n),所以整個排序的時間複雜度為o(nlogn),由於每次歸併都需要乙個陣列存放相鄰序列合併後的元素,在全域性變數定義乙個長度為n的陣列,作為輔助空間。所以空間複雜度為o(n).

其演算法的**實現如下:

//int *s是待排序列,int *ns是輔助空間。兩者長度相同

void merge(int *s, int *ns, int begin, int mid, int end)

else

}if(first > mid)

if(sec > end)

for(int j = begin; j <= end; j++)

}void mergesort(int *s, int *ns, int begin, int end)

}

基數排序:(以十進位制的整型為例)基數排序依次根據每個位上的數字,從低位到高位進行排序。這樣,在低位排完序之後,高位一樣的數字在同一桶內已經有序了。具體演算法步驟如下:

分配,從個位開始,根據位上的數值,把元素分配到(0-9)的其中乙個桶中。

收集,把上次排完序的元素,按桶的順序再複製回陣列中。

重複1,2步驟,直到分配到最高位。

基數排序,每次都是乙個桶排序。基數排序的時間複雜度是o(dn),空間複雜度是o(mn).其中d是元素的最高位數,m是桶的數量,n是待排序列的元素數。

基數排序和桶排序都不是比較排序,其時間複雜度不受下限nlogn限制,當待排元素均勻的分布在每個區間時,比較適合使用桶排序。

其演算法的**實現如下:

int getnuminpos(int num, int

pos)

res = (num/key)%10;

return res;

}int numofrules(int

*s, int len)

if(num > maxnum) maxnum = num;

}return maxnum;

}void radixsort(int

*s, int len)

intindex = 0; //收集

for(int k = 0; k < 10; ++k)}}

}

各排序演算法總結及實現

1.插入排序 insertsort 插入排序通過把序列中的值插入乙個已經排序好的序列中,直到該序列的結束。插入排序是對氣泡排序的改進。它比氣泡排序快2倍。適用於資料在1000一下的場合下使用插入排序,或者重複排序不超過200資料項的序列。遍歷陣列,遍歷到i時,a0,a1 ai 1是已經排好序的,取出...

各排序演算法對比

比較名稱 時間複雜度 空間複雜度 是否穩定 是否與序列初始狀態有關 適用情況 儲存結構 備註直接插入排序 最好o n 平均o n 2 最壞o n 2 o 1 是是 n較小 小於等於50 初始狀態基本有序,順序儲存 鏈式儲存 折半插入排序 o n 2 o 1 是比較次數無關 移動次數有關 順序儲存 僅...

各排序演算法效能分析

插入排序 最壞時間始n 2 快速排序和插入排序的區別是 插入排序始將關鍵字插入已排序的子串行中,而快速排序始 對整個檔案,把基準關鍵字放到正確的位置上。快排最壞時間依然是n 2,平均時間始nlgn。在堆排序 的過程中只需乙個輔助空間 所以空間 複雜度為 0 1 堆排序的時間複雜度為 nlgn 由於堆...