起始点是一个类似于列表或数组的东西,如下所示:
1 {A, 4, 9}
2 {B, 6, 1}
3 {C, 1, 3}
4 {D, 3,10}
5 {E, 7, 2}
6 {F, 4, 2}
7 {G, 9, 8}
8 {H,10, 5}
9 {I, 7, 5}
10 {J, 6, 8}
如果我们可以将它改成像这样的列表或数组:
1 {C, 1, 3}
2 {F, 2, 4} (nodes swapped)
3 {D, 3,10}
4 {A, 4, 9}
5 {I, 5, 7} (nodes swapped)
6 {B, 6, 1}
7 {E, 7, 2}
8 {J, 8, 6} (nodes swapped)
9 {G, 9, 8}
10 {H,10, 5}
如果按照节点1的顺序排序,那么我们可以将这个列表或数组读作链表:
start with item 1: {C, 1, 3}
read node2: 3
skip to item 3: {D, 3,10}
read node2: 10
skip to item 10: {H,10, 5}
...
skip to item 6: {B, 6, 1}
read node2: 1
end of list
result: C D H I E F A G J B
创建这个列表的第二个版本可以在原地完成,通过交换列表中的项目或将项目复制到新列表中(如果您有足够的空间)。唯一需要注意的是,有时您可能需要交换两个节点。在原地重新排序时,可能会像这样进行:
look at item 1: {A, 4, 9}
if item 4 has a node1 different from 4, swap item 1 and 4
else, change item 1 to {A, 9, 4} and swap item 1 and 9
(-> item 1 and 4 swapped)
while current item is already in-place, skip to next
(-> stay at item 1)
look at new item 1: {D, 3,10}
if item 3 has a node1 different from 3, swap item 1 and 3
else, change item 1 to {D,10, 3} and swap item 1 and 10
(-> item 1 and 3 swapped)
while current item is already in-place, skip to next
(-> item 1 is now {C, 1, 3}, so skip to item 2)
...
创建新的列表或数组时,这应该更加简单:
look at item 1: {A, 4, 9}
if new list has no item 4, copy item 1 as item 4 to the new list
else, change item 1 to {A, 9, 4} and copy as item 9 to the new list
move to next item
正如您所看到的,无需多次迭代列表;每个项目只交换或复制一次,并且其目的地由其node1或node2确定。
更新
我刚意识到,订购物品的步骤可能会比上述描述的(大大)增加。例如,如果您首先将 {A,4,8} 移动到位置 4,将 {B,5,9} 移动到位置 5,然后遇到 {C,4,5},您就会卡住。然后,您必须将 {C,4,5} 与其他两个项目之一交换,交换另一个项目中的节点,并将其移动到位。该新位置本身可能已被占用,等等,因此无法知道两个选项中哪个更小。在最坏的情况下,交换次数接近 N2。
更新2
当然,可以通过将项目存储为双向链表来解决上述问题。例如,遇到{A,4,8}时,将{A,8}存储为项目4,将{A,4}存储为项目8,然后对于{B,5,9},将{B,9}存储为项目5,将{B,5}存储为项目9,然后对于{C,4,5},将其添加到已存储的项目中,使项目4变为{A,8,C,5},项目5变为{B,9,C,4}。然后可以在两个方向上遍历双向链表。这将增加需要完成的工作和使用的空间,但仍然与列表中的项目数量成线性关系。