Рассмотрим следующий пример:
MultiSet s1({7, 7});
MultiSet s2({5});
Если вы теперь перебираете s1:
1st iteration: 7 7
^
aux1
2nd iteration: 7 7
^
aux1
Если у вас есть несколько равных элементов в s1
, вы обнаружите их более одного раза, что в итоге приведет к добавлению квадрата кратности (или произведения обеих кратностей, если один из s2 больше).
С другой стороны, так как 5 не содержится в s1
, вы также не будете пытаться найти его в s2
- тем не менее, оно есть ...
Чтобы решить первую проблему, вам нужно проверить, содержится ли текущий элемент в s3
, и если это так, просто пропустите его.
Чтобы исправить вторую проблему, вам нужно выполнить итерации по s2
, добавив все элементы, которые еще не содержатся в s3
.
Тем не менее, конечный результат будет иметь довольно низкую производительность (должно быть где-то между O(n²)
и O(n³)
, а не последним). К сожалению, вы выбрали структуру данных (простой односвязный список - очевидно, не отсортированный!), Который предлагает плохую поддержку для операций, которые вы намереваетесь - и особенно для выбранного вами алгоритма.
Если вы сохраняете два списка отсортированными, вы можете создать алгоритм с линейным временем выполнения. Это будет работать так же, как шаг слияния в сортировке слиянием:
while(elements available in both lists):
if(left element < right element):
append left element to s3
advance left
else
append right element to s3
if(left element == right element):
advance left // (too! -> avoid inserting sum of multiplicities)
advance right
append all elements remaining in left
append all elements remaining in right
// actually, only in one of left and right, there can be elements left
// but you don't know in which one...
Сохранение списка во время вставки довольно просто:
while(current element < new element):
advance
insert before current element // (or at end, if no current left any more)
Однако, когда вы выставляете узлы списка напрямую, вы всегда находитесь в опасности, что вставка не начнется с элемента head - и ваш порядок сортировки может быть нарушен.
Вы должны соответствующим образом заключить в капсулу:
- Переименуйте ваш текущий MultiSet в e. г. «Узел» и создайте новый класс
MultiSet
.
- Сделать класс узла вложенным классом нового набора классов.
- Все модификаторы списка должны быть только членами заданного класса.
- Вы можете предоставить класс узла, но пользователь не должен иметь возможность его изменять. Тогда это будет просто своего рода итератор.