常用的排序演算法

2021-09-24 01:56:43 字數 4688 閱讀 5127

c++中幾種常用的排序演算法的最好和最壞的情況:

1 直接插入排序:比較次數 最少n-1次;最多(n-1)(n+2)/2

移動次數 最少0; 最多(n-1)(n+4)/2

使用乙個輔助儲存空間,是穩定的排序;

2 折半插入排序:比較次數 最少與最多同,都是n*log2n(其中2為底,下邊表示同),

移動次數 最少0,最多時間複雜度為o(n2);(n的平方,以下也如此表示);

使用乙個輔助儲存空間,是穩定的排序;

3 氣泡排序: 比較最少為:n-1次,最多時間複雜度表示為o(n2);

移動次數最少為0,最多時間複雜度表示為o(n2);

使用乙個輔存空間,是穩定的排序;

4 簡單選擇排序: 比較次數沒有多少之分,均是n(n-1)/2;

移動次數最少為0,最多為3(n-1);

使用乙個輔存空間,是穩定的排序;

5 快速排序:比較和移動次數最少時間複雜度表示為o(n*log2n);

比較和移動次數最多的時間複雜度表示為o(n2);

使用的輔助儲存空間最少為log2n,最多為n的平方;是不穩定的排序;

6 堆排序: 比較和移動次數沒有好壞之分,都是o(n*log2n);

使用乙個輔存空間,是不穩定的排序;

7 2-路歸併排序:比較和移動次數沒有好壞之分,都是o(n*log2n);

需要n個輔助儲存空間,是穩定的排序;

其具體實現演算法:

氣泡排序 (bubble sort)

氣泡排序是最簡單粗暴的排序方法之一。它的原理很簡單,每次從左到右兩兩比較,把大的交換到後面,每次可以確保將前m個元素的最大值移動到最右邊。

步驟從左開始比較相鄰的兩個元素x和y,如果 x > y 就交換兩者

執行比較和交換,直到到達陣列的最後乙個元素

重複執行1和2,直到執行n次,也就是n個最大元素都排到了最後

void bubble_sort(vector&nums)}}

}

交換的那一步可以不借助temp,方法是

nums[j] += nums[j + 1];

nums[j + 1] = num[j] - nums[j + 1];

nums[j] -= num[j + 1];

複雜度分析

由於我們要重複執行n次冒泡,每次冒泡要執行n次比較(實際是1到n的等差數列,也就是(a1 + an) * n / 2),也就是 o(n^2)。 空間複雜度是o(n)。

2. 插入排序(insertion sort)

插入排序的原理是從左到右,把選出的乙個數和前面的數進行比較,找到最適合它的位置放入,使前面部分有序。

步驟從左開始,選出當前位置的數x,和它之前的數y比較,如果x < y則交換兩者

對x之前的數都執行1步驟,直到前面的數字都有序

選擇有序部分後乙個數字,插入到前面有序部分,直到沒有數字可選擇

void insert_sort(vector&nums)}}

}

複雜度分析

因為要選擇n次,而且插入時最壞要比較n次,所以時間複雜度同樣是o(n^2)。空間複雜度是o(n)。

3. 選擇排序(selection sort)

選擇排序的原理是,每次都從亂序陣列中找到最大(最小)值,放到當前亂序陣列頭部,最終使陣列有序。

步驟從左開始,選擇後面元素中最小值,和最左元素交換

從當前已交換位置往後執行,直到最後乙個元素

void selection_sort(vector&nums)

}int temp = nums[i];

nums[i] = nums[min];

nums[min] = temp;

}}

複雜度分析

每次要找一遍最小值,最壞情況下找n次,這樣的過程要執行n次,所以時間複雜度還是o(n^2)。空間複雜度是o(n)。

4. 希爾排序(shell sort)

希爾排序從名字上看不出來特點,因為它是以發明者命名的。它的另乙個名字是「遞減增量排序演算法「。這個演算法可以看作是插入排序的優化版,因為插入排序需要一位一位比較,然後放置到正確位置。為了提公升比較的跨度,希爾排序將陣列按照一定步長分成幾個子陣列進行排序,通過逐漸減短步長來完成最終排序。

例子例如 [10, 80, 70, 100, 90, 30, 20] 如果我們按照一次減一半的步長來算, 這個陣列第一次排序時以3為步長,子陣列是:

10 80 70 90 30 20 100

這裡其實按照列劃分的4個子陣列,排序後結果為

10 30 20 90 80 70 100

也就是 [10, 30 20 90 80 70 100]

然後再以1為步長生成子陣列

10 30 20 …

這個時候就是一縱列了,也就是說最後一定是以乙個陣列來排序的。

步驟計算當前步長,按步長劃分子陣列

子陣列內插入排序

步長除以2後繼續12兩步,直到步長最後變成1

void shell_sort(vector&nums)

nums[j + gap] = temp;}}

}

複雜度分析

希爾排序的時間複雜度受步長的影響,具體分析在維基百科。

5. 歸併排序(merge sort)

歸併排序是採用分治法(divide and conquer)的乙個典型例子。這個排序的特點是把乙個陣列打散成小陣列,然後再把小陣列拼湊再排序,直到最終陣列有序。

步驟把當前陣列分化成n個單位為1的子陣列,然後兩兩比較合併成單位為2的n/2個子陣列

繼續進行這個過程,按照2的倍數進行子陣列的比較合併,直到最終陣列有序

void merge_array(vector&nums, int b, int m, int e, vector&temp)

void merge_sort(vector&nums, int b, int e, vector&temp)

}

這個實現中加了乙個temp,是和原陣列一樣大的乙個空間,用來臨時存放排序後的子陣列的。

複雜度分析

在merge_array過程中,實際的操作是當前兩個子陣列的長度,即2m。又因為打散陣列是二分的,最終迴圈執行數是logn。所以這個演算法最終時間複雜度是o(nlogn),空間複雜度是o(n)。

6. 快速排序(quick sort)

快速排序也是利用分治法實現的乙個排序演算法。快速排序和歸併排序不同,它不是一半一半的分子陣列,而是選擇乙個基準數,把比這個數小的挪到左邊,把比這個數大的移到右邊。然後不斷對左右兩部分也執行相同步驟,直到整個陣列有序。

步驟用乙個基準數將陣列分成兩個子陣列

將大於基準數的移到右邊,小於的移到左邊

遞迴的對子陣列重複執行1,2,直到整個陣列有序

void quick_sort(vector&nums, int b, int e, vector&temp)

temp[lb] = nums[m];

for (int i = b; i < e; i++)

nums[i] = temp[i];

quick_sort(nums, b, lb, temp);

quick_sort(nums, lb + 1, e, temp);

}}//解法2: 不需要輔助空間

void quick_sort(vector&nums, int b, int e)

swap(nums[b], nums[lb]);

quick_sort(nums, b, lb);

quick_sort(nums, lb + 1, e);

}}

複雜度分析

快速排序也是乙個不穩定排序,時間複雜度看維基百科。空間複雜度是o(n)。

7. 堆排序(heap sort)

堆排序經常用於求乙個陣列中最大k個元素時。因為堆實際上是乙個完全二叉樹,所以用它可以用一維陣列來表示。因為最大堆的第一位總為當前堆中最大值,所以每次將最大值移除後,調整堆即可獲得下乙個最大值,通過一遍一遍執行這個過程就可以得到前k大元素,或者使堆有序。

在了解演算法之前,首先了解在一維陣列中節點的下標:

i節點的父節點 parent(i) = floor((i-1)/2)

i節點的左子節點 left(i) = 2i + 1

i節點的右子節點 right(i) = 2i + 2

步驟構造最大堆(build max heap):首先將當前元素放入最大堆下乙個位置,然後將此元素依次和它的父節點比較,如果大於父節點就和父節點交換,直到比較到根節點。重複執行到最後乙個元素。

最大堆調整(max heapify):調整最大堆即將根節點移除後重新整理堆。整理方法為將根節點和最後乙個節點交換,然後把堆看做n-1長度,將當前根節點逐步移動到其應該在的位置。

堆排序(heapsort):重複執行2,直到所有根節點都已移除。

void heap_sort(vector&nums)

for (int i = n - 1; i > 0; i--)

}void max_heapify(vector&nums, int beg, int end)

if (nums[curr] < nums[child]) else

}}

複雜度分析

堆執行一次調整需要o(logn)的時間,在排序過程中需要遍歷所有元素執行堆調整,所以最終時間複雜度是o(nlogn)。空間複雜度是o(n)。

常用的排序演算法

排序方式 插入排序 直接插入排序 shell排序 選擇排序 直接選擇排序 堆排序交換排序 氣泡排序 快速排序 歸併排序 分配和索引排序 基數排序 桶式排序 include using namespace std 直接插入排序 arr為待排陣列,n為陣列長度 void insertsort int a...

常用的排序演算法

1.氣泡排序 private static void bubblesort int a 列印氣泡排序的結果 for int i 0 i2.快速排序 public class quicksort qs.data data qs.sort 0,qs.data.length 1 qs.display 3....

常用的排序演算法

1.氣泡排序 時間複雜度 o n 2 氣泡排序演算法的運作如下 從後往前 比較相鄰的元素。如果第乙個比第二個大,就交換他們兩個。對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。針對所有的元素重複以上的步驟,除了最後乙個。持續每次對越來越少的元素重複上...