本文僅作為個人學(xué)習(xí)排序算法的參考筆記,若想詳細(xì)了解學(xué)習(xí),請前往 http://blog.csdn.net/han_xiaoyang/article/details/12163251
tip:
- 文中會提及穩(wěn)定算法和不穩(wěn)定算法的概念,先貼一下百度的解釋:假定在待排序的記錄序列中,存在多個具有相同的關(guān)鍵字的記錄,若經(jīng)過排序,這些記錄的相對次序保持不變,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,則稱這種排序算法是穩(wěn)定的;否則稱為不穩(wěn)定的。
插入排序算法
- 插入排序(Insertion Sort)的工作原理是通過構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。
- 空間代價O(1)
- 平均時間復(fù)雜度為O(n^2),最好時間復(fù)雜度n-1,最壞時間復(fù)雜度n(n+1)/2
- 穩(wěn)定的排序算法
- 插入排序不適合對于數(shù)據(jù)量比較大的排序應(yīng)用。但是,如果需要排序的數(shù)據(jù)量很小,例如,量級小于千,那么插入排序還是一個不錯的選擇。
void insertionSort(int arr[])
{
for(int i = 1; i < arr.length; i++)
{
int j = i - 1;
int temp = arr[i];
while((j >= 0) && (arr[j] > temp))
{
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
二分插入排序算法
- 二分(折半)插入(Binary insert sort)排序是一種在直接插入排序算法上進(jìn)行小改動的排序算法。其與直接排序算法最大的區(qū)別在于查找插入位置時使用的是二分查找的方式,在速度上有一定提升。
- 穩(wěn)定的排序算法
- 空間代價:O(1)
- 時間代價:插入每個記錄需要O(log i)比較,最多移動i+1次,最少2次。最佳情況O(n log n),最差和平均情況O(n^2)。
- 當(dāng)n較大時,總排序碼比較次數(shù)比直接插入排序的最差情況好得多,但比最好情況要差,所元素初始序列已經(jīng)按排序碼接近有序時,直接插入排序比二分插入排序比較次數(shù)少。二分插入排序元素移動次數(shù)與直接插入排序相同,依賴于元素初始序列。
void BinInsertSort(int arr[])
{
for(int i = 1; i < arr.length; i++)
{
int left = 0;
int right = i - 1;
int temp = arr[i];
while (left <= right)
{
int middle = (left +right) / 2;
if(arr[middle] > temp)
{
right = middle - 1;
}
else
{
left = middle + 1;
}
}
for(int j = i - 1; j >= left; j--)
{
arr[j + 1] = arr[j];
}
arr[left] = temp;
}
}
小結(jié):
- 插入排序:取一個元素,在已排序的元素中一一比較,滿足條件就替換,直至不滿足條件;
- 二分插入排序:取一個元素,在已排序的元素中,找到滿足條件的位置i,讓i + 1往后的元素后退一位,然后將取出的元素插入i位置
希爾排序
- 希爾排序的時間復(fù)雜度與增量序列的選取有關(guān),例如希爾增量時間復(fù)雜度為O(n2),而Hibbard增量的希爾排序的時間復(fù)雜度為O(N(5/4)),但是現(xiàn)今仍然沒有人能找出希爾排序的精確下界。
- 不穩(wěn)定排序
void shellSort(int arr[])
{
int gap = arr.length / 2; //在此增量取數(shù)組長度/2
while(gap > 0)
{
for(int i = 0; i < gap; i++)
{
int j = i + gap;
int temp = arr[j];
while((temp < arr[i]) && (j < arr.length))
{
arr[j] = arr[i];
j += gap;
}
arr[j] = temp;
}
gap /= 2;
}
}
選擇排序
- 選擇排序(Selection sort)是一種簡單直觀的排序算法。工作原理如下:首先在未排序序列中找到最?。ù螅┰兀娣诺脚判蛐蛄械钠鹗嘉恢?,然后,再從剩余未排序元素中繼續(xù)尋找最小(大)元素,然后放到已排序序列的末尾。
- 選擇排序的交換操作介于0和(n-1)次之間
- 選擇排序的比較操作為n(n-1)/2次之間,比較次數(shù)O(n^2)
- 選擇排序的賦值操作介于0和3(n-1)次之間
- 交換次數(shù)O(n),最好情況是,已經(jīng)有序,交換0次;最壞情況是,逆序,交換n-1次
- 交換次數(shù)比冒泡排序少,由于交換所需CPU時間比比較所需的CPU時間多,n值較小時,選擇排序比冒泡排序快
| 復(fù)雜度 |
值 |
| 最差時間復(fù)雜度 |
О(n2) |
| 最優(yōu)時間復(fù)雜度 |
О(n2) |
| 平均時間復(fù)雜度 |
О(n2) |
| 最差空間復(fù)雜度 |
О(n) total, O(1) |
void selectSort(int arr[])
{
int length = arr.length;
for(int i = 0; i < length; i++)
{
int min = arr[i];
int index = i;
int j = i + 1;
while(j < length)
{
if(min > arr[j])
{
min = arr[j];
index = j;
}
j++;
}
arr[index] = arr[i];
arr[i] = min;
}
}
快速排序
- 基本思想:通過一趟排序?qū)⒋庞涗浄指舫瑟毩⒌膬刹糠?,其中一部分記錄的關(guān)鍵字均比另一部分的關(guān)鍵字小,則可分別對這兩部分記錄繼續(xù)進(jìn)行排序
- 復(fù)雜度: 平均狀況下,排序 n 個項目要Ο(n log n)次比較。在最壞狀況下則需要Ο(n^2)次比較
| 復(fù)雜度 |
值 |
| 最差時間復(fù)雜度 |
О(n^2) |
| 最優(yōu)時間復(fù)雜度 |
O(n log n) |
| 平均時間復(fù)雜度 |
O(n log n) |
| 最差空間復(fù)雜度 |
根據(jù)實現(xiàn)的方式不同而不同 |
- 從數(shù)列中挑出一個元素,稱為 "基準(zhǔn)"(pivot);
- 排序數(shù)組,所有元素比基準(zhǔn)值小的擺放在基準(zhǔn)前面,所有元素比基準(zhǔn)值大的擺在基準(zhǔn)的后面(相同的數(shù)可以到任一邊)。在這個分區(qū)退出之后,該基準(zhǔn)就處于數(shù)列的中間位置。這個稱為分區(qū)(partition)操作。
- 遞歸地(recursive)把小于基準(zhǔn)值元素的子數(shù)列和大于基準(zhǔn)值元素的子數(shù)列排序。
function quickSort(first, end, array) {
var key = array[first];//默認(rèn)選擇第一個為pivot
var i = first;
var j = end;
if (first > end) {
while (i < j) {
/**
* 以 23 7 36 8 15 9 為例, 第一遍基準(zhǔn)為23
*/
// 從數(shù)組最右邊開始遍歷, 如果比基準(zhǔn)大, 則比較下一個; 如果比基準(zhǔn)小, 則賦值到基準(zhǔn)的位置
while (array[j] > key && j > i) {
j--;
}
if (i < j) {
array[i++] = array[j];
// 賦值后, 數(shù)組排列為9 7 36 8 15 9 i=1 j=5
// 數(shù)組中有兩個相同的數(shù), 其中賦值到基準(zhǔn)位置的數(shù)才是其正確位置, j位置上的則是可被替換的
}
// 從數(shù)組最左邊開始遍歷, 如果比基準(zhǔn)小, 則比較下一個; 如果比基準(zhǔn)大, 則賦值到j(luò)的位置
while (array[i] < key && j > i) {
i++;
}
if (i < j) {
array[j--] = array[i];
// 賦值后, 數(shù)組排列為9 7 36 8 15 36 i=2 j=4
// 數(shù)組中有兩個相同的數(shù), 其中賦值到j(luò)位置的數(shù)才是其正確位置, i位置上的則是可被替換的
}
array[i] = key;
// 將基準(zhǔn)賦值到i位置 數(shù)組排序為9 7 23 8 15 36
// i=2 j=4 在進(jìn)行一次以23為基準(zhǔn)的循環(huán)
// 得到 9 7 15 8 23 36 保證在23前的數(shù)都比23小, 在23后的數(shù)都比23大. 則以23為基準(zhǔn)的排序結(jié)束, 跳出循環(huán)
}
quickSort(0, i - 1, array);
quickSort(i + 1, array.length - 1, array);
}
}
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。