冒泡,插入,快速排序,遞歸(setTimeout()內存不溢出)

冒泡,插入,快速排序,遞歸(setTimeout()內存不溢出)

強化下印象javascript

B站視頻地址(時效性):https://www.bilibili.com/vide...java

百度搬運分流:算法

連接: https://pan.baidu.com/s/1KZGW...
提取碼:wkjt
複製這段內容後打開百度網盤手機App,操做更方便哦

代碼

/**
 * @name 數組排序算法(保證數組數據惟一)
 * @author SunSeekerX
 * @time 2019-11-23 16:05:37
 * @LastEditors SunSeekerX
 * @LastEditTime 2019-11-23 18:59:32
 */

/**
 * 冒泡排序
 * 1.比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。
 * 2.對每一對相鄰元素作一樣的工做,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
 * 3.針對全部的元素重複以上的步驟,除了最後一個。
 * 4.持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較。
 */

console.log("------------------冒泡排序---------------");
console.time();
const arr = [1, 9, 5, 4, 3, 8];
console.log("排序前>>>", arr);
for (let i = 0; i < arr.length - 1; i++) {
  for (let j = 0; j < arr.length - 1 - i; j++) {
    let temp = null;
    if (arr[j] > arr[j + 1]) {
      temp = arr[j];
      arr[j] = arr[j + 1];
      arr[j + 1] = temp;
    }
  }
}
console.log("排序後>>>", arr);
console.timeEnd();
console.log("\n");

/**
 * 插入排序
 * 1.依次取出數組中的值
 * 2.更新的數組對比插入到新的數組(抓牌原理同樣)
 */

console.log(
  "------------------插入排序,從後往前比(鬥地主抓牌)---------------"
);
// 插入排序,從後往前比(鬥地主抓牌)
const arr2 = [1, 9, 5, 4, 3, 8];
console.time();
console.log("排序前>>>", arr2);
// 1.取出第一張牌
const newArr = [arr2[0]];
for (let i = 1; i < arr2.length; i++) {
  // 2.從後面往前插
  for (let j = newArr.length - 1; j >= 0; j--) {
    // 若是取出的牌比當前循環的牌大,就放在這個牌後面
    if (arr2[i] > newArr[j]) {
      // 插入到新的數組
      newArr.splice(j + 1, 0, arr2[i]);
      break;
    }
    // 比較到第一張牌,放到手裏的第一張(最小)
    if (j === 0) {
      newArr.unshift(arr2[i]);
    }
  }
}
console.log("排序後>>>", newArr);
console.timeEnd();
console.log("\n");

/**
 * 快速排序
 * 1.首先設定一個分界值,經過該分界值將數組分紅左右兩部分。
 * 2.將大於或等於分界值的數據集中到數組右邊,小於分界值的數據集中到數組的左邊。此時,左邊部分中各元素都小於或等於分界值,而右邊部分中各元素都大於或等於分界值。
 * 3.而後,左邊和右邊的數據能夠獨立排序。對於左側的數組數據,又能夠取一個分界值,將該部分數據分紅左右兩部分,一樣在左邊放置較小值,右邊放置較大值。右側的數組數據也能夠作相似處理。
 * 4.重複上述過程,能夠看出,這是一個遞歸定義。經過遞歸將左側部分排好序後,再遞歸排好右側部分的順序。當左、右兩個部分各數據排序完成後,整個數組的排序也就完成了。
 */

console.log("------------------快速排序---------------");
const arr3 = [1, 9, 5, 4, 3, 8];
console.time();
console.log("排序前>>>", arr3);
function quick(arr) {
  // 4.結束遞歸(當arr中小於等於一項,則返回)
  if (arr.length <= 1) {
    return arr;
  }

  // 1.找到數組的中間項把他刪除
  let middleIndex = Math.floor(arr.length / 2);
  let middleValue = arr.splice(middleIndex, 1)[0];

  // 2.準備左右兩個數組,循環剩下的數組中的每一項,比中間項小的放左邊,反之放右邊
  let arrLeft = [],
    arrRight = [];
  for (let i = 0; i < arr.length; i++) {
    arr[i] < middleValue ? arrLeft.push(arr[i]) : arrRight.push(arr[i]);
  }

  // 3.遞歸處理左右兩邊數組,一直到左右兩邊都排好(左右讓左邊+中間+右邊爲最後的結果)
  return quick(arrLeft).concat(middleValue, quick(arrRight));
}
console.log("排序後>>>", quick(arr3));
console.timeEnd();
console.log("\n");

console.log("------------------分割線---------------\n\n");

console.log("------------------(For循環計算1-10累加的和)---------------");
console.time();
let total = 0;
for (let i = 1; i <= 10; i++) {
  total = total + i;
}
console.log("For循環計算後>>>", total);
console.timeEnd();
console.log("\n");

console.log("------------------(遞歸計算1-10累加的和)---------------");
console.time();
function sumFun(n) {
  if (n > 10) {
    return 0;
  }
  return n + sumFun(n + 1);
}
console.log("遞歸計算後>>>", sumFun(1));
console.timeEnd();
console.log("\n");

/** 
 * 堆棧溢出
 * 
 * Uncaught RangeError: Maximum call stack size exceeded
*/

// function fn() {
//   fn();
// }
// fn();

/** 
 * 堆棧不溢出
 * 這實際上並非遞歸調用,由於fn2的第一次調用實際上在setTimeout()調用下一個調用以前完成。
 * 因此,這不是技術上的遞歸,而且不會隨着時間的推移創建堆棧。它能夠在沒有任何積聚的狀況下永久運行,這是保持反覆運行的完美方式。
 * javascript不是多線程的,所以它不會爲定時器建立多個線程。
 * 觸發的每一個定時器事件只是將事件放入事件隊列中,而且若是當時沒有JS正在運行,則觸發該事件(從而調用回調函數)。
 * 若是JS正在運行,那麼JS引擎會等待,直到當前正在執行的JS完成,而後爲事件隊列中的下一個事件提供服務(從而調用回調)。
 * 
 * 通俗的說
 * 
 * 在執行setTimeout中的函數方法以前,fn()這個方法已經執行完畢了,內存堆棧已經釋放了,所以不會內存溢出
*/

// function fn2() {
//   setTimeout(() => fn2(), 0);
// }
// fn2();

輸出結果

------------------冒泡排序---------------
排序前>>> [ 1, 9, 5, 4, 3, 8 ]
排序後>>> [ 1, 3, 4, 5, 8, 9 ]
default: 2.884ms


------------------插入排序,從後往前比(鬥地主抓牌)---------------
排序前>>> [ 1, 9, 5, 4, 3, 8 ]
排序後>>> [ 1, 3, 4, 5, 8, 9 ]
default: 0.896ms


------------------快速排序---------------
排序前>>> [ 1, 9, 5, 4, 3, 8 ]
排序後>>> [ 1, 3, 4, 5, 8, 9 ]
default: 0.903ms


------------------分割線---------------


------------------(For循環計算1-10累加的和)---------------
For循環計算後>>> 55
default: 0.211ms


------------------(遞歸計算1-10累加的和)---------------
遞歸計算後>>> 55
default: 0.234ms
相關文章
相關標籤/搜索