我正在编写一个算法来对3D盒子的数组进行排序,以便按照从前到后的顺序进行绘制。有一种定义明确,稳定的方法可以决定两个方框中的哪一个位于另一个方框的前面,因此我编写了一个函数来执行该操作,然后将函数传递给Array.prototype.sort()
以获得正确的绘制顺序
但是可以设置框的周期,使A>B
,B>C
和C>A
都为真。这意味着整个列表没有明确定义的排序顺序,即使任何一对的顺序都是明确定义的。
在实践中,这种情况不大可能出现,如果确实如此,我可以忍受一两个盒子的顺序错误。但是,在这种情况下,是否存在可以对整个列表进行错误排序或崩溃的JS实现?
现在只需填写更多上下文,项目就完成了(事实上,如果你愿意,没有理由你不能look at it):
我问这个问题的原因是,虽然明显的答案是“你不能使用破坏的比较器排序”,但仍然......这是一个类似排序的任务,并试图进行排序 会给出一些有用的结果。
在我的具体应用中,上面显示的循环情况从未实际出现过(至少,你必须真正尝试)。我希望我可以对对象进行排序,这样,如果删除了属于循环的任何元素,剩下的元素将按严格的顺序排列。但我没有达到这一点,这就是原因:
我的第一个想法是,当我比较两个方框时,无论哪个方框位于X轴前面或 Y轴或,Z轴都在前面排序。但这意味着我不是比较框(A),而是真正比较无限的交叉形状(B):
- 这意味着它们像疯了一样重叠,而且循环情况并不罕见;事实上,如果有3个或更多个对象,我不妨使用随机顺序。
在某些时候我看到了this helpful reference,这表明我应该只测试在屏幕上实际重叠的成对方框。添加该测试(并且如果它们不重叠则排序框为“相等”)会产生更好的结果,框中的顺序通常不正确,但仍然存在大量错误。
问题是快速排序算法不会测试每一对可能的值(如果他们这样做,他们将是O(n 2 ))。将A和B排序为“相等”并不仅仅意味着它们的相对顺序并不重要;这意味着如果C在A之前排序,它也必须在B之前排序。无论浏览器使用什么类型的算法,它都会跳过基于此假设的比较,因此它不会测试我需要它来测试的每对盒子
最后,我编写了我自己的无用的,天真的排序代码(测试每个框,直到找到重叠)。我的屏幕上永远不会有超过40个对象,所以性能还可以,而且结果经常是正确的。一个更彻底的算法会涉及回溯,并会引发暂停问题,所以我就此止步了。
所以,这不是最令人满意的结论,但有时它会如何发展。无论如何,希望这会为其他人提供一些帮助(或残酷的娱乐)。
答案 0 :(得分:1)
如果排序不具有传递性 - 如您所说,类型允许循环关系<?xml version="1.0" encoding="UTF-8"?>
<map>
<entry>
<string>PNB_ALERTLOG_RECEIVER_CHANNEL</string>
<com.mirth.connect.util.ConfigurationProperty>
<value>PNB_ALERTLOG_RECEIVER</value>
<comment>Canal que...</comment>
</com.mirth.connect.util.ConfigurationProperty>
</entry>
<entry>
<string>PNB_CFG_FILE_ACCESS_CONTROL</string>
<com.mirth.connect.util.ConfigurationProperty>
<value>resources/configPnbDev/pnbAccessControl.json</value>
<comment>Este ficheiro...</comment>
</com.mirth.connect.util.ConfigurationProperty>
</entry>
</map>
- 那么我不知道这些项目的顺序是错误的:-)
ECMAScript标准(ECMA-262,5.1版)says of Array.prototype.sort
:
如果
A > B ; B > C ; C > A
未定义,并且不是此数组元素的一致比较函数(见下文),则comparefn
的行为是实现定义的。
并且“见下文”解释了,是的,比较的传递性需要 comparefn 才有资格作为“一致”。
如果满足以下所有要求,函数
sort
是一组值comparefn
的一致比较函数[...]
- 如果
S
和a =CF b
,则b =CF c
(a =CF c
的及物性传承- 如果
=CF
和a < CF b
,则b <\ CF c
(a <\ CF c
的及物性传承- 如果
<\ CF
和a >CF b
,则b >CF c
(a >CF c
的及物性传承
因此,正如您所描述的那样,您的非传递性比较函数会调用规范的“实现定义”子句。
我建议将“实现定义”读作“可以做任何事情或者什么也不做,不可预测,并且仍然符合此规范”。