计数排序[PHP]

计数排序
GitHub源码

  1. 获取序列中的最小值min和最大值max O(n)
  2. 统计min - max之间所有值在序列中的出现次数 O(n)
  3. 顺序输出min - max的所有值,次数为0不输出,其余次数为多少就输出多少 O(k) k为数据范围

    例如序列为: 2, 4, 6, 9, 4, 8

    1. min = 2, max = 9, n为6,k为8
    2. 统计出现次数为
      [2 => 1, 3 => 0, 4 => 2, 5 => 0, 6 => 1, 7 => 0, 8 => 1, 9 => 1]
    3. 输出结果为
      2, 4, 4, 6, 8, 9

    很明显,计数排序的复杂度为O(n) + O(k),也就是和数据量和数据范围有关.
    若n和k相近,则可认为是O(n)
    同时,因为要统计出现次数,如果数据范围过大而数据又很稀疏,造成的空间浪费比较大

class CountSort
{
    private $originalData = [];
    private $rangeMap = [];
    private $resultData = [];

    public function __construct($original = [])
    {
        $this->originalData = $original;
    }

    public function sort()
    {
        list($min, $max) = $this->calculateDataRange();
        $this->statisticNumberOfOccurrence($min, $max);
        $this->resultData = $this->generateResult();
        return $this->resultData;
    }

    protected function calculateDataRange()
    {
        $max = null;
        $min = null;

        foreach ($this->originalData as $value) {
            if (!is_null($max)) {
                if ($value > $max) {
                    $max = $value;
                }
            } else {
                $max = $value;
            }

            if (!is_null($min)) {
                if ($value < $min) {
                    $min = $value;
                }
            } else {
                $min = $value;
            }
        }

        return [$min, $max];
    }

    protected function statisticNumberOfOccurrence($min, $max)
    {
        for ($i = $min; $i <= $max; $i++) {
            $this->rangeMap[$i] = 0;
        }

        foreach ($this->originalData as $value) {
            $this->rangeMap[$value]++;
        }
    }

    protected function generateResult()
    {
        $result = [];

        foreach ($this->rangeMap as $key => $value) {
            if ($value != 0) {
                for ($i = 0; $i < $value; $i++) {
                    array_push($result, $key);
                }
            }
        }
        return $result;
    }
}

$testData = [2, 3, 4, 3, 10, 30, 20, 15, 10, 12, 33];

$countSort = new CountSort($testData);
echo '<pre>';
var_dump($countSort->sort());
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值