js實現快速排序(in-place)簡述

来源:http://www.cnblogs.com/LIUYANZUO/archive/2016/08/07/5745306.html
-Advertisement-
Play Games

快速排序,又稱劃分交換排序。以分治法為策略實現的快速排序演算法。 本文主要要談的是利用javascript實現in-place思想的快速排序 分治法: 在電腦科學中,分治法是建基於多項分支遞歸的一種很重要的演算法範式。字面上的解釋是“分而治之”,就是把一個複雜的問題分成兩個或更多的相同或相似的子問題, ...


快速排序,又稱劃分交換排序。以分治法為策略實現的快速排序演算法。

本文主要要談的是利用javascript實現in-place思想的快速排序

 

分治法:

電腦科學中,分治法是建基於多項分支遞歸的一種很重要的演算法範式。字面上的解釋是“分而治之”,就是把一個複雜的問題分成兩個或更多的相同或相似的子問題,直到最後子問題可以簡單的直接求解,原問題的解即子問題的解的合併。(摘自維基百科)

 

快速排序的思想

數組中指定一個元素作為標尺,比它大的放到該元素後面,比它小的放到該元素前面,如此重覆直至全部正序排列。

 

快速排序分三步:

  1. 選基準:在數據結構中選擇一個元素作為基準(pivot)
  2. 劃分區:參照基準元素值的大小,劃分無序區,所有小於基準元素的數據放入一個區間,所有大於基準元素的數據放入另一區間,分區操作結束後,基準元素所處的位置就是最終排序後它應該所處的位置
  3. 遞歸:對初次劃分出來的兩個無序區間,遞歸調用第 1步和第 2步的演算法,直到所有無序區間都只剩下一個元素為止。

 

現在先說說普遍的實現方法(沒有用到原地演算法)

function quickSort(arr) {
    if (arr.length <= 1) return ;
    
    //取數組最接近中間的數位基準,奇數與偶數取值不同,但不印象,當然,你可以選取第一個,或者最後一個數為基準,這裡不作過多描述
    var pivotIndex = Math.floor(arr.length / 2);
    var pivot = arr.splice(pivotIndex, 1)[0];
    //左右區間,用於存放排序後的數
    var left = [];
    var right = [];

    console.log('基準為:' + pivot + ' 時');
    for (var i = 0; i < arr.length; i++) {
        console.log('分區操作的第 ' + (i + 1) + ' 次迴圈:');
        //小於基準,放於左區間,大於基準,放於右區間
        if (arr[i] < pivot) {
            left.push(arr[i]);
            console.log('左邊:' + (arr[i]))
        } else {
            right.push(arr[i]);
            console.log('右邊:' + (arr[i]))
        }
    }
    //這裡使用concat操作符,將左區間,基準,右區間拼接為一個新數組
    //然後遞歸1,2步驟,直至所有無序區間都 只剩下一個元素 ,遞歸結束
    return quickSort(left).concat([pivot], quickSort(right));
}

var arr = [14, 3, 15, 7, 2, 76, 11];
console.log(quickSort(arr));
/*
 * 基準為7時,第一次分區得到左右兩個子集[ 3, 2,]   7   [14, 15, 76, 11];
 * 以基準為2,對左邊的子集[3,2]進行劃分區排序,得到[2] 3。左子集排序全部結束
 * 以基準為76,對右邊的子集進行劃分區排序,得到[14, 15, 11] 76
 * 此時對上面的[14, 15, 11]以基準為15再進行劃分區排序, [14, 11] 15
 * 此時對上面的[14, 11]以基準為11再進行劃分區排序, 11  [14]
 * 所有無序區間都只剩下一個元素,遞歸結束
 *
 */

通過斷點調試,可得出結果。

 

弊端:

它需要Ω(n)的額外存儲空間,跟歸併排序一樣不好。在生產環境中,需要額外的記憶體空間,影響性能。

同時,很多人認為上邊的就是真正的快速排序了。 所以,在下麵,很有必要的推薦in-place演算法的快速排序

有關於原地演算法可參考維基百科,被牆的同學,百度也差不多。

 

in-place

快速排序一般是用遞歸實現,最關鍵是partition分割函數,它將數組劃分為兩部分,一部分小於pivot,另一部分大於pivot。具體原理上邊提過

function quickSort(arr) {
    // 交換
    function swap(arr, a, b) {
        var temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

    // 分區
    function partition(arr, left, right) {
        /**
         * 開始時不知最終pivot的存放位置,可以先將pivot交換到後面去
         * 這裡直接定義最右邊的元素為基準
         */
        var pivot = arr[right];
        /**
         * 存放小於pivot的元素時,是緊挨著上一元素的,否則空隙里存放的可能是大於pivot的元素,
         * 故聲明一個storeIndex變數,並初始化為left來依次緊挨著存放小於pivot的元素。
         */
        var storeIndex = left;
        for (var i = left; i < right; i++) {
            if (arr[i] < pivot) {
                /**
                 * 遍曆數組,找到小於的pivot的元素,(大於pivot的元素會跳過)
                 * 將迴圈i次時得到的元素,通過swap交換放到storeIndex處,
                 * 並對storeIndex遞增1,表示下一個可能要交換的位置
                 */
                swap(arr, storeIndex, i);
                storeIndex++;
            }
        }
        // 最後: 將pivot交換到storeIndex處,基準元素放置到最終正確位置上
        swap(arr, right, storeIndex);
        return storeIndex;
    }

    function sort(arr, left, right) {
        if (left > right) return;

        var storeIndex = partition(arr, left, right);
        sort(arr, left, storeIndex - 1);
        sort(arr, storeIndex + 1, right);
    }

    sort(arr, 0, arr.length - 1);
    return arr;
}

console.log(quickSort([8, 4, 90, 8, 34, 67, 1, 26, 17]));

 

分區的優化

這裡細心的同學可能會提出,選取不同的基準時,是否會有不同性能表現,答案是肯定的,但,因為,我是搞前端的,對演算法不是很瞭解,所以,這個坑留給厲害的人來填補。

 

複雜度

快速排序是排序速度最快的演算法,它的時間複雜度是O(log n)

在平均狀況下,排序n個項目要Ο(n log n)次比較。在最壞狀況下則需要Ο(n2)次比較.


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

-Advertisement-
Play Games
更多相關文章
  • 在hibernate中我們知道如果要從資料庫中得到一個對象,通常有兩種方式,一種是通過session.get()方法,另一種就是通過session.load()方法,然後其實這兩種方法在獲得一個實體對象時是有區別的,在查詢性能上兩者是不同的。 一.load載入方式 當使用load方法來得到一個對象時 ...
  • 持久化(Persistence) 即把數據(如記憶體中的對象)保存到可永久保存的存儲設備中(如磁碟)。持久化的主要應用是將記憶體中的對象存儲在關係型的資料庫中,當然也可以存儲在磁碟文件中、XML數據文件中等等。 持久化是將程式數據在持久狀態和瞬時狀態間轉換的機制。 JDBC就是一種持久化機制。文件IO也 ...
  • //fourth day to study python 24. In python , how to create funcation. we can use def to define funcation. such as: def MyFirstFuncation(): print('this ...
  • 請註意以下要點: 1、是否開啟了認證,QQ郵箱、163郵箱均要開啟認證 2、javax.mail.MessagingException: Could not connect to SMTP host: smtp.163.com, port: 25; //連接超時 解決參考:將這個屬性的true加上引 ...
  • stdafx.h: Form1.h ...
  • 1.安裝 Erlang,官網:https://www.erlang.org/ 2.安裝RabbitMQ伺服器,rabbitMQ server,官網http://www.rabbitmq.com/ 註:可以根據不同的需要到官網進行相關下載!!! 3.安裝完成之後需要對其進行配置變數: 創建新的系統變數 ...
  • 最近想用C++在windows下實現一個基本的圖像查看器功能,目前只想到了使用GDI或OpenGL兩種方式。由於實在不想用GDI的API了,就用OpenGL的方式實現了一下基本的顯示功能。用GDAL讀取圖像,這樣就能與圖像格式無關。OpenGL的glDrawPixels()函數也能實現圖像顯示,但是... ...
  • 數組的定義: JavaScript 中的數組是一種特殊的對象,用來表示偏移量的索引是該對象的屬性,索引可能是整數。然而,這些數字索引在內部被轉換為字元串類型,這是因為 JavaScript 對象中的屬性名必須是字元串。在內部被歸類為數組。由於 Array 在 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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...