目录

许多人都说算法是程序的核心,算法的好坏决定了程序的质量。排序算法还是应该掌握的,它是程序开发的必备工具。

1、冒泡排序

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

步骤描述:

  • 1、 将 A[n-1] 与 A[n] 进行比较,若 A[n] < A[n-1] ,则交换两元系的位置。
  • 2、 修改数组下标,使需要比较的两个元素为 A[n-1] 和 A[n-2] ,重复步骤(1),对这两个元素进行比较。重复这个过程,直到对 A[1] 和 A[0] 进行比较完为止。完成第1遍扫描。
  • 3、 经过第1遍扫描后,最小的元素已经像气泡一样“浮”到最上面,即位于元素 A[0] 中了。接下来重复前面的步骤,进行第2遍扫描,只是扫描结束位置到 A[2] 与 A[1] 进行比较完为止(因为A[0]中已经是最小的数据,不用再进行比较)。
  • 4、 通过 n-1 遍扫描,前 n-1 个数都已经排序完成,最后一个元素 A[n] 肯定就是最大的数了。至此,完成排序操作。

代码实现:


$arr = [4,5,6,2,8,9,5,6,7,7,8,89,9,9,7,8,9,0,8,44,88,99,39];
function bubbleSort($arr){
    $len = count($arr);
    //该层循环控制 需要冒泡的轮数
    for ($i = 0; $i < $len - 1 ; $i++){
        //该层循环用来控制每轮 冒出一个数 需要比较的次数
        for ($j = 0; $j < $len -1 - $i; $j++){
            //如果当前值大于自己后面值,进行位置互换
            if ($arr[$j] > $arr[$j+1]){
                $toRightNum = $arr[$j];
                $arr[$j] = $arr[$j+1];
                $arr[$j+1] = $toRightNum;
            }
        }
    }
    return $arr;
}

2、选择排序

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

步骤描述:

  • 1、 维护数组中最小的前 n 个元素的已排序序列。
  • 2、 每次从剩余未排序的元素中选取最小的元素,将其放在已排序序列的后面,作为序列的第 n+1 个记元素。
  • 3、 以空序列作为排序工作的开始,直到未排序的序列里只剩一个元素时(它必然为最大),只需直接将其放在已排序的记录之后,整个排序就完成了。

代码实现

$arr = [4,5,6,2,8,9,5,6,7,7,8,89,9,9,7,8,9,0,8,44,88,99,39];
//选择排序:倒序
function selectSortDesc($arr){
    $length = count($arr);
    //双重循环完成,外层控制轮数,内层控制比较次数
    for ($i=0;$i<$length;$i++){
        //默认把第一个当做大的值
        $bigest = $i;
        //第一轮,第一个元素和第二个以后的元素逐个比较,找出最大的值对应的key
        //第二轮,第二个元素和第三个以后的元素逐个比较,找出最大的值对应的key
        //以此类推
        for ($j=$i+1;$j<$length;$j++){
            if ($arr[$bigest] < $arr[$j]){
                //如果当前值小于下一个值,则把下一个值的key赋值给$bigest
                $bigest = $j;
            }
        }
        if ($bigest != $i){
            //如果最终找到的最大的值的key不等于当前轮的key,则进行替换
            $temp = $arr[$bigest];
            $arr[$bigest] = $arr[$i];
            $arr[$i] = $temp;
        }
    }
    return $arr;
}

3、插入排序

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

步骤描述

  • 1、 对于第1个元素,因为没有比较,将其作为已经有序的序列。
  • 2、 从数组中获取下一个元素,在已经排序的元素序列中从后向前扫描,并进行判断。
  • 3、 若排序序列的元素大于新元素,则将该元素向后移动一位。
  • 4、 重复步骤(3),直到在已排序的元素中找到小于或者等于新元素的元素,将新元素插入到该元素的后面。
  • 5、 重复步骤(2) ~ (4),直到完成排序。

代码实现:

$arr = [4,5,6,2,8,9,5,6,7,7,8,89,9,9,7,8,9,0,8,44,88,99,39];
/**
 * 插入排序:正序
 * @param $arr
 * @return mixed
 */
function insertSortAsc($arr){
    $length = count($arr);
    //第0个元素默认当做已排好序的
    for ($i=1;$i<$length;$i++){
        //每次取出第一个未排序的值
        $firstNotSortValue = $arr[$i];
        //从已排好序的最后一个元素开始往前找
        for ($j=$i-1;$j>=0;$j--) {
            if ($firstNotSortValue < $arr[$j]) {
                $arr[$j+1] = $arr[$j];
                $arr[$j]   = $firstNotSortValue;
            } else {
                //如果碰到不需要移动的元素,由于是已经排序好是数组,则前面的就不需要再次比较了,跳出本层循环提高排序效率
                //跳出循环的效率比不跳出循环的效率高出大约40%
                break;
            }
        }
    }
    return $arr;
}

4、快速排序

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

步骤描述

  • 1、 从数列中挑出一个元素,以该元素为“基准”。
  • 2、 扫描一遍数列,将所有比“基准”小的元素排在基准前面,所有比“基准”大的元素排在基准后面。
  • 3、 通过递归,将各子序列划分为更小的序列,直到把小于基准值元素的子数列和大于基谁值元素的子数列排序。

代码实现:

$arr = [4,5,6,2,8,9,5,6,7,7,8,89,9,9,7,8,9,0,8,44,88,99,39];
function quickSort($arr){
    $length = count($arr);
    if ($length <= 1) return $arr;
    //取出一个值作为中间值
    $mid = $arr[0];
    //左右护法
    $left = [];
    $right = [];
    for ($i=1;$i<$length;$i++){
        if ($arr[$i] < $mid) {
            $left[] = $arr[$i];
        } else {
            $right[] = $arr[$i];
        }
    }
    $left = quickSort($left);
    $right = quickSort($right);
    return array_merge($left,array($mid),$right);
}

阅读原文


本文收藏来自互联网,仅用于学习研究,著作权归原作者所有,如有侵权请联系删除

markdown @tsingchan

引用格式为收藏注解,比如本句就是注解,非作者原文。