目录
1.快速排序
tip:从1开始每个数和arr[0]比较,分别放进左右数组,递归,合并
代码:
function quicksort($arr){
if(count($arr) <=1){
return $arr;
}
$larr = [];
$rarr = [];
for($i=1;$i<count($arr);$i++){
if($arr[$i] <= $arr[0]){
$larr[] = $arr[$i];
}else{
$rarr[] = $arr[$i];
}
}
$left = quicksort($larr);
$right = quicksort($rarr);
return array_merge($left,array($arr[0]),$right);
}
2.插入排序
tip:从数组第二位开始遍历,和前面的数比较,符合就互换位置,直到遍历所有数
代码:
function insert_sort($arr){
for($i=1;$i<count($arr);$i++){
//待插入的值
$temp = $arr[$i];
//待比较的值
$j = $i-1;
while($j>=0&&$temp>$arr[$j])
{
$arr[$j+1] = $arr[$j];
$arr[$j] = $temp;
$j--;
}
$arr[$j+1] = $temp;
}
return $arr;
}
3.希尔排序
tip:带基数的插入排序
代码:
function shellsort($arr){
//初始化增量
$increment = count($arr);
while($increment > 1)
{
$increment = intval($increment/3) + 1;
for($i=$increment;$i<count($arr);$i++){
//待插入值
$temp = $arr[$i];
//待比较位置
$j = $i - $increment;
//降序排列
while($j>=0&&$temp>$arr[$j])
{
$arr[$j+$increment] = $arr[$j];
$arr[$j] = $temp;
$j = $j-$increment;
}
$arr[$j+$increment] = $temp;
}
}
return $arr;
}
4.归并排序
tip:把数组切割,直到不可分割,排序单个小数组,然后合并,递归执行
代码:
function merge_sort(&$arr){
$count = count($arr);
if($count <= 1){
return $arr;
}
$mid = intval($count/2);
$left = array_slice($arr, 0,$mid);
$right = array_slice($arr, $mid);
merge_sort($left);
merge_sort($right);
$merge=[];
while(count($left)&&count($right)){
$merge[] = $left[0]<$right[0] ? array_shift($left):array_shift($right);
}
$arr = array_merge($merge,$left,$right);
// var_dump($arr);
}
5.堆排序
tip:以最后一个父节点为起始节点,比较子节点,把最小值或最大值移动到父节点,遍历所有父节点后
//最小值或最大值移动到根节点,把根节点和尾节点交换,数组长度减一继续遍历
代码:
function heep_sort($arr)
{
//获取数组的长度
$arrsize = count($arr);
while($arrsize > 0)
{
//遍历每个节点,和子节点比较得到最小值
for($i = intval($arrsize/2)-1;$i>=0;$i--){
//起初认定当前节点最小
$min = $i;
//如果存在左节点
if($i*2+1 < $arrsize){
//比较和左节点的大小,如果左节点的值更小,那么进行交换
if($arr[$i] > $arr[$i*2+1]){
$temp = $arr[$i];
$arr[$i] = $arr[$i*2+1];
$arr[$i*2+1] = $temp;
}
}
//如果存在又节点
if($i*2+2 < $arrsize){
//比较和右节点的大小,如果右节点的值更小,那么进行交换
if($arr[$i] > $arr[$i*2+2]){
$temp = $arr[$i];
$arr[$i] = $arr[$i*2+2];
$arr[$i*2+2] = $temp;
}
}
//执行完一次遍历,跳到下一个非叶子节点
}
//成功找到第一个最小值,使数组长度减一
//首尾交换,保存最小值
$temp = $arr[0];
$arr[0] = $arr[$arrsize-1];
$arr[$arrsize-1] = $temp;
$arrsize--;
}
return $arr;
}
6.冒泡排序
tip:这个就不用说了,很简单
代码:
function maopao($arr){
$count=count($arr);
for($i=0;$i<$count;$i++){
for($j=0;$j<$count-$i-1;$j++){
if($arr[$j]<$arr[$j+1]){
$temp = $arr[$j];
$arr[$j] = $arr[$j+1];
$arr[$j+1] = $temp;
}
}
}
var_dump($arr);
}
7.计数排序
tip:时间复杂度O(n+k),n为排序的数的个数,k为要排序的数的最大值,消耗空间来达到快捷,空间换时间,
//计算数组的最大和最小值,创建一个键从min到max的数组,计数排序数组的每个值的个数,然后向一个新数组填充入栈
步骤:
找出待排序的数组中最大和最小的元素
统计数组中每个值为i的元素出现的次数,存入数组C的第i项
对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
反向填充目标数组:将每个元素i放在新数组的第C[i]项,每放一个元素就将C[i]减去1
代码:
function countsort($arr){
$count = count($arr);
$carr = [];
$min = $arr[0];
$max = $arr[0];
//找最大值和最小值
for($i=1;$i<$count;$i++){
if($arr[$i]<$min){
$min = $arr[$i];
}
if($arr[$i]>$max){
$max = $arr[$i];
}
}
for($i=$min;$i<=$max;$i++){
$carr[$i] = 0;
}
for($i=1;$i<$count;$i++){
$carr[$arr[$i]]++;
}
$newarr = [];
for($i=$max;$i>=$min;$i--){
while($carr[$i]>0)
{
$newarr[]=$i;
$carr[$i]--;
}
}
var_dump($newarr);
}
8.基数排序
代码:
//默认降序
function radixSort($arr, $desc=true)
{
if (count($arr) <= 1) {
return $arr;
}
$max = $arr[0];
for($i=1;$i<count($arr);$i++)
{
if ($arr[$i] > $max){
$max = $arr[$i];
}
}
$n = 0;//记录最大数的位数
while($max > 1){
$max = $max/10;
$n++;
}
for($j=1;$j<=$n;$j++){
$tmp_arr = [];
for($k=0;$k<count($arr);$k++){
$r = pow(10,$j-1);
$num = $arr[$k] > $r ? intval($arr[$k]/$r)%10 : 0;
$tmp_arr[$num][] = $arr[$k];
}
$arr=[];
if ($desc) {
for($m=9;$m>=0;$m--)
{
if (!empty($tmp_arr[$m])){
for($p=0;$p<count($tmp_arr[$m]);$p++){
$arr[] = $tmp_arr[$m][$p];
}
}
}
} else {
for($m=0;$m<=9;$m++)
{
if (!empty($tmp_arr[$m])){
for($p=0;$p<count($tmp_arr[$m]);$p++){
$arr[] = $tmp_arr[$m][$p];
}
}
}
}
}
return $arr;
}
9.桶排序
代码:
function bucketSort($arr, $bucketSize = 5)
{
if (count($arr) === 0) {
return $arr;
}
$minValue = $arr[0];
$maxValue = $arr[0];
for ($i = 1; $i < count($arr); $i++) {
if ($arr[$i] < $minValue) {
$minValue = $arr[$i];
} else if ($arr[$i] > $maxValue) {
$maxValue = $arr[$i];
}
}
$bucketCount = floor(($maxValue - $minValue) / $bucketSize) + 1;
$buckets = array();
for ($i = 0; $i < $bucketCount; $i++) {
$buckets[$i] = [];
}
for ($i = 0; $i < count($arr); $i++) {
$buckets[floor(($arr[$i] - $minValue) / $bucketSize)][] = $arr[$i];
}
$arr = array();
for ($i = 0; $i < count($buckets); $i++) {
$bucketTmp = $buckets[$i];
sort($bucketTmp);
for ($j = 0; $j < count($bucketTmp); $j++) {
$arr[] = $bucketTmp[$j];
}
}
return $arr;
}
10.选择排序
tip:思路分析:在要排序的一组数中,选出最小的一个数与第一个位置的数交换。
然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
代码:
function select_sort($arr){
$count=count($arr);
//循环次数
for($i=0;$i<$count-1;$i++){
//假设最小值的位置
$p = $i;
for($j=$i+1;$j<$count;$j++){
if($arr[$p]>$arr[$j]){
$p = $j;
}
}
if($p!=$i){
//说明最小值发生变化
$temp = $arr[$p];
$arr[$p] = $arr[$i];
$arr[$i] = $temp;
}
}
var_dump($arr);
}
速度测试:
//测试 5000个0-999的随机数
//基数排序 0ms
//堆排序 8ms
//希尔排序 22ms
//插入排序 5ms
//归并排序 0-1ms 20000个数在2ms内 分割
//快速排序 0ms 20000个数在1ms内 递归
//计数排序 0ms 1000000个数在3ms内 快但消耗空间
//冒泡排序 12ms 最慢
//选择排序 5ms