PHP排序算法

各种排序的稳定性,时间复杂度和空间复杂度总结:

比较时间复杂度:

 

冒泡排序

1,比较相邻的元素。如果第一个比第二个大,就交换他们两个

2,对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。这样,最后的元素应该是最大的数

3,针对所有的元素重复以上的步骤,除了最后一个

4,持续每次对越来越少的元素重复上面的步骤,知道没有任何一个数字需要比较

效果图:

代码:

 

function bubble_sort($arr){
      $len = count($arr);
      //该层循环控制需要冒泡的轮数
      for($i=1;$<$len;$i++){
           //该层循环用来空值每轮需要比较的次数,冒出一个数
           for($k=0;$k<$len-$i;$k++){
                if($arr[$k]>$arr[$k+1]){
                     $tmp = $arr[$k+1];
                     $arr[$k+1] = $arr[$k];
                     $arr[$k]=$tmp;
                }
           }
      }
      return $arr;
}

 

 

快速排序

1,从数列中跳出一个元素,称为“基准”

2,重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准大的摆放在基准后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个成为分区操作。

3,递归地把小于基准值元素的子数列和大于基准值元素的子数列排序。

效果图:

代码:

 

function qiuck_sort($arr){
      //先判断是否需要继续进行(递归出口)
      $length = count($arr);
      if($length <= 1){
            return $arr;
      }
      //取第一个数作为基准
      $base_num = $arr[0];
      $left_array = array();//小于基准的
      $right_array = array();//大于基准的
      for($i=1;$i<$length;$i++){
           if($base_num>$arr[$i]){
                $left_array[] = $arr[$i];
           }else{
                $right_array[] = $arr[$i];
           }
      }
      $left_array = quick_sort($left_array);//递归
      $right_array = quick_sort($$right_array);//递归
      return array_merge($left_array,array($base_num),$right_array);
}

 

 

选择排序
1,在未排序序列中找到最小元素与第一个位置元素交换

2,从剩余未排序元素中继续寻找最小元素与第二个位置的数交换

3,依此类推,直至虽有元素均排序完毕

效果图:

代码:

 

function select_sort($arr){
      //双重循环,外层空值论述,内层空值比较次数
      $len = count($arr);
      for($i=0;$i<$len-1;$i++){
           //先假设最小的值的位置
           $p = $i;
           for($j=$i+1;$j<$len;$j++){
                if($arr[$p] > $arr[$j]){
                     //比较,发现更小的,记录下最小值的位置;并且在下次比较时采用一直的最小值进行比较
                     $p = $j;
                }
           }
           //已经确定了当前的最小值的位置,保存到$p中。如果发现最小值的位置与当前假设的位置$i不同,则位置呼唤即可。
           if($p != $i){
                $tmp = $arr[$p];
                $arr[$p] = $arr[$i];
                $arr[$i] = $tmp;
           }
      }
      return $arr;
}

 

 

插入排序

1,从第一个元素开始,该元素可以认为已经被排序

2,取出下一个元素,在已经排序的元素序列中从后向前

3,如果该元素(已排序)大于新元素,将该元素移到下一个位置

4,重复步骤3,直到找到已排序的元素小于或者等于新元素的位置

5,将新元素插入到该位置中

6,重复步骤2

(在要排序的一组数中,假设前面的数已经是拍好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,知道全部排好顺序)

 

function insert_sort($arr){
      $len = count($arr);
      for($i=1,$i<$len;$i++){
           $tmp = $arr[$i];
           //内层循环控制,比较并插入
           for($j=$i-1;$j>=0;$j--){
                if($tmp<$arr[$j]){
                     //发现插入的元素要小,交换位置,将后边的元素与前面的元素互换
                     $arr[$j+1] = $arr[$j];
                     $arr[$j] = $tmp;
                }else{
                     //如果碰到不需要移动的元素,由于是已经排序好的数组,则前面的就不需要再次比较了。
                     break;
                }
           }
      }
      return $arr;
}

 

 

希尔排序

希尔排序,也称递减增量排序算法,是插入排序的一种高速而稳定的改进版本
1,插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率

2,但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位

效果图:

 

归并排序

1,申请空间,使其大小位两个已经排序序列之和,该空间用来存放合并后的序列

2,设置两个指针,最初位置分别为两个已经排序序列的起始位置

3,比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置

4,重复步骤3直到某一指针达到序列位

5,将另一序列剩下的所有元素直接复制到合并序列尾

效果图:

代码:

 

$a = [1, 4, 6, 8, 10, 14, 16];
$b = [2, 3, 5, 8, 9, 11];
function merge_sort($a, $b)
{
    $a_i = $b_i = 0;
    $count_a = count($a);
    $count_b = count($b);
    $ret = [];
    while ($a_i < $count_a && $b_i < $count_b) {
        if ($a[$a_i] > $b[$b_i]) {
            array_push($ret, $b[$b_i]);
            $b_i++;
        } else {
            array_push($ret, $a[$a_i]);
            $a_i++;
        }
    }
    if ($a_i < $count_a) {
        $ret = array_merge($ret, array_slice($a, $a_i));
    }
    if ($b_i < $count_b) {
        $ret = array_merge($ret, array_slice($b, $b_i));
    }
    return $ret;
}

$ret = merge_sort($a, $b);
echo implode(',', $ret);

 

 

 

 

 

堆排序

起始节点为1的父子关系: 父节点k, 子节点为2K、2k+1     子节点j, 父节点为 floor(j/2)  floor为向下取整
起始节点为0的父子关系: 父节点k, 子节点为2K+1, 2k+2   子节点j, 父节点为 floor((j-1)/2)
参数$k为调整点位置, $lenth为数组长度,也就是从1起始到最后一个节点的坐标.

效果图:

代码:

 

function fixDown(&$arr, $k, $lenth)
{
  while(2*$k<=$lenth) { //只要当前节点有子节点, 就需要继续该循环
    $j = $k*2;
    if ($j<$lenth && $arr[$j]<$arr[$j+1]) $j++;  // 只要子节点有右节点,且右节点比左节点大,那么切换到右节点操作。
    if ($arr[$j] < $arr[$k]) break; // 如果子节点都没有父节点大, 那么调整结束。
    exch($arr[$j], $arr[$k]);
     $k = $j;
  }
}

function exch(&$a, &$b) {
  $tmp = $a; $a = $b; $b = $tmp;
}

function headSort(&$arr)
{
  $len = count($arr);
  array_unshift($arr, NULL);
  for($i=$len/2;$i>=1;$i--) {
    fixDown($arr, $i, $len);
  }
  while($len>1) {
    exch($arr[1], $arr[$len]);
    fixDown($arr, 1, --$len);
  }
  array_shift($arr);
}
$arr = array(4,6,4,9,2,3);
headSort($arr);

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值