Мне нужен очень быстрый алгоритм для следующей задачи. Я уже реализовал несколько алгоритмов, которые дополняют его, но они слишком медленные для нужной мне производительности. Он должен быть достаточно быстрым, чтобы алгоритм мог запускаться не менее 100 000 раз в секунду на современном процессоре. Это будет реализовано в C ++.
Я работаю с интервалами / диапазонами, структурой с начальной и конечной координатами на линии.
У меня есть два вектора (динамических массива) диапазонов, и мне нужно объединить их. Один вектор src, а другой dst. Векторы сортируются по начальным координатам пролета, и пролеты не перекрываются в пределах одного вектора.
Пролеты в векторе src должны быть объединены с пролетами в векторе dst, чтобы результирующий вектор все еще сортировался и не перекрывался. То есть. если во время объединения обнаружены перекрытия, два участка объединяются в один. (Объединение двух пролетов - это просто вопрос изменения координат в структуре.)
Теперь есть еще один улов: во время слияния интервалы в векторе src должны быть "расширены". Это означает, что константа будет добавлена в начало, а другая (большая) константа в конечную координату каждого диапазона в src. Это означает, что после расширения диапазона src они могут перекрываться.
Я пришел к тому, что до сих пор это невозможно сделать полностью на месте, требуется какое-то временное хранилище. Я думаю, что это должно быть выполнимо за линейное время по числу элементов src и dst, суммированных.
Любое временное хранилище может быть совместно использовано несколькими прогонами алгоритма.
Два основных подхода, которые я пробовал, которые слишком медленны:
Добавьте все элементы src к dst, расширяя каждый элемент перед добавлением его. Затем выполните сортировку на месте. Наконец, выполните итерацию по результирующему вектору, используя указатели «чтение» и «запись», с указателем чтения, опережающим указатель записи, объединяя интервалы по мере их прохождения. Когда все элементы объединены (указатель чтения достигает конца) dst усекается.
Создать временный рабочий вектор. Выполните наивное объединение, как описано выше, многократно выбирая следующий элемент из src или dst и сливаясь с рабочим вектором. Когда закончите, скопируйте рабочий вектор в dst, заменив его.
Первый метод имеет проблему с сортировкой O ((m + n) * log (m + n)) вместо O (m + n) и имеет некоторые накладные расходы. Это также означает, что вектор dst должен вырасти намного больше, чем нужно.
У второй есть основная проблема - много копировать и снова выделять / освобождать память.
Структуры данных, используемые для хранения / управления диапазонами / векторами, могут быть изменены, если вы считаете, что это необходимо.
Обновление: забыл сказать, насколько велики наборы данных. Наиболее распространенные случаи - от 4 до 30 элементов в любом векторе, либо либо dst пусто, либо существует большое перекрытие между диапазонами в src и dst.