相信大家面試的時候都要經歷手寫什麼什麼排序這種事情吧,要不就是大概說一下思路。不許用各種語言封裝好的函式、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...
常見的排序演算法
排序演算法是最基礎,也是最簡單的演算法思想,因為應用場景多,書寫簡單,所以應用較為普遍,所以在面試和考試的時候,都會涉及到排序演算法,雖然排序演算法種類很多,但是只要理解了思想,然後靈活運用,那麼就不難記憶.排序演算法兩個需要記憶和理解的點就是 演算法思想和時間複雜度.下面我們就介紹和分析一下常見的...