常見的排序演算法

2021-08-17 23:50:54 字數 3841 閱讀 1112

相信大家面試的時候都要經歷手寫什麼什麼排序這種事情吧,要不就是大概說一下思路。不許用各種語言封裝好的函式、api,僅僅用原生的方法把他寫出來。雖然看起來沒什麼意思,但是這也是考察乙個人的基礎有沒有紮實、程式設計思想好不好的一種方法。

重要的事情說三遍:

主要理解快速排序!!!

主要理解快速排序!!!

主要理解快速排序!!!

而且要滾瓜爛熟!

以下所有的排序都是公升序

先說最簡單的吧,冒泡,就是指數值大的,就是乙個大氣泡,慢慢冒到後面(水面)去。對於要排序的陣列,乙個個去遍歷,大的數往後移。往後移怎麼做到呢,就是遍歷的時候,兩個數中(第j和j+1個)要是誰比較大,誰在後面(交換位置)。氣泡都聚集在水面(大數都從後面聚集在一起,所以每次第二層遍歷都會到len-1-j截止)

時間複雜度o(n^2),如果是已經排好的情況是o(n)

function

bubble

(arr)}}

return arr

}

快排是面試問得最多的了,也是目前用得最多,效率最穩的方法。快速排序的最慢情況是o(n²),公升序的時候。但它的數學期望是o(n log n) ,且o(n log n)記號中隱含的常數因子很小,比複雜度穩定等於o(n log n)的歸併排序要小很多。對絕大多數順序性較弱的隨機數列而言,快速排序總是佔優。

首先,取乙個基準值(我們取第乙個,也可以取中間、取最後都行),接著讓小於基準值的在左邊,大於的在右邊,分成左右兩堆。然後分別對左邊和右邊那堆採取同樣的操作,取基準值,讓基準值左邊都是小於他的,右邊都是大於他的。一直重複操作,直到全部公升序。

這種方法容易理解,但是依賴另外開闢出來的陣列。我們取第乙個作為基準,從第二(特別注意,第二個開始!不然棧溢位)個開始遍歷,小於基準的數放在左陣列(left),大於基準的放在右陣列,接著對左陣列和右邊陣列重複操作,再對左邊陣列的左邊和右邊進行操作……直到陣列長度為1

function

quick

(arr)

var pivot = arr[0]

var left =

var right =

var len = arr.length

for(var i = 1;iif(arr[i]>pivot)else

}return quick(left).concat([pivot],quick(right))

}

當然網上也有人家從中間開始的,中間開始的話,就用splice去除這個值,再給pivot賦值

這種比較難理解,但是不會占用其他記憶體。基準值也是取第乙個,quick傳入3個引數:陣列,子陣列的起始位置、子陣列的結束位置。第一次賦值肯定是quick(arr),left和right是undefined,left和right預設是第乙個和最後乙個數的索引。 partitionindex是基準值索引。

核心部分是中間判斷left

function

quick

(arr, left, right)

}var temp = arr[pivot];

arr[pivot] = arr[index - 1];

arr[index - 1] = temp;

partitionindex = index-1;

quick(arr, left, partitionindex-1);

quick(arr, partitionindex+1, right);

}return arr;

}

表現最穩定的排序之一,無論什麼資料進去都是o(n²)複雜度,但是依賴額外記憶體儲存最小值

陣列長度為len的陣列中進行選擇排序時:

- 取後len個的最小值放陣列第乙個位置

- 取後len-1個的最小值放陣列第二個位置

- 取後len-2個的最小值放陣列第三個位置

…….

顯然,最後乙個就是最大的,前面的已經完成了排序

function

select

(arr)

}temp = arr[i]

arr[i] = arr[min]

arr[min] = temp

}return arr

}

就像打牌一樣,自己是怎麼整理的呢。拿著一張牌,乙個個往下去對比,發現下乙個大於(或等於)自己,上乙個小於(或等於)自己,那就把他放在中間。複雜度穩定o(n^2),最好的情況是已經排序完成時o(n),依賴額外記憶體,儲存當前遍歷的數

function

insert

(arr)

arr[preindex+1] = current;

}return arr;

}

將陣列區間取出來(【min,max】),然後對陣列進行遍歷,計算每乙個陣列元素在區間【min,max】中出現次數,最後從頭到尾把陣列寫出來。複雜度是o(n),比較穩定,但是依賴額外記憶體空間

計數排序需要全部都是整數!

這裡,我們取正整數來試驗,所以只要取得最大值就行。arr的值表示bucket的位置,如果bucket的某個位置是undefined,說明arr裡面沒有這個位置的索引值

function

count

(arr)

bucket[arr[i]]++;//開始統計

}for (var j = 0; j < max + 1; j++)

}return arr;

}

先比較個位數的大小,按順序分類,從頭到尾重新取出數字。再進行第二次比較,比較十位數的大小,按順序分類,再從頭到尾取出……..直到最高位。要求全是整數。

我們這裡比較兩位數以內的

var counter = ;

function

radixsort

(arr, maxdigit)

counter[bucket].push(arr[j]);//和計數排序一樣,這裡只需要0-9的陣列存放

}var pos = 0;

for(var j = 0; j < counter.length; j++) }}

}return arr;

}

由名字可以知道,這其實就是一種遞迴。順序是比較前面兩個=>比較前面兩個的後面兩個=>比較前面四個=>比較前面四個的後面兩個=>比較前面6個的後面兩個=>比較前面8個……..

始終都是o(nlogn)的複雜度,不受輸入資料影響,但是依賴額外記憶體

每一次2個數的小組比較,兩個小組的數量一致而且排序方式也是公升序,對比起來就是一一對比。大的組比較也是一樣。數量不同只有陣列長度非2的n次方的尾部的比較。

function

mergesort

(arr)

var middle = math.floor(len / 2),//陣列被分成左右兩個子陣列

left = arr.slice(0, middle),

right = arr.slice(middle);

return merge(mergesort(left), mergesort(right));

}function

merge

(left, right)

else

}while (left.length)

result.push(left.shift());//取出第乙個取比較

while (right.length)

result.push(right.shift());

return result;

}

常見的排序演算法

一 氣泡排序 include include void swap int a,int b void bubblesort int arr,int size int main void bubblesort a,5 for int i 0 i 5 i cout 二 選擇排序 void selectio...

常見的排序演算法

需要包含的標頭檔案 include stdafx.h include include include 氣泡排序是穩定排序 時間複雜度 o n 2 void swap int a,int b void bubblesort int a,int n void printnum int a,int n a...

常見的排序演算法

排序演算法是最基礎,也是最簡單的演算法思想,因為應用場景多,書寫簡單,所以應用較為普遍,所以在面試和考試的時候,都會涉及到排序演算法,雖然排序演算法種類很多,但是只要理解了思想,然後靈活運用,那麼就不難記憶.排序演算法兩個需要記憶和理解的點就是 演算法思想和時間複雜度.下面我們就介紹和分析一下常見的...