快速排序由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>
最后,如看不明白,能够用调试工具进行断点调试,这样会理解得更快更完全一些,但愿此文章对你有帮助。指针