在PHP项目中,我有一些数据,我想使用线性时间排序,简单的计数排序:
$ar = array(7, 2, 0, 3, 8, 0, 12, 7, 6, 7);
$count = array();
foreach ($ar as $v)
$count[$v]++;
$sorted = array();
foreach ($count as $v => $c)
for ($i = 0; $i < $c; $i++)
$sorted[] = $v;
问题是以上显然不起作用。 php数组的工作方式更像是散列映射而不是数组。可以通过在最终循环之前插入ksort($count)
来使代码工作,但ksort
在O(nlogn)
中运行会破坏整个点。
有没有办法在PHP中进行线性时间排序?也许使用一些参数array()
,或者一些完全不同的结构?
答案 0 :(得分:3)
您没有正确关注algorithm。这是O(n)。
$ar = array(7, 2, 0, 3, 8, 0, 12, 7, 6, 7);
$count = array();
foreach ($ar as $v) {
$count[$v] = isset($count[$v]) ? $count[$v] + 1 : 1;
}
$sorted = array();
$min = min($ar);
$max = max($ar);
for ($i=$min; $i<=$max; $i++) {
if (isset($count[$i])) {
for ($j=0; $j<$count[$i]; $j++) {
$sorted[] = $i;
}
}
}
另外,请参阅array_count_values(),或者计算计数循环内的最小值和最大值。
答案 1 :(得分:0)
如果我理解你的问题并正确评论,那么只使用sort($ count)就可以了吗?
$ar = array(7, 2, 0, 3, 8, 0, 12, 7, 6, 7);
$sorted = $ar;
sort($sorted);
var_dump($ar);
var_dump($sorted);
结果:
array(7,2,0,3,8,0,12,7,6,7);
array(0,0,2,3,6,7,7,7,8,12);
但我想知道foreach($ ar as $ v)$ count [$ v] ++; ......真的没有意义......
答案 2 :(得分:0)
要在自己的变量($ar
)中获取已排序的$sorted
,这非常简单:
$sorted = $ar;
sort($sorted);
这让我觉得你的问题和评论没有全面展现。
编辑现在,在你澄清了你想要实现一个特定的算法之后(你实际上已经得到了一个答案,显示了一些错误的实现它的错误点),我认为这是值得的关注你问题的另一个方面:
您正在比较两种(理论)算法的复杂性,但您不考虑算法的实现方式。
PHP sort()
- 即使基于“坏”快速排序,也会超过您自己的PHP用户代码实现其他算法的数字。
您刚刚在这里比较了错误的参数。当您将内置PHP函数与用户代码中的某些函数进行比较时,函数的复杂性并不多。
答案 3 :(得分:0)
在代码中添加一些注释,向您展示为什么这样做不符合您认为应该做的事情。
$ar = array(7, 2, 0, 3, 8, 0, 12, 7, 6, 7);
$count = array();
foreach ($ar as $v) {
// add each number in $ar to $count.
// the first number in $ar is 7, so 7 will be the first number in $count.
// because 7 is in $ar 3 times, $count[7] == 3.
$count[$v]++;
}
// the output of print_r will be very revealing:
print_r($count);
/*Array
(
[7] => 3
[2] => 1
[0] => 2
[3] => 1
[8] => 1
[12] => 1
[6] => 1
)*/
$sorted = array();
foreach ($count as $v => $c) {
// the first entry: $count[7] == 3
// so add 7 to $sorted 3 times.
// the second entry: $count[2] == 1
// so add 2 to $sorted 1 time.
// etc.
for ($i = 0; $i < $c; $i++) {
$sorted[] = $v;
}
}
这只是根据数字在第一个数组中的位置将数字组合在一起。
答案 4 :(得分:0)
批准的答案是错误的。正确的:
$ar = array(7, 2, 0, 3, 8, 0, 12, 7, 6, 7);
$count = array();
foreach ($ar as $v) {
$count[$v] = isset($count[$v]) ? $count[$v] + 1 : 1;
}
$sorted = array();
$min = min($ar);
$max = max($ar);
for ($i=$min; $i <= $max; $i++) {
if (isset($count[$i])) {
for ($j=0; $j<$count[$i]; $j++) {
$sorted[] = $i;
}
}
}