ZetCode

PHP 基数排序算法

最后修改于 2025 年 4 月 16 日

基本定义

算法是一种逐步解决问题或执行计算的程序。排序算法将元素按特定顺序排列。

常见的排序算法包括冒泡排序、选择排序、插入排序、归并排序、快速排序、堆排序和基数排序。 它们各自具有不同的时间和空间复杂度特征。

基数排序概述

基数排序是一种非比较型整数排序算法。 它通过从最低有效位到最高有效位对数字进行分组来处理数字。

基数排序的时间复杂度为 O(nk),其中 n 是元素的数量,k 是最长数字中的位数。 它对于大型数据集非常有效。

数值基数排序(升序)

此示例演示了对正整数进行升序的基数排序。

numeric_radix_sort.php
<?php

function radixSort(array $arr): array {
    $maxDigits = max(array_map('strlen', array_map('strval', $arr)));
    
    for ($digit = 0; $digit < $maxDigits; $digit++) {
        $buckets = array_fill(0, 10, []);
        
        foreach ($arr as $num) {
            $digitVal = (int) (($num / (10 ** $digit)) % 10);
            $buckets[$digitVal][] = $num;
        }
        
        $arr = array_merge(...$buckets);
    }
    
    return $arr;
}

$numbers = [170, 45, 75, 90, 802, 24, 2, 66];
$sorted = radixSort($numbers);

print_r($sorted); // [2, 24, 45, 66, 75, 90, 170, 802]

该算法处理每个数字位,将数字分配到基于当前数字的桶中,然后按顺序收集它们。

数值基数排序(降序)

此修改后的版本通过反转桶的顺序对数字进行降序排序。

numeric_radix_sort_desc.php
<?php

function radixSortDesc(array $arr): array {
    $maxDigits = max(array_map('strlen', array_map('strval', $arr)));
    
    for ($digit = 0; $digit < $maxDigits; $digit++) {
        $buckets = array_fill(0, 10, []);
        
        foreach ($arr as $num) {
            $digitVal = (int) (($num / (10 ** $digit)) % 10);
            $buckets[$digitVal][] = $num;
        }
        
        $arr = array_merge(...array_reverse($buckets));
    }
    
    return $arr;
}

$numbers = [170, 45, 75, 90, 802, 24, 2, 66];
$sorted = radixSortDesc($numbers);

print_r($sorted); // [802, 170, 90, 75, 66, 45, 24, 2]

与升序排序的唯一区别是在合并之前反转桶。 这给了我们降序的结果。

字符串基数排序(升序)

基数排序也可以通过处理字符按字母顺序对字符串进行排序。

string_radix_sort.php
<?php

function stringRadixSort(array $arr): array {
    $maxLength = max(array_map('strlen', $arr));
    
    for ($pos = $maxLength - 1; $pos >= 0; $pos--) {
        $buckets = array_fill(0, 256, []);
        
        foreach ($arr as $str) {
            $char = $pos < strlen($str) ? ord($str[$pos]) : 0;
            $buckets[$char][] = $str;
        }
        
        $arr = array_merge(...$buckets);
    }
    
    return $arr;
}

$words = ["apple", "banana", "kiwi", "orange", "pear"];
$sorted = stringRadixSort($words);

print_r($sorted); // ["apple", "banana", "kiwi", "orange", "pear"]

这从右到左处理字符串,使用 ASCII 值进行字符比较。 较短的字符串被视为具有空字符。

字符串基数排序(降序)

对于降序字母顺序,我们反转桶的合并顺序。

string_radix_sort_desc.php
<?php

function stringRadixSortDesc(array $arr): array {
    $maxLength = max(array_map('strlen', $arr));
    
    for ($pos = $maxLength - 1; $pos >= 0; $pos--) {
        $buckets = array_fill(0, 256, []);
        
        foreach ($arr as $str) {
            $char = $pos < strlen($str) ? ord($str[$pos]) : 0;
            $buckets[$char][] = $str;
        }
        
        $arr = array_merge(...array_reverse($buckets));
    }
    
    return $arr;
}

$words = ["apple", "banana", "kiwi", "orange", "pear"];
$sorted = stringRadixSortDesc($words);

print_r($sorted); // ["pear", "orange", "kiwi", "banana", "apple"]

降序版本在合并之前反转桶,类似于数值降序排序实现。

基数排序与快速排序基准测试

让我们比较一下基数排序与快速排序在大型数据集上的性能。

sort_benchmark.php
<?php

function generateRandomNumbers(int $count): array {
    $numbers = [];
    for ($i = 0; $i < $count; $i++) {
        $numbers[] = rand(1000, 999999);
    }
    return $numbers;
}

function benchmark(callable $sortFunc, array $data): float {
    $start = microtime(true);
    $sortFunc($data);
    return microtime(true) - $start;
}

$largeDataset = generateRandomNumbers(100000);

$radixTime = benchmark('radixSort', $largeDataset);
$quickTime = benchmark(function($arr) { sort($arr); }, $largeDataset);

echo "Radix sort time: " . number_format($radixTime, 4) . " seconds\n";
echo "Quick sort time: " . number_format($quickTime, 4) . " seconds\n";

在包含 100,000 个数字的典型测试中,基数排序通常在整数数据上优于快速排序,尤其是在数字具有有限位数长度时。

何时使用基数排序

基数排序的局限性

来源

维基百科上的基数排序

本教程介绍了 PHP 中的基数排序算法,并提供了数值和文本数据升序和降序排序的示例。

作者

我叫 Jan Bodnar,是一位热衷于编程并拥有丰富编程经验的程序员。 我从 2007 年开始撰写编程文章。 迄今为止,我撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出 所有 PHP 教程