幾種常見排序演算法總結
插入排序
選擇排序
快速排序
堆排序
希爾排序
歸併排序
穩定性
時間、空間複雜度
一、插入排序(insertion sort)
實際執行時間,更多地取決於輸入序列所含逆序對的總數
template <typename T> void List <T>:: insertionSort( Posi(T) p, int n){
for(int r=0;r<n;r++){
insertAfter(search(p->data,r,p),p->data);//查詢+插入
p=p->succ; remove(p->pred);
}
}
效能分析:O(n)
二、選擇排序(selection sort)
template <typename T> void List <T> ::selectionSort(Posi(T) p, int n){
Posi(T) head =p->pred; Posi(T) tail =p; //待排序區間(head,tail)
for(int i=0; i<n; i++) tail=tail->succ; //head/tail可能是頭/尾哨兵
while(1<n){
//反覆從(非平凡的)待排序區間找出最大者,並移至有序區間前段
insertBefore(tail, remove(selectMax(head->succ,n)));
tail=tail->red; n- -;//待排序區間、有序區間的範圍,均同步更新
}
}
當selectMax()複雜度為theta(n)時 ,總體複雜度為theta(n^2) ,儘管如此,元素移動操作遠遠少於bubble sort,複雜度主要來自於比較操作 ,但是我們可以將selectMax()的複雜度降低為theta(log n)
三、快速排序(Quicksort)
快速排序是一種常用的演算法,它利用了分治策略(Divide and Conquer)。雖然它在最壞的情況下可能達到O(n^2)的時間複雜度,但是在平均的情況下,它一般都是非常有效的,所以是一種實用的演算法。
演算法思路:
選出一個軸點P,令P的左側元素均小於P點的元素,右側均大於P點的元素
虛擬碼:
quickSort(arr[],lo,hi){
if(lo<hi){
p=partition(arr,lo,hi);
quickSort(arr,lo,pi-1);
quickSort(arr,pi+1,hi);
}
}
最壞情況下時間複雜度:O(n^2)
最好情況下時間複雜度:O(n*lg n)
四、堆排序(heap sort)
演算法思路:
建堆過程即為排序過程。
堆通常以陣列形式表現
Representation | Explanation |
---|---|
Arr[(2*i)+1] | Returns the left child node |
Arr[(2*i)+2] | Returns the right child node |
Arr[(i-1)/2] | Returns the parent node |
class Heap{
public:
inline int left(int idx){
return (idx<<1)+1;
}
inline int right(int idx){
return (idx<<1)+2;
}
void max_heapify(vector<int>& nums, int idx){
int largest =idx;
int l =left(idx), r =right(idx);
if(l<heap_size && nums[l]>nums[largest]) largest=l;
if(l<heap_size && nums[r]>nums[largest]) largest=r;
if(largest!=idx) {
swap(nums[idx],nums[largest]);
max_heapify(nums,largest);
}
}
void build_max_heap(vector<int> & nums){
heap_size=nums.size();
for(int i=(heap_size>>1)-1;i>=0;i--)
max_heapify(nums,i);
}
private:
int heap_size;
}
排序時間複雜度為O(n*lg n)
五、希爾排序(shell sort)
將整個序列看作一個矩陣,逐列w-sorting
遞減增量 diminishing increment
由粗到細:重排矩陣,使其更窄,再次逐列排序w-ordered
逐步求精:如此往復,直至矩陣變成一列1-sorting
步長序列 step sequence:由各矩陣寬度構成的逆序列
優劣
1.不需要大量的輔助空間,和歸併排序一樣容易實現
2.希爾排序的時間複雜度與增量序列的選取有關,例如希爾增量時間複雜度為O(n^2),而Hibbard增量的希爾排序的時間複雜度為O(n^(3/2)),希爾排序時間複雜度的下界是n*log2n
3.希爾排序沒有快速排序演算法快,因此中等大小規模表現良好,對規模非常大的資料排序不是最優選擇
希爾演算法在最壞情況下和平均情況下執行效率相差不是很多,而快速排序在最壞情況下的執行效率會非常差。
void shellsort(int v[],int n)
{
int gap,i,j,temp;
for (gap = n/2; gap > 0; gap /= 2)
{
for(i = gap; i < n; i++)
for(j = i-gap; j>=0 && v[j]>v[j+gap]; j -= gap)
{
temp = v[j];
v[j] = v[j+gap];
v[j+gap] = temp;
}
}
}
六、歸併排序(merge sort)
歸併排序(merge sort)
歸併排序利用了分治(divide-and-conquer)的思想。
演算法思路如下:
MergeSort(arr[],l,r)
If(r>l):
1. 找到中點,將陣列一分為二:mi=(l+r)/2
2. 對第一個部分進行歸併排序:mergeSort(arr,l,m)
3. 對第二部分進行歸併排序:mergeSort(arr,m+1,r)
4. 將上面兩個排好序的序列融合:merge(arr,l,m,r)
效能分析:
1.是穩定的排序演算法相關文章
- 幾種常見的排序演算法總結排序演算法
- 常見排序演算法總結排序演算法
- 35.幾種常見的排序演算法排序演算法
- python3實現幾種常見的排序演算法Python排序演算法
- 總結幾種常見的垂直居中的佈局
- 10種python常見的排序演算法!Python排序演算法
- 常見排序演算法排序演算法
- 幾種常見的JS遞迴演算法JS遞迴演算法
- js 常見四種排序JS排序
- python實現常見的五種排序演算法Python排序演算法
- 幾種常見的Python資料結構Python資料結構
- 常見壓縮演算法總結演算法
- 四種常見NLP框架使用總結框架
- 6種常見的地標識別演算法整理和總結演算法
- 常見的三種排序演算法(選擇,冒泡,計數)排序演算法
- 常見的排序演算法 (下)排序演算法
- 幾種常見的NO SQL DBSQL
- Vim常見模式有幾種?模式
- react常見幾種事件宣告React事件
- Java常見排序演算法之插入排序Java排序演算法
- 幾種常用的排序演算法排序演算法
- 【Java資料結構與演算法筆記(一)】常見排序演算法及面試考點總結Java資料結構演算法筆記排序面試
- 演算法之常見排序演算法-氣泡排序、歸併排序、快速排序演算法排序
- 用 Java 實現常見的 8 種內部排序演算法Java排序演算法
- 常見的排序演算法分析(一)排序演算法
- iOS常見的幾種加密方法iOS加密
- 幾種常見的CSS佈局CSS
- 幾種經典的排序演算法排序演算法
- 七種常見的陣列排序演算法整理(C語言版本)陣列排序演算法C語言
- 六種排序演算法的JavaScript實現以及總結排序演算法JavaScript
- PHP 常見4種排序 氣泡排序、選擇排序、插入排序、快速排序PHP排序
- 總結幾種常見的/需要注意到的雲伺服器安全策略伺服器
- golang 常見疑惑總結Golang
- python常見漏洞總結Python
- 常見演算法 PHP 實現 -- 堆排序演算法PHP排序
- 常見排序演算法及複雜度排序演算法複雜度
- Javascript常見排序演算法的筆記JavaScript排序演算法筆記
- 排序演算法全總結排序演算法