zoukankan      html  css  js  c++  java
  • 数据结构与算法之PHP排序算法(桶排序)

    一、基本思想
    桶排序是将待排序的数据分割成许多buckets,然后每个bucket各自排序,或用不同的排序算法,或者递归的使用bucket sort算法。也是典型的分而治之(divide-and-conquer)的策略。
     
    二、算法过程及PHP代码实现
    1)找出待排序数组arr中的最大值max、最小值min;
    2)设置一个定量的数组当作空桶,范围为min~max(min、max为步骤1求得的最小值、最大值);
    3)遍历待排序数组arr,计算每个元素arr[i]放的桶,把数据放到对应的桶里;
    4)如果桶不为空,对桶中的数据进行排序;
    5)遍历桶数组,把所有桶中排序好的元素放到一个新的数组里。
    例如:
    待排序数组为5,3,5,2,8,其最小值是2,最大值是8,可以在2-8的取值范围内定义一个桶数组$bucket,并且让所有的元素值都为0;
    对需要排序的数组进行循环遍历,将数据依次放到对应的桶中,即:
    首先是5,则使$bucket[5]++,继续遍历,$bucket[2]=1,$bucket[3]=1,$bucket[5]=2,$bucket[8]=1,
    然后循环$bucket数组,若$bucket[2]=1,则循环输出元素2一次,$arr[5]=2,则循环输出5两次,结果为 2 3 5 5 8
    PHP代码如下:
    <?php
    function bucketSort($arr) {
        // 设置木桶
        $bucket = [];
        $min = min($arr);
        $max = max($arr);
        // $bucket = array_fill($min, $max - $min + 1, 0);
        for ($m = $min; $m <= $max; $m++) {
            $bucket[$m] = 0;
        }
        // 将待排数据按照范围放到对应的木桶中
        $cnt = count($arr);
        for ($n = 0; $n < $cnt; $n++) {
            $bucket[$arr[$n]]++;
        }
        // 从木桶中拿出数据
        $result = [];
        for ($i = $min; $i <= $max; $i++) {
            if (($bucket[$i]) > 0) {
                for ($j = 1; $j <= $bucket[$i]; $j++) {
                    $result[] = [$i];
                }
            }
        }
        // 处理数组
        $res = [];
        foreach ($result as $v) {
            $res[] = $v[0];
        }
        return $res;
    }
     
    $arr = [12, 31, 85, 7, 41, 34, 10, 96];
    $res = bucketSort($arr);
    print_r($res);
    设置木桶也可以先确定木桶的个数,即n = (max - min) / arr.length + 1,其中,max、min为待排序数组的最大值、最小值,然后桶的范围为0-(n-1),后面的步骤同前面的3-5步相同。
    PHP代码如下:
    <?php
    function bucketSort(&$arr) {
        $min = min($arr);
        $max = max($arr);
        $n = $max - $min + 1;
        $buckets = [];
        for ($i = 0; $i < $n; $i++) {
            $buckets[$i] = 0;
        }
        for ($i = 0; $i < count($arr); $i++) {
            $buckets[$arr[$i] - $min]++;
        }
        $k = 0;
        for ($i = 0; $i < $n; $i++) {
            while ($buckets[$i]-- > 0) {
                $arr[$k++] = $i + $min;
            }
        }
    }
     
    三、效率分析
    对于N个待排数据,M个桶,
    1、时间复杂度:O(N+C),其中C=N*(logN-logM)
    2、空间复杂度:O(N+M),稳定性排序
    3、缺陷:
    1)参与排序的数组存放的必须是整数。
    2)数组中的最大数和最小数保持在一个合理的间距内。
    3)需要额外的内存空间。
     
    四、算法改进
    按着上述代码,如果要排序的范围是1-100万,将申请大量的内存,也就是设置了100万个桶。为了节省内存,可以改进这个算法,把待排序数组划分为n个大小相同的子区间(桶),然后基于某种映射函数,将待排序序列的元素映射到第i个桶中,再对每个桶中的所有元素排序,最后合并。
    1)确定元素的最大值max、最小值min、数组长度length;
    2)确定桶数:n = (max - min) / length + 1;
    3)确定桶的编号:0 ~ (n - 1);
    4)确定数组元素对应的桶的编号:index = (x - min) / length;
    5)对每个桶进行排序;
    6)合并所有桶的元素。
    PHP代码如下:
    <?php
    function bucketSort($arr) {
        $length = count($arr);
        $min = min($arr);
        $max = max($arr);
        $n = ceil(($max - $min) / $length) + 1;
        // 设置木桶
        $buckets = [];
        for ($i = 0; $i < $n; $i++) {
            $buckets[$i] = [];
        }
        // 将每个元素放入桶
        for ($i = 0; $i < $length; $i++) {
            $index = ceil(($arr[$i] - $min) / $length);
            $buckets[$index][] = $arr[$i];
        }
        // 对每个桶进行排序
        $res = [];
        for ($i = 0; $i < $n; $i++) {
            sort($buckets[$i]);
            // 合并所有桶中的元素
            $res = array_merge($res, $buckets[$i]);
        }
        return $res;
    }
    $arr = [12, 31, 85, 7, 41, 34, 10, 96];
    $res = bucketSort($arr);
    print_r($res);
    这种方法,只需要设置12个桶即可,大大的节省了空间。
  • 相关阅读:
    FFmpeg filter简介
    CR, LF, CR/LF 回车 换行
    Windows / VS下不同类型变量转换
    Android库分析工具(崩溃反编译)
    adb install使用说明
    多媒体文件格式探测⑨
    多媒体文件格式之AVI
    多媒体文件格式之RMVB
    多媒体文件格式之TS
    多媒体文件格式之FLV
  • 原文地址:https://www.cnblogs.com/sunshineliulu/p/8671245.html
Copyright © 2011-2022 走看看