亞馬遜迴應《新世界》燒卡事件 所提建議治標不治本
阿新 • • 發佈:2021-07-22
簡單梳理一下以前學過的排序演算法
氣泡排序
平均時間複雜度:O(n²);穩定
- 比較相鄰元素,如果前面的比後面大,就交換兩個元素
- 每一對相鄰元素做同樣的比較,從開始第一對元素一直比到結尾,一輪結束最後的元素是最大的。
- 除了每輪比較出來的最大元素,對其他元素重複以上操作。
public void bubbleSort(int[] array) { for (int i = 0; i < array.length; i++) { for (int j = 0; j < array.length - 1; j++) { if (array[j + 1] < array[j]) { int temp = array[j]; array[j] = array[j + 1]; array[j + 1] = temp; } } } }
選擇排序
平均時間複雜度:O(n²);不穩定
- 在所有元素中選取最小的元素,放在第一個位置。
- 在剩餘元素裡選取最小的元素,放在第二個位置。
- 以此類推
public void selectionSort(int[] array) { for (int i = 0; i < array.length; i++) { int minIndex = i; for (int j = i; j < array.length; j++) { if (array[j] < array[minIndex]) { minIndex = j; } } int temp = array[minIndex]; array[minIndex] = array[i]; array[i] = temp; } }
插入排序
平均時間複雜度:O(n²);穩定
- 以第一個元素為有序序列,從末尾開始比較,即要插入的元素和已經有序的最大者開始比起。
- 如果比它大則插入後面,否則一直比較,直到找到它該插入的位置。
- 如果遇到的元素和要插入的元素相等,那麼要插入的元素放在相等元素的後面。所以,相等元素的前後順序沒有改變,所以插入排序是穩定的。
public void insertionSort(int[] array) { int current; for (int i = 0; i < array.length - 1; i++) { current = array[i + 1]; int preIndex = i; while (preIndex >= 0 && current < array[preIndex]){ array[preIndex + 1] = array[preIndex]; preIndex--; } array[preIndex + 1] = current; } }
希爾排序
平均時間複雜度:O(nlog₂n);不穩定
希爾排序又叫做最小增量排序,將整個待排序的序列分割成為若干子序列,分別進行插入排序。
- 選擇增量 gap=length/2,這種增量選擇可以用一個序列來表示,{n/2, (n/2)/2, ... 1},稱為增量序列。
- 對每個子序列進行插入排序後,縮小增量繼續以 gap = gap/2 的方式執行。
public void shellSort(int[] array){
int len = array.length;
int temp, gap = len / 2;
while (gap > 0) {
for (int i = gap; i < len; i++) {
temp = array[i];
int preIndex = i - gap;
while (preIndex >= 0 && array[preIndex] > temp) {
array[preIndex + gap] = array[preIndex];
preIndex -= gap;
}
array[preIndex + gap] = temp;
}
gap /= 2;
}
}
歸併排序
分治法的典型應用。始終都是 O(nlogn) 的時間複雜度,代價是需要額外的記憶體空間。
平均時間複雜度:O(nlogn);穩定
- 將長度為 n 的序列分成兩個長度為 n/2 的子序列;
- 分別對子序列採用歸併排序;
- 將兩個排序好的子序列合併成一個有序序列;
public void sort(int[] array) {
//在排序前,先建好一個長度等於原陣列長度的臨時陣列,避免遞迴中頻繁開闢空間
int[] temp = new int[array.length];
sort(array, 0, array.length - 1, temp);
}
public void sort(int[] array, int left, int right, int[] temp) {
if (left < right) {
int mid = (left + right) / 2;
sort(array, left, mid, temp); //左邊歸併排序,使得左子序列有序
sort(array, mid + 1, right, temp);//右邊歸併排序,使得右子序列有序
merge(array, left, mid, right, temp);//將兩個有序子數組合並操作
}
}
public void merge(int[] array, int left, int mid, int right, int[] temp){
int i = left; //左序列指標
int j = mid + 1; //右序列指標
int t = 0; //臨時陣列指標
while (i <= mid && j <= right) {
if (array[i] <= array[j]) {
temp[t++] = array[i++];
} else {
temp[t++] = array[j++];
}
}
while (i <= mid) {//將左邊剩餘元素填充進temp中
temp[t++] = array[i++];
}
while (j <= right) {//將右序列剩餘元素填充進temp中
temp[t++] = array[j++];
}
t = 0;
//將temp中的元素全部拷貝到原陣列中
while (left <= right) {
array[left++] = temp[t++];
}
}
快速排序
平均時間複雜度:O(nlogn);不穩定
- 在序列中選一個基準數(pivot),一般選首位置元素為基準。
- 快排利用兩個指標,分別設為左left,右right,雙向進行。比基準數大的放右邊,比基準數小的放左邊,當left < right 時,遍歷結束。
- 利用遞迴,把比基準小的子序列、比基準大的子序列分別重複上述排序步驟。
public void quickSort(int[] array, int left, int right) {
if (left < right) {
int index = getIndex(array, left, right);
quickSort(array, left, index - 1);
quickSort(array, index + 1, right);
}
}
public int getIndex(int[] array, int left, int right) {
int pivot = array[left];
while (left < right) {
while (left < right && array[right] >= pivot) {
right--;
}
array[left] = array[right];
while (left < right && array[left] <= pivot) {
left++;
}
array[right] = array[left];
}
array[right] = pivot;
return right;
}
public void quickSort(int[] array) {
quickSort(array, 0, array.length - 1);
}
堆排序
有點遺忘,回頭補上
你應當熱愛自由!
作者:Leejk,轉載請註明原文連結:https://www.cnblogs.com/leejk/p/15068383.html