用快速排序?qū)崿F(xiàn)javascript 中數(shù)組的Array.sort() 方法

快速排序是數(shù)組常用的排序算法,采用分而治之的思想野崇,需要用到遞歸猾普,故需要先了解遞虾啦。

  • Array.prototype.sort(callback)接受一個 回調(diào)函數(shù) 比如
    testArr.sort((a,b) => a-b) 正在研究中
    那sort用的是什么排序算法呢翠霍?那就要看Chrome V8引擎的源碼了锭吨。

sort方法源碼

DEFINE_METHOD(
  GlobalArray.prototype,
  sort(comparefn) {
    CHECK_OBJECT_COERCIBLE(this, "Array.prototype.sort");

    if (!IS_UNDEFINED(comparefn) && !IS_CALLABLE(comparefn)) {
      throw %make_type_error(kBadSortComparisonFunction, comparefn);
    }

    var array = TO_OBJECT(this);
    var length = TO_LENGTH(array.length);
    return InnerArraySort(array, length, comparefn);
  }
);

InnerArraySort方法源碼

function InnerArraySort(array, length, comparefn) {
  // In-place QuickSort algorithm.
  // For short (length <= 10) arrays, insertion sort is used for efficiency.

  if (!IS_CALLABLE(comparefn)) {
    comparefn = function (x, y) {
      if (x === y) return 0;
      if (%_IsSmi(x) && %_IsSmi(y)) {
        return %SmiLexicographicCompare(x, y);
      }
      x = TO_STRING(x);
      y = TO_STRING(y);
      if (x == y) return 0;
      else return x < y ? -1 : 1;
    };
  }
  function InsertionSort(a, from, to) {
    ...
  };
 ...
  function QuickSort(a, from, to) {
    var third_index = 0;
    while (true) {
      // Insertion sort is faster for short arrays.
      if (to - from <= 10) {
        InsertionSort(a, from, to);
        return;
      }
      if (to - from > 1000) {
        third_index = GetThirdIndex(a, from, to);
      } else {
        third_index = from + ((to - from) >> 1);
      }
      // Find a pivot as the median of first, last and middle element.
      var v0 = a[from];
      var v1 = a[to - 1];
      var v2 = a[third_index];
      var c01 = comparefn(v0, v1);
      if (c01 > 0) {
        // v1 < v0, so swap them.
        var tmp = v0;
        v0 = v1;
        v1 = tmp;
      } // v0 <= v1.
      var c02 = comparefn(v0, v2);
      if (c02 >= 0) {
        // v2 <= v0 <= v1.
        var tmp = v0;
        v0 = v2;
        v2 = v1;
        v1 = tmp;
      } else {
        // v0 <= v1 && v0 < v2
        var c12 = comparefn(v1, v2);
        if (c12 > 0) {
          // v0 <= v2 < v1
          var tmp = v1;
          v1 = v2;
          v2 = tmp;
        }
      }
      // v0 <= v1 <= v2
      a[from] = v0;
      a[to - 1] = v2;
      var pivot = v1;
      var low_end = from + 1;   // Upper bound of elements lower than pivot.
      var high_start = to - 1;  // Lower bound of elements greater than pivot.
      a[third_index] = a[low_end];
      a[low_end] = pivot;

      // From low_end to i are elements equal to pivot.
      // From i to high_start are elements that haven't been compared yet.
      partition: for (var i = low_end + 1; i < high_start; i++) {
        var element = a[i];
        var order = comparefn(element, pivot);
        if (order < 0) {
          a[i] = a[low_end];
          a[low_end] = element;
          low_end++;
        } else if (order > 0) {
          do {
            high_start--;
            if (high_start == i) break partition;
            var top_elem = a[high_start];
            order = comparefn(top_elem, pivot);
          } while (order > 0);
          a[i] = a[high_start];
          a[high_start] = element;
          if (order < 0) {
            element = a[i];
            a[i] = a[low_end];
            a[low_end] = element;
            low_end++;
          }
        }
      }
      if (to - high_start < low_end - from) {
        QuickSort(a, high_start, to);
        to = low_end;
      } else {
        QuickSort(a, from, low_end);
        from = high_start;
      }
    }
  };

  ...

  QuickSort(array, 0, num_non_undefined);
 ...
  return array;
}
  • 這一步最重要的是QuickSort,從代碼和注釋中可以看出sort使用的是插入排序和快速排序結(jié)合的排序算法寒匙。數(shù)組長度不超過10時零如,使用插入排序。長度超過10使用快速排序锄弱。在數(shù)組較短時插入排序更有效率考蕾。

自己實現(xiàn)的mysort() 方法

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>冒泡排序</title>
  <style>
    * {
      margin: 0;
      padding: 0;
    }
    header {
      text-align: center;
      font-size: 30px;
      font-weight: 900;
      line-height: 100px;
      width: 100%;
      height: 100px;
      background-color: #888;
      border-bottom: 1px solid #000;
      color: #fff;
      box-sizing: border-box;
    }

    aside {
      position: absolute;
      padding-left: 10px;
      top: 100px;
      left: 0;
      bottom: 0;
      width: 250px;
      background-color: #ddd;
      box-sizing: border-box;
      border: 1px solid #000;
      border-top: 0;
    }

    main {
      position: absolute;
      top: 100px;
      right: 0;
      left: 250px;
      bottom: 0;
      background-color: #fff;
    }

    #algorithm,
    #data_structure {
      margin-left: 60px;
    }

    form {
      width: 95%;
      height: 300px;
      margin: 20px auto;
      border: 1px solid #000;
    }

    #array_info {
      display: block;
    }

    input {
      width: 99%;
      height: 30px;
      border: 1px solid #000;
      margin: 5px auto;
      font-size: 20px;

    }

    #result_info {
      display: block;
    }

    #sortButton {
      background-color: royalblue;
      width: 200px;
      height: 40px;
      border-radius: 5px;
    }

    h3 {
      margin-bottom: 10px;
    }
  </style>
</head>

<body>
  <!-- 布局容器 -->

  <!-- 頭部區(qū)域 -->
  <header>
    數(shù)據(jù)結(jié)構(gòu)與算法
  </header>
  <!-- 側(cè)邊欄 -->
  <aside>
    <h3>*******數(shù)據(jù)結(jié)構(gòu)*******</h3>
    <ol id="data_structure">
      <li>數(shù)組</li>
      <li>棧</li>
      <li>隊列和雙端隊列</li>
      <li>鏈表</li>
      <li>集合</li>
      <li>字典和散列表</li>
      <li>樹</li>
      <li>二叉堆</li>
      <li>圖</li>
    </ol>
    <h3>*******算法*******</h3>
    <ol id="algorithm">
      <li>排序</li>
      <li>遞歸</li>
      <li>搜索</li>
    </ol>
  </aside>
  <!-- 主體 -->
  <main>
    <h3>這是前段程序員必須掌握的排序算法</h3>
    請輸入你要排序的數(shù)組,主要需要用英文逗號分隔,中文排序不生效会宪。 例如:3,4,5,10,1,2,3,56,6,7,7
    <input type="text" id="array_info">
    排序后的結(jié)果
    <input type="text" id="result_info">
    <input type="button" id="sortButton" value="點擊開始快速排序">
  </main>
  <script>
    // 快速排序的調(diào)用函數(shù)
    Array.prototype.mysort =  function ( left = 0, right = this.length -1) {
      if (this.length === 0) return this
      let index = partition(this, left, right)
      if (left < index - 1) this.mysort( left, index - 1)
      if (index < right) this.mysort(index, right)
      return this
      // partition是一個策略函數(shù),傳進 數(shù)組和左右指針了辕翰,可以進行劃分排序,返回劃分關(guān)鍵節(jié)點位置狈谊,以便下一次遞歸調(diào)用時候傳參
      function partition(arr, left, right) {
        const pivot = arr[Math.floor((left + right) / 2)]
        while (left <= right) {
          while (arr[left] < pivot) {
          left++
          }
          while (arr[right] > pivot) {
            right--
          }
          if (left <= right) {
            ;[arr[left], arr[right]] = [arr[right], arr[left]]
            left++;
            right--;
          }
        } 
        return left
      }
    }
    const btn = document.querySelector('#sortButton')
    btn.addEventListener('click', function () {
      const array_info = document.querySelector('#array_info').value
      const testArr = array_info.split(',')
      document.querySelector('#result_info').value = testArr.mysort()
    })
  </script>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喜命,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子河劝,更是在濱河造成了極大的恐慌壁榕,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赎瞎,死亡現(xiàn)場離奇詭異牌里,居然都是意外死亡,警方通過查閱死者的電腦和手機务甥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門牡辽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敞临,你說我怎么就攤上這事态辛。” “怎么了挺尿?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵奏黑,是天一觀的道長。 經(jīng)常有香客問我编矾,道長熟史,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任窄俏,我火速辦了婚禮蹂匹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凹蜈。我一直安慰自己限寞,他們只是感情好忍啸,可當(dāng)我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著昆烁,像睡著了一般吊骤。 火紅的嫁衣襯著肌膚如雪缎岗。 梳的紋絲不亂的頭發(fā)上静尼,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音传泊,去河邊找鬼鼠渺。 笑死,一個胖子當(dāng)著我的面吹牛眷细,可吹牛的內(nèi)容都是我干的拦盹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼溪椎,長吁一口氣:“原來是場噩夢啊……” “哼普舆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起校读,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤沼侣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后歉秫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蛾洛,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年雁芙,在試婚紗的時候發(fā)現(xiàn)自己被綠了轧膘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡兔甘,死狀恐怖谎碍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情洞焙,我是刑警寧澤椿浓,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站闽晦,受9級特大地震影響扳碍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜仙蛉,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一笋敞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荠瘪,春花似錦夯巷、人聲如沸赛惩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽喷兼。三九已至,卻和暖如春后雷,著一層夾襖步出監(jiān)牢的瞬間季惯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工臀突, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勉抓,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓候学,卻偏偏與公主長得像藕筋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子梳码,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容