JavaScript 排序演算法(JavaScript sorting algorithms)

来源:http://www.cnblogs.com/givebest/archive/2017/08/13/7355161.html
-Advertisement-
Play Games

介紹常見的排序演算法:冒泡排序、選擇排序、插入排序、歸併排序、快速排序及簡單的性能測試。 ...


JavaScrip 排序演算法(JavaScript Sorting Algorithms)

基礎構造函數

以下幾種排序演算法做為方法放在構造函數里。

function ArrayList () {
  var array = [];

  // 交換位置
  var swap = function (index1, index2) {
    var aux = array[index1];
    array[index1] = array[index2];
    array[index2] = aux;
  }

  this.insert = function (item) {
    array.push(item);
  };

  this.toString = function () {
    return array.join();
  };

  this.val = function () {
    return array;
  }

  // 冒泡排序
  this.bubbleSort = function () {
    //etc
  }
}

1. 冒泡排序

冒泡排序比較任何兩個相鄰的項,如果第一個比第二個大,則交換它們。

複雜度 O(n^2)。

代碼

this.bubbleSort = function () {
  console.time('Bubble Sort');
  var length = array.length;
  for (var i = 0; i < length; i++) {
    for (var j = 0; j < length - 1 - i; j++) {
      if (array[j] > array[j+1]) {
        swap(j, j + 1);
      }
    }
  }
  console.timeEnd('Bubble Sort');
}

圖解

冒泡排序

2. 選擇排序

選擇排序演算法是一種原址比較排序演算法。選擇排序大致的思路是找到數據結構中的最小值並將其放置在第一位,接著找到第二小的值並將其放在第二位,以此類推。

複雜度:O(n^2)。

代碼

this.selectionSort = function () {
  console.time('selectionSort');
  var length = array.length,
      indexMin;

  for (var i = 0; i < length - 1; i++) {
    indexMin = i;
    for (var j = i; j < length; j++) {
      if (array[indexMin] > array[j]) {
        indexMin = j;
      }
    }

    if (i !== indexMin) {
      swap(i, indexMin);
    }
  }
  console.timeEnd('selectionSort');
}

圖解

選擇排序

3. 插入排序

插入排序每次排一個數組項,以此方式構建最後的排序數組。假定第一項已經排序了,接著,它和第二項進行比較,第二項是應該待在原位還是插到第一項之前呢?這樣,頭兩項就已正確排序,接著和第三項比較(它是該插入到第一、第二還是第三的位置呢?),以此類推。

排序小型數組時,此演算法比選擇排序和冒泡排序性能要好。

代碼

this.insertionSort = function () {
  console.time('insertionSort');
  var length = array.length,
      j, temp;

  for (var i = 1; i < length; i++) {
    j = i;
    temp = array[i];
    while (j > 0 && array[j-1] > temp) {
      array[j] = array[j-1];
      j--;
    }
    array[j] = temp;
  }
  console.timeEnd('insertionSort');
}

圖解

插入排序

4. 歸併排序

歸併排序是一種分治演算法。其思想是將原始數組切分成較小的數組,直到每個小數組只有一個位置,接著將小數組歸併成較大的數組,直到最後只有一個排序完畢的大數組。

複雜度:O(n log^n)。

代碼

this.mergeSort = function () {
  console.time('mergeSort');
  array = mergeSortRec(array);
  console.timeEnd('mergeSort');
}
var mergeSortRec  = function (array) {
  var length = array.length;
  if (length === 1) {
    return array;
  }

  var mid = Math.floor(length / 2),
      left = array.slice(0, mid),
      right = array.slice(mid, length);

  return merge(mergeSortRec(left), mergeSortRec(right));
}
var merge = function (left, right) {
  var result = [],
      il = 0,
      ir = 0;

  while (il < left.length && ir < right.length) {
    if (left[il] < right[ir]) {
      result.push(left[il++]);
    } else {
      result.push(right[ir++]);
    }
  }

  while (il < left.length) {
    result.push(left[il++]);
  }

  while (ir < right.length) {
    result.push(right[ir++]);
  }

  return result;
}

圖解

歸併排序

5. 快速排序

歸併排序一樣,快速排序也使用分治的方法,將原始數組分為較小的數組(但它沒有像歸併排序那樣將它們分割開)。

它的性能通常比其他的複雜度為O(n log^n)的排序演算法要好。

複雜度:O(n log^n)。

代碼

this.quickSort = function () {
  console.time('quickSort');
  quick(array, 0, array.length - 1);
  console.timeEnd('quickSort');
}

var quick = function (array, left, right) {
  var index;
  if (array.length > 1) {
    index = partition(array, left, right);

    if (left < index - 1) {
      quick(array, left, index - 1);
    }

    if (index < right) {
      quick(array, index, right);
    }
  }
};

// 劃分過程
var partition = function (array, left, right) {
  var pivot = array[Math.floor((right + left) / 2)],
      i = left,
      j = right;

  while (i < j) {
    while (array[i] < pivot) {
      i++;
    }

    while (array[j] > pivot) {
      j--;
    }

    if (i <= j) {
      swapQuickSort(array, i, j);
      i++;
      j--;
    }
  }
  return i;
}

var swapQuickSort = function (array, index1, index2) {
  var aux = array[index1];
  array[index1] = array[index2];
  array[index2] = aux;
}

圖解

快速排序1
快速排序2
快速排序3
快速排序4
快速排序5

6. ECMAScript 排序

ECMAScript沒有定義用哪個排序演算法,所以瀏覽器廠商可以自行去實現演算法。例如,Mozilla Firefox使用歸併排序作為Array.prototype.sort的實現,而Chrome使用了一個快速排序(下麵我們會學習的)的變體。

this.esSort = function () {
  console.time('esSort');
  var tempArray = [];
  tempArray = array.sort(function (a, b) {
    return a - b;
  });
  console.timeEnd('esSort');
  return tempArray;
}

性能測試

環境

  • OS:WIN10 64位

  • 瀏覽器:Google Chrome 60.0.3112.78

代碼

/**
* 創建隨機數組
* @param  {[type]} size [description]
* @return {[type]}      [description]
*/
function createNonSortedArray (size) {
  var array = new ArrayList();
  for (var i = size; i > 0; i--) {
    var tempNum = Math.random() * i >>> 0;
    array.insert(tempNum);
  }
  return array;
}

// 冒泡排序
(function () {
  var array = createNonSortedArray(500);
  array.bubbleSort(); // Bubble Sort: 2.625ms
  console.log(array.val());
}());


// 選擇排序
(function () {
  var array = createNonSortedArray(500);
  array.selectionSort(); // selectionSort: 1.986083984375ms
  console.log(array.val());
}());

// 插入排序
(function () {
  var array = createNonSortedArray(500);
  array.insertionSort(); // insertionSort: 1.825927734375ms
  console.log(array.val());
}());

// 歸併排序
(function () {
  var array = createNonSortedArray(500);
  array.mergeSort(); // mergeSort: 0.76416015625ms
  console.log(array.val());
}());


// 快速排序
(function () {
  var array = createNonSortedArray(500);
  array.quickSort(); // quickSort: 0.39111328125ms
  console.log(array.val());
}());


// ES排序
(function () {
  var array = createNonSortedArray(500);
  array.esSort(); // esSort: 0.34130859375ms
  console.log(array.val());
}());

由此可見,一般情況我們只需要使用JavaScript 提供的 Array.prototype.sort() 方法即可,瀏覽器(或宿主環境)會在底層採用最優演算法幫我們實現排序。

來源/參考

轉載請註明出處: http://blog.givebest.cn/javascript/2017/08/02/javascript-sorting-algorithms.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 放假啦~學生們要買車票回家了,有汽車票、火車票,等。但是,車站很遠,又要考試,怎麼辦呢?找代理買啊,雖然要多花點錢,但是,說不定在搞活動,有折扣呢~ 編譯,運行 ...
  • 本周要進行boost asio庫的學習,在學習之前發現最好需要先瞭解一下前攝器模式,這樣對asio庫的理解很有幫助,故寫下此文 我之前寫的隨筆XShell的模擬實現中的鏈接方式可以說是同步的(伺服器阻塞等待鏈接),這樣當有伺服器端在等待鏈接的時候就浪費了大量的資源,我們可以讓伺服器非同步等待客戶端的鏈 ...
  • 現有一批裝備(產品),分為不同的部位(上裝、下裝)與不同的等級(lv1、lv2)。又有不同lv的工廠,只生產對應lv的全套裝備。 代碼實現上...本次寫得比較偷懶,函數實現都寫在頭文件了.... 有些重覆的代碼,是直接用sed替換一些字元生成的。如: Suit Trousers Clothes Tr ...
  • 1、有一個工廠,專門生產不同品牌的汽車。當有人需要從此工廠提貨的時候,只需要告訴他,要什麼品牌的,就可以了,並不關心這些車是怎麼生產出來的。 2、以上方式,如果增加品牌的時候,也要修改工廠,有點麻煩。於是,把工廠也抽象了。 1的類圖與實現: 首先,是通用的車 然後是不同品牌的車,繼承自Car 接著, ...
  • 項目框架轉換 原來用的是jquery+ace.js框架的項目 現在需要改為現在流行的angularJS框架 本人又不會angularJS,只能一步一步的摸索 路漫漫其修遠兮 吾將上下而求索 剛接觸angularJS 給我的第一感覺是總有和最早期的ASP有些相似 很多前端邏輯 很多界面代碼揉合在一起, ...
  • 最近發現好多網站都採用頂部彈窗,並且不用用戶手動去點擊確定。感覺這樣很方便用戶,所以也找了好多大神的代碼,整理一下方便以後查找 前端: 個人感覺還是很好用的,這個是從某位大神那裡引用來的,如果有冒犯,麻煩告訴我,我會刪除的 下載鏈接:http://pan.baidu.com/s/1hr8vIF6 ...
  • 今天想在Sublime Text(簡稱ST)內編寫HTML後直接使用瀏覽器看效果,想添加View in Browser插件,然後遇到奇怪的問題添加插件直接報"找不到有用的插件" 一開始懷疑是中文破解版的,換成原版的就會好。但是官網上下載原版還是不行,然後上網搜了一下,發現好多人遇到此問題。 接著就一 ...
  • 之前我的旅游網站前端部分只用了HTML+CSS解決,接下來逐步使用更高級的CSS特性和新引入的JavaScript技術來提高網站的交互體驗。 每到進行線上更新的時候,就來記錄一次更新的內容。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...