数组的排序算法

<?php

/*

 * 内部排序:

 * 指将需要的数据处理所有数据都加载到内部存储器中进行排序。包括:交换式排序法、选择排序、插入排序、快排

 * 外部排序:

 * 数据量过大:无法全部加载到内存中,需要借助外部存储器进行排序:合并排序、直接合并排序

 */

/*

 * 冒泡排序算法 通过对数组元素从后往前的移动,把最大往后移动 最小往前移动 进行位置上的交换

 * 如果每次数据没有进行交换 说明排序有序,不需要进行排序 使用key开关来进行排序的控制

 */

$arr1 = array(

    34,

    23,

    1,

    3,

    21,

    66,

    78,

    38,

    40,

    12

);

// 冒泡排序的函数 这里把每一个算法封装成一个方法 方便以后的调用 直接操作原数组 要把地址传过去

function bubbleSort(&$arr)

{

    // 中间交换介质 容器

    $tmp = 0;

    // 改循环控制外层循环 控制次数

    for ($i = 0; $i < count($arr); $i ++) {

        // 设置比较的开关

        $key = false;

        // 该层循环用来控制每轮循坏比较次数

        for ($j = 0; $j < count($arr) - 1 - $i; $j ++) {

            if ($arr[$j] > $arr[$j + 1]) {

                $tmp = $arr[$j + 1];

                $arr[$j + 1] = $arr[$j];

                $arr[$j] = $tmp;

                $key = true;

            }

            // 如果没有比较说明顺序已经排列完毕 不需要再进行比较

            if (! $key) {

                break;

            }

        }

    }

}

 

/*

 * 选择排序算法 在要排序的一组数中,选出最小的一个数与第一个位置的数交换。

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

 */

function selectSort(&$arr)

{

    // 双重循环完成,外层控制轮数,内层控制比较次数;

    for ($i = 0; $i < count($arr) - 1; $i ++) {

        // 先假设最小的值的位置

        $minValue = $arr[$i];

        // 记录最小值的下标

        $minIndex = $i;

        for ($j = $i + 1; $j < count($arr); $j ++) {

            // $minValue 是当前已知的最小值

            if ($minValue > $arr[$j]) {

                // 比较,发现更小的,记录下最小值的位置;并且在下次比较时采用已知的最小值进行比较。

                $minValue = $arr[$j];

                $minIndex = $j;

            }

        }

        // 已经确定了当前的最小值的位置,保存到$minIndex中。如果发现最小值的位置与当前假设的位置$i不同,则位置互换即可。

        if ($minIndex != $i) {

            $tmp = $arr[$i];

            $arr[$i] = $arr[$minIndex];

            $arr[$i] = $tmp;

        }

    }

}

 

/*

 * 插入排序

 * 在要排序的一组数中,假设前面的数已经是排好顺序的,现在要把第n个数插到前面的有序数中,

 * 使得这n个数也是排好顺序的。如此反复循环,直到全部排好顺序。

 */

function insertSort(&$arr)

{

    for ($i = 1; $i < count($arr); $i ++) {

        // 准备插入数的位置

        $insertValue = $arr[$i];

        // 插入的位置

        $insertIndex = $i - 1;

        // 如果条件满足 说明我们还没有找到合适的位置

        while ($insertIndex >= 0 && $insertValue < $arr[$insertIndex]) {

            // 同时要把数值后移

            $arr[$insertIndex + 1] = $arr[$insertIndex];

            $insertIndex --;

        }

        

        $arr[$insertIndex + 1] = $insertValue;

    }

}

// 插入排序的优化代码 从大到小

function insertSortGooda($arr)

{

    for ($i = 1; $i < count($arr); $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;

}

/*快速排序

*选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,

*一部分比基准元素小,一部分大于等于基准元素。此时基准元素在其排好序后的正确位置,

*然后再用同样的方法递归地排序划分的两部分。

*/

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);

}

// 把遍历的输出代码封装成一个方法

function printfArray($arr)

{

    // 数组的索引 遍历和输出

    foreach ($arr as $key => $value) {

        echo $key . "=" . $val . "<br/>";

    }

}

posted @ 2017-04-03 16:29  乌托邦小余  阅读(369)  评论(0编辑  收藏  举报