因为之前没有编程基础,最近才知道排序算法这个概念,原来平时在操作数组的时候是用到“算法”这玩意的。

从网上找了下资料,都一个来源;用$arr=array(1,43,54,62,21,66,32,78,36,76,39); 做例子排序。

1. 冒泡排序

1.1 原理

在要排序的一组数中,对当前还未排好的序列,从前往后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即,每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。

1.2 代码实现:

function bubbleSort($arr)
{
    $len=count($arr);

    //该层循环控制 需要冒泡的轮数
    for($i=1;$i<$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.3 理解:

假设有10个数:

没排完 排完
********* * (没排完的数中冒出一个最大的)
******** ** (没排完的数中冒出一个最大的放到排完的中,成为第二大的)
…… ……
…… ……
* ********* (直到没排完的只剩一个最小的,排序完成;过程中没排完的实际上是混序的,两两冒泡不会有排序效果,只是筛选出哪个大哪个小)

2. 选择排序

2.1 原理

在要排序的一组数中,选出最小的一个数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。

2.2 代码实现

function selectSort($arr) {
    //双重循环完成,外层控制轮数,内层控制比较次数
    $len=count($arr);
    for($i=0; $i<$len-1; $i++) {
        //先假设最小的值的位置
        $p = $i;
        for($j=$i+1; $j<$len; $j++) { //$arr[$p] 是当前已知的最小值
            if($arr[$p] > $arr[$j]) {
                //比较,发现更小的,记录下最小值的位置;并且在下次比较时采用已知的最小值进行比较。
                $p = $j;
            }
        }

        //已经确定了当前的最小值的位置,保存到$p中。如果发现最小值的位置与当前假设的位置$i不同,则位置互换即可。
        if($p != $i) {
            $tmp = $arr[$p];
            $arr[$p] = $arr[$i];
            $arr[$i] = $tmp;
        }
    }

    //返回最终结果
    return $arr;
}

2.3 理解

假设有10个数:

排完 没排完
* ********* (所有中抽出一个最小的,放到第一个)
** ******** (没排完的抽出一个最小的,放到第二个)
…… ……
…… ……
********* * (直到抽完所有的数,排序完成)

3. 插入排序

3.1原理

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

3.2 代码实现

function insertSort($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;
}

3.3 理解

假设有10个数:

排完 没排完
* ********* (拿出没排完的第一个数,到排完的中进行排序)
** ******** (拿出没排完的第一个数,到排完的中进行排序)
…… ……
…… ……
********* * (拿出没排完的最后一个数,到排完的中进行排序;期间是两两比较方式)

4. 快速排序

4.1 原理

选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素。此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

4.2 代码实现

function quickSort($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);
}

4.3 理解

假设有10个数:

小于拿出                                拿出            大于拿出
***                                        *            ******
小于拿出    再拿出        大于拿出    |    之前拿出    |    小于拿出    再拿出    大于拿出
    *        *            *        |        *        |    **            *        ***
… …
… …

如此循环直到最后全部拆开,再合起来,排序完成。

**********

5. 总结

  • 冒泡排序: 逐渐筛选出最大值
  • 选择排序:逐渐筛选出最小值
  • 插入排序:按顺序一个一个取出进行排序
  • 快速排序:逐渐递归拆分进行排序,直至全部拆分排序完成