有没有办法知道natsort()php中发生的步骤数?

时间:2016-10-31 08:45:37

标签: php arrays sorting

我的任务是找到将字符串数组排列成字典顺序所需的步骤。

经过一番研究,我发现natsort()做了同样的事情。但是我无法找到它的定义,也无法找到任何可以给我natsort()所需步骤数的函数。

例如, 我有一个包含以下值的数组

  • Oksana Baiul
  • Michelle Kwan

以字典方式对此数组进行排序所需的步骤数为1

所以我有兴趣直接获取步骤数而不是实现任何排序算法。

感谢任何帮助。!

1 个答案:

答案 0 :(得分:3)

用于计算比较步骤:

natsort在排序过程中使用特定的比较函数,也可以单独调用:strnatcmp

这意味着:

natsort($data);

...将产生与以下相同的结果:

usort($data, 'strnatcmp');

或者,更详细:

usort($data, function ($a, $b) {
    return strnatcmp($a, $b);
});

这打开了计算此比较函数被调用次数的大门:

$count = 0;
usort($data, function ($a, $b) use (&$count) {
    $count++;
    return strnatcmp($a, $b);
});

例如:

$data = ['test', 'abc10', 'abc2', 'OK', 9, 13];

$count = 0;
usort($data, function ($a, $b) use (&$count){
    $count++;
    return strnatcmp($a, $b);
});

echo "$count comparisons: " . implode(", ", $data);

输出:

  

8次比较:9,13,OK,abc2,abc10,test

请注意,此排序算法区分大小写:" OK"在" abc"。

之前排序

对于不区分大小写的自然排序,您可以使用natcasesortstrnatcasecmp

用于计算交换

无法使用上述方法知道在排序过程中有多少交换。 PHP在内部使用version of QuickSort,因此您可以模仿相同类型的算法并自行计算交换。由于以下原因,这显然是一种估计:

  • 根据他们在每个递归步骤中选择枢轴的方式,快速排序有不同的风格,因此这会影响他们为特定输入执行的互换次数;
  • 有些风格根本不交换,但是一起创建一个新数组,然后最后用它覆盖原始数组 - 例如参见this algorithm in PHP;
  • 还有其他口味的确执行交换,但是随机选择枢轴(在算法中),因此相同输入的交换次数会有所不同;
  • 当数组只有少数元素时,许多实现将切换到another sorting algorithm,这又会影响交换次数。

我将在这里提供我认为最标准算法的代码:它在给定分区的中间选择一个数据透视索引:

class QuickSort {
    private static $swaps = 0;
    private static $cmp = 'test';

    private static function swap(&$array, $i, $j) {
        if ($i == $j) return;
        self::$swaps++;
        list($array[$i], $array[$j]) = [$array[$j], $array[$i]];
    }

    private static function partition(&$array, $begin, $end) {
        $cmp = self::$cmp;
        $index = floor(($begin + $end) / 2);
        $pivot = $array[$index];
        self::swap($array, $index, $end); 
        for ($i = $index = $begin; $i < $end; $i++) {
            if ($cmp($array[$i], $pivot) >= 0) continue;
            self::swap($array, $index++, $i);
        }
        self::swap($array, $index, $end); 
        return $index;
    }

    private static function qsort(&$array, $begin, $end) {
        if ($end <= $begin) return;
        $index = self::partition($array, $begin, $end);
        self::qsort($array, $begin, $index - 1);
        self::qsort($array, $index + 1,  $end);
    }

    public static function sort(&$array, $cmp = 'strcmp') {
        self::$swaps = 0;
        self::$cmp = $cmp;
        self::qsort($array, 0, count($array) - 1);
        return self::$swaps;
    }
}

// Sample input
$data = [1,3,2,8,2,5,4,6];
// Call it: this sort function returns the number of swaps made
$swaps = QuickSort::sort($data, 'strnatcmp');
// Display the result:
echo "$swaps swaps: " . implode(", ", $data);

输出:

9 swaps: 1, 2, 2, 3, 4, 5, 6, 8

同样,在某些情况下,互换的数量可能比您预期的要多,因为快速排序并非专门设计用于最小化掉期数量。