演算法基礎 --- 十大排序
三大基礎排序
1.氣泡排序
1.比較相鄰的兩個元素,如果前一個比後一個大,則交換位置。
2.第一輪的時候最後一個元素應該是最大的一個。
3.按照步驟一的方法進行相鄰兩個元素的比較,這個時候由於最後一個元素已經是最大的了,所以最後一個元素不用比較。
function bubbleSort(arr) {
for(let i=0;i<arr.length-1;i++){
for(let j=0;j<arr.length-1-i;j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
}
}
}
}
複雜度分析
- 時間複雜度 O(n^2)
第一趟a1&a2、a2&a3、…an-2&an-1、an-1&an:共n-1次比較
第二趟a1&a2、a2&a3、…an-2&an-1:共n-2次比較
…
第n-1趟a1與a2比較:共一次比較
1+2+3+......+n-1 = 1/2(n-1)^2
- 空間複雜度 O(1)
動態圖
2.選擇排序
首先在未排序序列中找到最小元素,存放到排序序列的起始位置,
然後,再從剩餘未排序元素中繼續尋找最小元素,然後放到已排序序列的末尾。
以此類推,直到所有元素均排序完畢。
function selectSort(arr) {
let minIndex;
for(let i=0;i<arr.length-1;i++){
minIndex = i;
for(let j=i+1;j<arr.length;j++){
if(arr[j] < arr[minIndex]){
minIndex = j;
}
}
swap(arr, i, minIndex);
}
}
複雜度分析
- 時間複雜度
第一趟a2&a1、a3&a1、…an-1&a1、an&a1:共n-1次比較
第二趟a3&a2、a4&a2、…an-1&a2、an&a2:共n-2次比較
…
第n-1趟an與an-1比較:共一次比較
1+2+3+......+n-1 = 1/2(n-1)^2
- 空間複雜度 O(1)
動態圖
3.插入排序
從第一個元素開始,該元素可以認為已經被排序
2.取出下一個元素,在已經排序的元素序列中從後向前掃描
3.如果該元素(已排序)大於新元素,將該元素移到下一位置
4.重複步驟3,直到找到已排序的元素小於或者等於新元素的位置
5.將新元素插入到下一位置中
6.重複步驟2
function insertSort(arr) {
let index;
for(let i=0;i<arr.length-1;i++){
index = i;
while(index >= 0 && arr[index] > arr[index+1]){
swap(arr, index, index+1);
index--;
}
}
}
複雜度分析
- 時間複雜度
最好情況(arr正有序): a1&a2、a2&a3、an-1&an:共n次比較 O(n)
最壞情況(arr逆有序): O(n^2)
第一趟a2&a1:共1次比較
第二趟a3&a2、a3&a1:共2次比較
…
第n-1趟an&an-1… an&a1:共n-1次比較
1+2+3+......+n-1 = 1/2(n-1)^2
- 空間複雜度 O(1)
動態圖
三大基礎排序中,冒泡和選擇只具有教學意義,實際開發中並不使用。
三大進階排序
1.歸併排序
歸併排序是建立在歸併操作的一種有效的排序演算法,該演算法是採用分治法的一個非常典型的應用。歸併排序是一種穩定的排序演算法,將已有序的子序列合併,等到一個完全有序的序列,即先使每個子序列有序,再使子序列段有序,若將兩個有序表合併成一個有序表,稱作2路合併
function mergeSort(arr, left, right) {
if(arguments.length === 1){
mergeSort(arr, 0, arr.length-1);
return;
}
if(left === right) return;
let mid = parseInt( (left + right) / 2);
mergeSort(arr, left, mid);
mergeSort(arr, mid+1, right);
merge(arr, left, mid, right);
}
function merge(arr, left, mid, right) {
let tmp = new Array(right-left+1),
index = 0,
p1 = left,
p2 = mid+1;
while(p1 <= mid && p2 <= right) {
tmp[index++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];
}
while(p1 <= mid) {
tmp[index++] = arr[p1++];
}
while(p2 <= right) {
tmp[index++] = arr[p2++];
}
for(let i=0; i<tmp.length; i++) {
arr[left+i] = tmp[i];
}
}
- 時間複雜度
T(n) = T(n/2) * 2 + O(n)
=> O(nlogn)
- 空間複雜度:O(n)
動態圖
2.快速排序
快速排序的基本思想是:通過一趟排序將待排記錄分割成獨立的兩部分,其中一部分記錄關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序
function quickSort(arr, left, right) {
if(arguments.length === 1){
quickSort(arr, 0, arr.length-1);
return;
}
if(left >= right) return;
let target = arr[parseInt((left+right)/2)],
less = left-1,
more = right+1,
index = left;
while(index < more) {
if( arr[index] < target) {
swap(arr, ++less, index++);
} else if( arr[index] > target ) {
swap(arr, --more, index);
} else {
index++;
}
}
quickSort(arr, left, less);
quickSort(arr, more, right);
}
- 時間複雜度
T(n) = T(n/2) * 2 + O(n)
=> O(nlogn)
- 空間複雜度:O(logn)
動態圖
3.堆排序
將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無序區;
將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];
由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整為新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成。
function heapSort(array) {
let length = array.length;
buildMaxHeap(array);
for (let j = length - 1; j >= 1; j--) {
swap(array, 0, j);
heap(array, 0, --length);
}
}
function buildMaxHeap(array){
let length = array.length;
for (let i = parseInt(length / 2) - 1; i >= 0; i--) {
heap(array, i, length);
}
}
function heap(array, x, length) {
let l = 2 * x + 1, r = 2 * x + 2, largest = x;
if (l < length && array[l] > array[largest]) {
largest = l;
}
if (r < length && array[r] > array[largest]) {
largest = r;
}
if (largest != x) {
swap(array, x, largest);
heap(array, largest, length);
}
}
動態圖
希爾排序,三大計數排序(計數排序、桶排序、基數排序)並不常用,這裡不做討論
相關文章
- 《資料結構與演算法》之十大基礎排序演算法資料結構演算法排序
- 演算法基礎:排序演算法:選擇排序演算法排序
- 基礎演算法之排序演算法演算法排序
- 夯實基礎:排序演算法之堆排序排序演算法
- 演算法學習 - 基礎排序演算法演算法排序
- 經典十大排序演算法(含升序降序,基數排序含負數排序)排序演算法
- 十大排序演算法排序演算法
- PHP基礎演算法之快速排序法PHP演算法排序
- 基礎演算法系列 之希爾排序演算法排序
- 老生常談之 PHP 基礎排序演算法PHP排序演算法
- 資料結構與演算法 基礎排序資料結構演算法排序
- PHP基礎演算法之選擇排序法PHP演算法排序
- PHP基礎演算法之氣泡排序法PHP演算法排序
- 基礎排序演算法詳解與優化排序演算法優化
- JS演算法——十大排序演算法JS演算法排序
- 十大經典排序演算法之氣泡排序排序演算法
- 資料結構和演算法面試題系列—排序演算法之基礎排序資料結構演算法面試題排序
- 排序演算法__基數排序排序演算法
- 2018年第七週-基礎的排序方法(三種基礎排序演算法簡介)排序演算法
- 十大排序演算法詳解排序演算法
- 演算法與資料結構之基礎排序演算法演算法資料結構排序
- 演算法與資料結構基礎 - 排序(Sort)演算法資料結構排序
- Android技能樹 — 排序演算法基礎小結Android排序演算法
- 十大排序演算法Java實現排序演算法Java
- java基礎 排序2Java排序
- 演算法資料結構 | 圖論基礎演算法——拓撲排序演算法資料結構圖論排序
- 【演算法】基數排序演算法排序
- C#實現——十大排序演算法之選擇排序C#排序演算法
- 十大經典排序演算法動畫與解析排序演算法動畫
- Python十大演算法之氣泡排序Python演算法排序
- 十大經典排序演算法(動圖演示)排序演算法
- 演算法基礎之8大排序演算法最優解-必讀演算法排序
- Java基礎系列—List排序Java排序
- JAVA基礎--氣泡排序Java排序
- 【資料結構基礎應用】【查詢和排序演算法】資料結構排序演算法
- 十大排序演算法全面解析 - Java實現排序演算法Java
- 十大排序演算法全面解析-Java實現排序演算法Java
- 十大經典排序演算法總結(JavaScript描述)排序演算法JavaScript