PHP排序算法

来源:互联网 发布:换头像软件 编辑:程序博客网 时间:2024/06/04 18:31

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


比较时间复杂度:



冒泡排序

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 = coung($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);