講到算法,不可避免的會提到排序算法;在排序算法中,冒泡排序、選擇排序和插入排序等是最常被問到的幾種基本的排序算法。下面用js來實現這幾個簡單的排序。
1、冒泡排序
概念
從序列的最右邊開始比較相鄰兩個數字的大小,再根據結果交換兩個數字的位置,重複這一操作,實現所有數字從小到大或從大到小排列的算法即冒泡排序。
步驟
- 外層循環,n長的數組需要比較n趟,每次找到一個最小值
- 內層循環,每一趟之後需要比較的個數減1;
- 從序列的末尾開始比較相鄰兩個數字的大小;如果比較的數據比左邊相鄰的數據小,則左移當前比較的數據。
- 直至當前比較數據的位置等於當前比較次數時,則一輪結束。
- 比較完一輪後,繼續從末尾開始比較下一輪
代碼
// 編寫方法,實現冒泡
var arr = [29,45,29,72,51,68,72,97];
var getMaopao = function(arr) {
//外層循環,控制趟數,每一次找到一個最小值
for (var i =0; i< arr.length - 1; i++){
// 內層循環,從右側開始控制比較的次數,並且判斷兩個數的大小
for (var j = arr.length; j>= i; j--){
// 如果後面的數小,放到前面(從小到大的冒泡排序)
if (arr[j]< arr[j-1]) {
var temp = arr [j];
arr [j] = arr[j-1];
arr[j-1] = temp;
}
}
}
return arr;
}
console.log('maopao', getMaopao(arr))
也可以是從前到後比較
for (var i = 0; i < arr.length - 1; i++) {
// 內層循環,控制比較的次數,並且判斷兩個數的大小
for (var j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
2、選擇排序
概念
從待排序的數據中尋找最小值,將其與序列最左邊的數字進行交換,重複這一操作的算法即選擇排序。
步驟
- 循環數組,找到最小值
- 將最小值和最左邊的元素進行調換,完成第一輪
- 從第二位開始,循環數組,找到剩下的最小值
- 重複直到最後一輪,依次完成所有數據的排序
代碼
var arr = [120,29,45,29,72,51,68,72,97];
var getChoose = function(arr) {
//外層循環,控制趟數,每一次找到一個最小值
for (var i =0; i< arr.length - 1; i++){
// 內層循環,從右側開始控制比較的次數,並且判斷兩個數的大小
var min = arr[i];
var minIndex = i;
// 內層循環,每一次找到餘下數字的最小值,記錄下標
for (var j = i; j< arr.length; j++){
if (arr[j]<min) {
min = arr[j]
minIndex = j
}
}
// 將最小值與第i位交換位置
var temp = arr[i]
arr[i] = arr [minIndex]
arr[minIndex] = temp
}
return arr;
}
console.log('choose', getChoose(arr))
如果不記錄下標,在內層循環交換位置也是可以的(每次都把最小值往前交換,類似冒泡),但是這樣交換的次數會很多,運行速度會變慢。
3、插入排序
概念
從序列左端開始依次對數據進行排序的算法稱爲插入排序。(序列中數據分爲已排序區和未排序區,依次對每個數據和已排序區比較,進行排序)
步驟
- 假設第一個數字已完成排序,對第二個數字與第一個進行比較
- 如果小於它,則放到它之前,否則之後,完成排序
- 然後第三個數字,與前兩個已排序的進行比較,找到小於它的數字,放在此數字之後
- 如此反覆,完成整個數組的排序
代碼
// 編寫方法,實現插入排序
var arr = [120,29,45,29,72,51,68,72,97];
var getChoose = function(arr) {
var newArr = [arr[0]];
//外層循環舊數組,獲得未排序區的數字
for (var i =1; i< arr.length; i++){
// 內層循環新數組,將未排序區的數字與已排序區比較
for (var j = 0; j< newArr.length; j++) {
// 當數字小於已排序區的某個數字時,將此數字插入在已排序區的該數字之後,跳出循環
if (arr[i]< newArr[j]) {
newArr.splice(j,0,arr[i])
break;
}
}
}
return newArr;
}
console.log('choose', getChoose(arr))
4、快速排序
概念
快速排序的原理,簡單來說就是把一個事情,分成很多小事情來處理,分治的思想。如找到一個基準,將大於它的放到右邊,小於它的所有數放到左邊,再分別對左右的數組重複此步驟,最後數組將按照從小到大的順序排列。
步驟
- 找基準(一般是以第一項爲基準)
- 遍歷數組,小於基準的放在left,大於基準的放在right
- 遞歸,對left和right內的數組不斷重複以上方式,直到最後剩下一位。(有些二分法的意思)
代碼
let dat=[5, 8, 10, 3, 2, 18, 17, 9];
var sortedData=function quickSort(data){
//遞歸出口
if(data.length<=1){
return data;
}
//此處要將基準數從原數組移除,避免上面的data.length判斷陷入死循環
let baseData=data.splice(0,1)[0];
let leftData=[],rightData=[];
//此處的data.length和上面不同,移除了基準數,比上面小1
for(let i=0;i<data.length;i++){
if(data[i]>baseData){
rightData.push(data[i]);
}else{
leftData.push(data[i]);
}
}
leftData=quickSort(leftData);
rightData=quickSort(rightData);
return [...leftData, baseData, ...rightData];
}
console.log(sortedData(dat));