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

有没有办法知道natsort()php中发生的步骤数?,php,arrays,sorting,Php,Arrays,Sorting,我的任务是找到将字符串数组按字典顺序排列所需的步骤 经过一些研究,我发现natsort()也做同样的事情。但是我找不到它的定义,也找不到任何函数可以为我提供natsort()中所需的步骤数 例如, 我有一个具有以下值的数组 奥克萨纳拜尔 关颖珊 按字典顺序排列此数组所需的步骤数为1 因此,我感兴趣的是直接获得步骤数,而不是实现任何排序算法 谢谢你的帮助 对于计算比较步骤: 在排序期间使用特定的比较函数,该函数也可以单独调用: 这意味着: natsort($data); 。。。将产生与以下相

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

经过一些研究,我发现
natsort()
也做同样的事情。但是我找不到它的定义,也找不到任何函数可以为我提供
natsort()
中所需的步骤数

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

  • 奥克萨纳拜尔
  • 关颖珊
按字典顺序排列此数组所需的步骤数为
1

因此,我感兴趣的是直接获得步骤数,而不是实现任何排序算法

谢谢你的帮助

对于计算比较步骤: 在排序期间使用特定的比较函数,该函数也可以单独调用:

这意味着:

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);
产出:

9 swaps: 1, 2, 2, 3, 4, 5, 6, 8
8比较:9、13、正常、abc2、abc10、测试

请注意,此排序算法区分大小写:“OK”排序在“abc”之前

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

用于计算掉期 无法使用上述方法来了解排序期间进行了多少次交换。PHP在内部使用了一个函数,因此您可以模拟相同的算法,自己计算交换。这显然是一个估计,原因如下:

  • 快速排序有不同的风格,根据他们在每个递归步骤中如何选择枢轴,因此这会影响他们对特定输入所做的交换的数量
  • 有些风格根本不交换,而是一起创建一个新数组,然后在最后用它覆盖原始数组——例如,请参见
  • 还有一些风格确实执行交换,但随机选择枢轴(在算法中),因此在相同的输入上交换的数量将不同
  • 许多实现将切换到阵列只有几个元素时,这同样会影响交换的数量
我将在这里提供我认为是最标准算法的代码:它选择一个轴索引,就在给定分区的中间:

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);
同样,在某些情况下,互换数量可能比您预期的要多,因为快速排序并不是专门为最小化互换数量而设计的。

对于计算比较步骤: 在排序期间使用特定的比较函数,该函数也可以单独调用:

这意味着:

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);
产出:

9 swaps: 1, 2, 2, 3, 4, 5, 6, 8
8比较:9、13、正常、abc2、abc10、测试

请注意,此排序算法区分大小写:“OK”排序在“abc”之前

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

用于计算掉期 无法使用上述方法来了解排序期间进行了多少次交换。PHP在内部使用了一个函数,因此您可以模拟相同的算法,自己计算交换。这显然是一个估计,原因如下:

  • 快速排序有不同的风格,根据他们在每个递归步骤中如何选择枢轴,因此这会影响他们对特定输入所做的交换的数量
  • 有些风格根本不交换,而是一起创建一个新数组,然后在最后用它覆盖原始数组——例如,请参见
  • 还有一些风格确实执行交换,但随机选择枢轴(在算法中),因此在相同的输入上交换的数量将不同
  • 许多实现将切换到阵列只有几个元素时,这同样会影响交换的数量
我将在这里提供我认为是最标准算法的代码:它选择一个轴索引,就在给定分区的中间:

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

同样,在某些情况下,互换的数量可能比您预期的要多,因为快速排序并不是专门为减少互换数量而设计的。

谢谢。。但似乎有些不对劲。如果我尝试排序-Elvis Stojko-Evgeni Plushenko-Kristi Yamaguchi,那么它应该返回0,而不是返回2。有两件事可以计算:比较的数量,或者互换的数量。这计算比较的数量,这实际上决定了算法的时间复杂度。你想数一数掉期的数量吗?是的。。。我尝试了这个usort($data,function($a,$b)use(&$count){$x=strnatcmp($a,$b);if($x==1)$count++;return$x;});我认为您不能这样推导,因为我们不知道调用时部分排序数组中
$a
$b
的顺序。True。。那我怎么知道掉期的数量呢?谢谢。。但似乎有些不对劲。如果我尝试排序-Elvis Stojko-Evgeni Plushenko-Kristi Yamaguchi,那么它应该返回0,而不是返回2。有两件事可以计算:比较的数量,或者互换的数量。这计算比较的数量,这实际上决定了算法的时间复杂度。你想数一数掉期的数量吗?是的。。。我尝试了这个usort($data,function($a,$b)use(&$count){$x=strnatcmp($a,$b);if($x==1)$count++;return$x;});我认为您不能这样推导,因为我们不知道调用时部分排序数组中
$a
$b
的顺序。True。。那我怎么才能得到互换的数量呢?