快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另一部分的全部數據都要小,而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序。更多介紹能夠百度百科,接下來直接上代碼算法
這個版本我看了以前有一篇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; }
這個版本就很流弊了,比上面寫法快的太多太多,猶如一個天一個地。我拿第一個版本去對比發現差得太多了。我用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語言的快速排序版本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; }
這個在網上找到的,和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>
最後,如看不明白,能夠用調試工具進行斷點調試,這樣會理解得更快更完全一些,但願此文章對你有幫助。指針