Отправной точкой является список или массив, как:
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}
, который заказывается в соответствии с node1 , то мы можем прочитать этот список или массив как связанный список:
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
Как вы можете видеть, нет необходимо многократно перебирать список; каждый элемент заменяется или копируется один раз, а его назначение определяется его узлом1 или узлом2.
ОБНОВЛЕНИЕ
Я просто понял, что количество шагов, чтобы заказать товар может быть (много) больше, чем описано выше. Если, например, вы начинаете с перемещения {A, 4,8} до местоположения 4 и {B, 5,9} до местоположения 5, а затем вы сталкиваетесь с {C, 4,5}, вы застреваете. Затем вам придется поменять {C, 4,5} одним из двух других элементов, поменять местами в другом элементе и переместить их на место. Это новое место уже может быть принято и так далее, поэтому не было бы способа узнать, какой из двух вариантов - меньшее зло. В худшем случае количество свопов будет близко к N .
ОБНОВЛЕНИЕ 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}. Затем вы можете пересечь двусвязный список в обоих направлениях. Это увеличит работу, которую необходимо выполнить, и используемое пространство, но оно по-прежнему является линейным по количеству элементов в списке.
Является ли структура списка уже определена как массив (id, node1, node2) ИЛИ является структурой списка, которая должна быть определена для получения наилучшего решения? – lemon
Вы ищете нечто похожее на [это решение] (http://stackoverflow.com/a/42072136/767890). Я не думаю, что вы можете получить более эффективный алгоритм. – InBetween
@lemon: он в настоящее время находится в базе данных, поэтому я могу прочитать его во все, что хочу – frankhommers