快速排序(QuickSort)多語言實現帶圖解

1. 描述簡介

快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小,而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序。更多介紹能夠百度百科,接下來直接上代碼算法

2. 動態演示

PHP快速排序動態演示

2. 算法複雜程度表

算法複雜程度表

3. 代碼實現

PHP版本V1.0

這個版本我看了以前有一篇C算法文章中的寫法,應該算很早的版本了,我把他用PHP寫了一版.遞歸部分我是使用替換的方式進行合併數據,也可使用 PHP 引用(&) 進行合併。下面是代碼和實現步驟:數組

/**
 * PHP 快速排序 v1.0
 * 實現步驟:
 *          1.首先在數據中定義一個基準數(M),具體怎麼選因人而異。,定義好左右兩個座標L、R (左邊座標不能大於右邊座標)
 *          2.定義好基準數(M)後,從最右往左找小於基準數(M)的值(J)而且不能小於或等於左邊座標,找到後中止。
 *          3.再從左往右找大於基準數(M)的值(I)而且不能小於或等於右邊座標,找到後中止。(爲何要先從右往左?由於從左往右就會錯過太多大於的值從而相遇,致使排序錯亂)
 *          4.I和J都找到後,進行交換位置。
 *          5.重複1-4步驟直到兩個數相同的值(V),則將V和M互換位置。
 *          6.再以M爲中心點進行分割重複1-5的流程直至結束
 * @param   array $data 數據
 * @param   int $left 左邊座標
 * @param   int $right 右邊座標
 * @param   string $orderBy 正序/倒敘
 * @return  array $data
 */
function QuickSort($data, $left, $right, $orderBy = 'asc')
{
    $l = $left; // 左邊開始位置
    $r = $right; // 右邊開始位置
    if ($left >= $right) return [];
    $m = $data[$left]; // 基準數
    while ($l != $r) {
        while ($data[$r] >= $m && $r != $l) $r--;
        while ($data[$l] <= $m && $r != $l) $l++;
        if ($l < $r) {
            $n        = $data[$l];
            $data[$l] = $data[$r];
            $data[$r] = $n;
        }
    }
    $data[$left] = $data[$l];
    $data[$l]    = $m;
    $Q1          = QuickSort($data, $left, $l - 1, $orderBy);
    $data        = $Q1 + $data;

    $Q2   = QuickSort($data, $l + 1, $right);
    $data = $Q2 + $data;

    return $data;
}

PHP版本V2.0(推薦)

這個版本就很流弊了,比上面寫法快的太多太多,猶如一個天一個地。我拿第一個版本去對比發現差得太多了。我用v1版本寫法執行10000就消耗10s左右,而用v2這個寫法直接秒開。無論哪一種語言,實現邏輯都同樣,推薦參考:工具

/**
 * 快速排序 v2.0
 * 實現步驟:
 *        1.創建基準數(中間值)
 *        2.循環數據,大於基準數的存 right 數組,小於基準數的存 left 數組
 *        3.分類完成後,將 left、right 數組遞歸繼續分類,直至剩下一個數組爲止
 *        4.遞歸分類完成後,將小於基準數的數組 left 、 基準數 和 大於基準數的數組 進行合併
 * @param array $data
 * @return array
 */
function QuickSort($data)
{
    $left   = [];
    $right  = [];
    $count  = count($data);
    if ($count < 2) return $data;
    $median = $data[0]; // 基準數
    for ($i = 1; $i < $count; $i++) {
        $v = $data[$i];
        if ($v < $median) $left[] = $v; else $right[] = $v;
    }
    $left  = QuickSort($left);
    $right = QuickSort($right);
    $rt    = array_merge($left, [$median], $right);
    return $rt;
}

C語言版本

接下來就是C語言的快速排序版本V1.0(我第一次使用的快速排序思想,本身定義的版本號來區分下~^_^) 稍微改動了一下ui

#include <stdio.h>
#include <stdlib.h>
int a[101],n;
/**
* C語言實現快速排序v1.0
*/
void quicksort(int left, int right){
    int i,j,base;
    i = left;
    j = right;
  
    if (left>right) return ;
    // 1.第一步,定義基準數
    base = a[left]; 
  
    // 4.左座標不等於右座標時繼續迭代,等於則相遇
    while(left != right){
        // 2.若是右邊大於基準數則繼續遞減迭代至小於基準數中止
        while(left<right && a[right]>=base) right--;
        // 2.1 與左指針所在位置進行交換
        a[left] = a[right];
     
        // 3.若是左邊小於基準數則繼續遞增迭代至大於基準數中止
        while(left<right && a[left]<=base) left++;
        // 3.1 與右指針所在位置進行交換
        a[right] = a[left];
    }
    // 4.1 左右座標相遇替換基準數
    a[left] = base;
     
    // 5.重複1.2.3.4 遞歸
    quicksort(i, left-1); // 重複基準數左邊
    quicksort(left+1, j);
    return;
}
int main()
{
    int i,j;
    printf("=============快速排序==============\r\n");
    printf("請輸入數量:");
    scanf("%d", &n);
    for (i=1; i<=n; i++){
        scanf("%d", &a[i]);
    }
    
    quicksort(1, n);
    printf("快速排序結果:\r\n");
    
    for (i=1; i<=n; i++)
        printf("%d ", a[i]);
   
    getchar(); getchar();
    system("pause");
    return 0;
}

Javascript語言版本

這個在網上找到的,和v2的版本實現思想一致:spa

<script>
    function quickSort(arr){
        var left=[],right=[];
        if(arr.length<1){
            return arr;
        }
        var index = Math.floor(arr.length/2);
        var point = arr.splice(index,1);
        for(var i = 0; i<arr.length; i++){
            if(arr[i]<point){
                left.push(arr[i]);
            }else{
                right.push(arr[i]);
            }
        }
        return quickSort(left).concat(point,quickSort(right));
    }
    
    console.log(quickSort([1, 2, 3, 4, 6, 78, 1]))
</script>

4. 總結

最後,如看不明白,能夠用調試工具進行斷點調試,這樣會理解得更快更完全一些,但願此文章對你有幫助。指針

  • 做用:快速有效的進行數據排序
  • 優勢:佔內存小,耗時少
  • 缺點:也是有的,不穩定
  • 難度:O(NlogN),最差能夠和冒泡排序同樣0(N2)程度
  • 核心思想:創建基準是(中間值),小於基準數的往左移,大於基準數的往右移。整個排序最終遞歸進行合併整理,以此達到整個數據變成有序
相關文章
相關標籤/搜索