排序是算法最基础的部分,在平常的开发中,我们也会用上各种各样的排序。 排序的算法很多,这里我先来实现最常用也比较经典的冒泡排序,插入排序,选择排序。

冒泡排序只会操作相邻的两个数据,每次冒泡都对相邻的两个数据进行比较,不满足大小的要求那么就互换位置。所以一次冒泡排序就能让一个元素移到它应该存在的位置。重复n次,就完成了排序。
当然了,当进行某一次冒泡排序时,如果不存在数据交换了。说明已经达到完全有序,不需要再进行后续的冒泡操作了,所以我们应该给他标示一下。
//冒泡排序
function bubbleSort(array $data){
if(count($data)==1){
return $data;
}
for ($i=0;$i<count($data);$i++){
$isOver=false;
for ($j=0;$j<count($data)-$i-1;$j++){
if($data[$j]>$data[$j+1]){
$temp=$data[$j];
$data[$j]=$data[$j+1];
$data[$j+1]=$temp;
$isOver=true;
}
}
if(!$isOver){
break;
}
}
return $data;
}
//$data=[2,6,67,4,5,34,53,13,6];
//var_dump(bubbleSort($data));
以上冒泡排序还能再优化
一.冒泡排序只涉及到相邻元素之间的位置交换,只需要常量的临时空间,所以它的时间复杂度是O(n),是一种原地排序。
二.冒泡排序只有交换才可以改变元素之间的顺序关系,当相邻的两个元素相等的时候,我们不进行交换,相同的数据在排序的位置不会发生改变,所以冒泡排序是稳定排序。
三.冒泡排序最坏的数据顺序刚好都是倒序,所以时间复杂度是O(n2),最好的情况下是有序的数据,我们只要进行一次冒泡,时间复杂度是O(n),所以冒泡排序的时间复杂度是O(n2).

插入排序把数据分成了两个区,左边有序区和右边无序区。每次从无序区中取出一个数,插入到对应有序区的位置。并且保证有序区的元素一直都是有序的。初始化的时候数组的第一个元素就是有序区。
插入排序也需要比较元素的大小以及对应的元素的移动。当我们拿到一个未排序区的数据和已排序区进行比较,找到合适的位置插入之后,我们还需要把插入点之后的位置全部往后面移动一位,给他腾出位置插入。
插入排序和冒泡排序一样,是稳定的排序,同时它的最坏情况倒序下,时间复杂度也是O(n2)。(插入排序还可以进行优化)
function insertOrder($data){
for ($i=0;$i<count($data)-1;$i++){
$temp=$data[$i];
for($j=$i-1;$j>=0;$j--){
if($data[$j]>$temp){
$data[$j+1]=$data[$j];
}else{
break;
}
}
$data[$j+1]=$temp;//调整比较数
}
return $data;
}

选择排序和插入排序一样,也区分有序区和无序区,只是选择排序每次是从无序区中拿出一个最小的数,插入到已排序区间的末尾。
值得注意的是选择排序不是一个稳定的排序。选择排序每次都要找剩余未排序元素的最小值,并和前面的数据互换位置,这就破坏了稳定性。
function selectOrder($data){
if(count($data)<=1){
return $data;
}
for ($i=0;$i<count($data);$i++){
$min=$i;
for($j=1;$j<count($data);$j++){
if($data[$j]<$data[$min]){
$min=$j;
}
}
if($min !==$i){
$temp=$data[$i];
$data[$i]=$data[$min];
$data[$min]=$temp;
}
}
return $data;
}
$data=[99,2,6,67,4,5,34,53,13,6,55];
var_dump(bubbleSort($data));
冒泡排序和插入排序时间复杂度一样,都是稳定的排序,同时都是原地排序,但是实际上,插入排序更受欢迎。是因为冒泡排序每次进行位置交换需要三个赋值的操作,而插入排序只需要一次赋值。在数量体越来越大的情况下,性能方面冒泡排序会比插入排序差很多。
