У меня есть разреженный матричный класс, чьи не нули и соответствующие им индексы столбцов хранятся в порядке строк, в основном контейнерах, подобных STL-вектору. Они могут иметь неиспользуемую емкость, например векторы; и для вставки/удаления элементов необходимо перемещать существующие элементы.
Скажем, что у меня есть операция, insert_erase_replace
или ier
для краткости. ier
может делать следующее, учитывая позицию p
, индекс столбца j
и значение v
:
- if
v==0
,ier
удаляет запись вp
и сдвигает все последующие записи влево. - Если
v!=0
иj
уже присутствует вp
,ier
заменяет содержимое ячейки наp
наv
. - если
v!=0
иj
нет вp
,ier
вставляет записьv
и индекс столбцаj
вp
после правого смещения всех последующих записей.
Итак, все это тривиально.
Теперь скажем, что у меня есть ier2
, что делает то же самое, за исключением того, что он принимает список, содержащий несколько индексов столбца j
и соответствующие значения v
. Он также имеет размер n
, который указывает, сколько пар index/value присутствует в списке. Но поскольку вектор сохраняет только нули, иногда фактический размер вставки меньше n
.
Еще тривиально.
Но теперь скажем, что у меня есть ier3
, который берет не только один список, например ier2
, но и несколько списков. Это означает редактирование среза разреженной матрицы.
В какой-то момент становится более эффективным выполнять итерацию через векторы, копируя их по частям и вставляя/заменяя/стираем индексы/значения list ier2
-style, когда мы приходим к каждой точке вставки. И если общий размер вставки приведет к тому, что мой вектор будет нуждаться в изменении размера, тогда мы это сделаем.
Учитывая, что мой вектор намного, намного больше, чем общая длина списков, есть алгоритм для эффективного объединения списков в вектор?
До сих пор вот что у меня:
-
Каждый список, переданный в
ier3
, представляет собой чистое удаление записей (сдвиг влево), замену сети (без движения, следовательно, дешевую) или чистую вставку записей (правая смена). Там также может быть некоторое перераспределение элементов, но дорогими частями являются чистые удаления и сетевые вставки. -
Не сложно найти алгоритм для эффективного выполнения ТОЛЬКО чистых вставок или сетевых удалений.
-
Это сложнее, если любой из двух может произойти.
Единственное, что я могу сделать, это обработать его двумя проходами:
- Erase/заменить
- Вставить/заменить
Мы сначала стираем, потому что это делает более вероятным, что для любых вставок потребуется меньше копий.
Это правильный подход? Кто-нибудь знает о лучшем?