常用的排序演算法主要有以下幾種:
氣泡排序的平均及最壞情況時間複雜度均為o(n2),原理是遍歷若干次要排序的數列,每次遍歷時,它都會從前往後依次的比較相鄰兩個數的大小;如果前者比後者大,則交換它們的位置。c++實現如下:
using namespace std;
void
bubblesort
(vector<
int>
& v)
}}
對於少量元素的排序,插入排序是乙個有效的演算法,且該演算法原址排序插入的數,在任何時候,最多只有其中的常數個數值儲存在外面。插入演算法的平均及最壞情況時間複雜度均為o(n2),**如下:
using namespace std;
void
insertsort
(vector<
int>
& v)
}
快排使用了分治法,將陣列v[p, …, r]分為兩個(可能為空)的子陣列v[p, …, q-1] 和 v[q, …, r],使得v[p, …, q-1] 的元素都小於等於v[q],而v[q]也小於等於a[q+1…r]中的每個元素。再遞迴呼叫快速排序,對子陣列v[p, …, q-1] 和a[q+1…r]進行排序。快速排序的平均時間複雜度為o(nlogn),最壞情況時間複雜度為o(n2),**如下:
using namespace std;
void
quicksort
(vector<
int>
& v,
int l,
int r)
int povit = v[r]
;int j = l-1;
for(
int i=l; i<=r; i++)}
swap
(v[j+1]
, v[r]);
quicksort
(v, l, j)
;quicksort
(v, j+
2, r)
;}
任何乙個元素都可以選來被當做pivot,但其合適與否與影響quicksort的效率。為避免「poivt不夠隨機」帶來的惡化效應,最理想的方式是取整個序列的頭、尾、中三個位置的元素,以其中值作為povit。
歸併排序基於分治演算法,首先分解待排序的n個元素的序列為兩個各具n/2個元素的子串行,再使用歸併排序遞迴地排序兩個子串行,最後合併兩個已排序的子串行成完整的已排序的序列。歸併排序的平均及最壞情況時間複雜度均為o(nlogn),**如下:
using namespace std;
//合併子串行
void
merge
(vector<
int>
& v,
int l,
int q,
int r)
else}}
void
mergesort
(vector<
int>
& v,
int l,
int r)
}
選擇排序的原理較為簡單,即遍歷未排序的陣列,選擇最小(或最大)的數放在已排序陣列的末尾,時間複雜度為o(n2),**如下:
void
selectsort
(vector<
int>
& v)
swap
(v[i]
, v[min]);
}}
堆排序的平均和最壞情況時間複雜度均為o(nlogn),且具有空間原址性。堆排序使用了「堆」這種資料結構進行資訊管理。堆排序使用了最大堆,最大堆的性質是指出來根以外的所有節點i都要滿足:
a [p
aret
n(i)
]>=a
[i
]a[paretn(i)] >= a[i]
a[pare
tn(i
)]>=a
[i]堆排序過程需要乙個函式max_heapify來維護最大堆的性質,序列的最大值在最大堆的根節點,因此迴圈將根節點的值與為排序序列的最後乙個值交換即可到達排序目的,**如下:
void
maxheapify
(vector<
int>
& v,
int i,
int& n)
else
int lagest;
if(l < n && v[l]
> v[i]
) lagest = l;
else lagest = i;
if(r < n && v[r]
> v[lagest]
) lagest = r;
if(lagest != i)
}void
heapsort
(vector<
int>
& v)
}
在上述的幾種演算法中,排序都是依賴於各元素之間的比較,這類演算法也可稱為比較排序。任何比較排序演算法在最壞情況下都要經過ω(nlogn)次比較,因此歸併排序和堆排序是漸進最優的。但是下面將要介紹的具有線性時間複雜度的桶排序不是用比較來確定排序的,因此,下界ω(nlogn)對它是不適用的。
桶排序適用於輸入資料服從均勻分布的排序,它的原理與雜湊表有些類似,它將[0, 1)的區間劃分為n(n為待排序陣列長度)個相同大小的子區間,稱為桶。然後將n個輸入數風別放在各個桶中。應為輸入資料是均勻的,所以一般不會出現很多數落在同乙個桶中的情況。輸出是先對每個桶中的數進行排序,然後遍歷每個桶,按照次序把各個桶中的元素列出來即可。**如下:
struct listnode};
void
bucketsort
(vector<
int>
& v)
max++
;for
(int i=
0; i++i)
else
else}if
(temp4)
else}}
for(
int i=
0; i++i)
int j=0;
for(
int i=
0; i++i)
}}
即使輸入資料不服從均勻分布,只要輸入資料滿足下列性質:只要所有桶的大小的平方和與總的元素呈線性關係。那麼桶排序依然可以在o(n)的時間內完成。
當輸入陣列的最大值不大時,可用以下方法:
void
bucketsort_2
(vector<
int>
& v)
vector<
int>
tmp(max+1,
0);for
(int i=
0; i++i)
int j=0;
for(
int i=
0; i++i)
}}
最後再寫一下c++ stl裡的sort函式,sort函式適用物件其實不多,因為關係型容器擁有自動排序功能,底層採用rb-tree,所以不需要用到sort演算法,序列式容器中的stack、queue和priority-queue都有特定的出入口,不允許使用者對元素排序,所以還剩下vector和deque可以用sort函式。
上面講了七種排序演算法,sort函式用到了其中的插入排序,快速排序和堆排序。當輸入序列長度n<=16時,採用插入排序,大於16則採用快速排序,當快排迴圈深度大於2logn時,改用堆排序。
常用的排序演算法
排序方式 插入排序 直接插入排序 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 氣泡排序演算法的運作如下 從後往前 比較相鄰的元素。如果第乙個比第二個大,就交換他們兩個。對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。針對所有的元素重複以上的步驟,除了最後乙個。持續每次對越來越少的元素重複上...