Добавление элементов в отсортированный массив

31

Каков был бы самый быстрый способ сделать это (с алгоритмической точки зрения, а также с практической точки зрения)?

Я думал что-то вроде следующего.

Я мог бы добавить в конец массива и затем использовать пузырьковую сортировку, так как она имеет наилучший случай (полностью отсортированный массив в начале), который близок к этому, и имеет линейное время выполнения (в лучшем случае).

С другой стороны, если я знаю, что я начинаю с отсортированного массива, я могу использовать двоичный поиск, чтобы найти точку вставки для данного элемента.

Я догадываюсь, что второй путь почти оптимален, но любопытно посмотреть, что там.

Как это лучше всего сделать?

soandos
источник
1
Самый быстрый способ, если вам приходится делать это часто, - это не использовать массив в первую очередь.
reinierpost
Вы имеете в виду самобалансировку бинарного дерева?
Soandos
Да, возможно; увидеть ответы ...
reinierpost

Ответы:

25

Мы подсчитываем количество чтений и записей элемента массива. Чтобы выполнить пузырьковую сортировку, вам нужно обращений (начальная запись до конца, затем, в худшем случае, два чтения и две записи для выполнения перестановок). Чтобы выполнить бинарный поиск, нам нужно ( для бинарного поиска, затем, в худшем случае, чтобы сместить элементы массива вправо, затем 1, чтобы записать элемент массива в его правильное положение).n 2 log n + 2 n + 1 2 log n 2 n1+4nn2logn+2n+12logn2n

Таким образом, оба метода имеют одинаковую сложность для реализаций массива, но метод двоичного поиска требует меньше обращений к массиву в долгосрочной перспективе ... асимптотически, вдвое меньше. Естественно, есть и другие факторы.

На самом деле, вы могли бы использовать более совершенные реализации и считать только фактические обращения к массиву (не доступы к элементу, который нужно вставить). Вы можете сделать для пузырьковой сортировки и для бинарного поиска ... так что если доступ к регистру / кешу дешев, а доступ к массиву дорог, поиск с конца и смещение по пути (умный пузырь сортировка для вставки) может быть лучше, но не асимптотически.log n + 2 n + 12n+1logn+2n+1

Лучшее решение может включать использование другой структуры данных. Массивы дают вам O (1) доступ (произвольный доступ), но вставки и удаления могут стоить. Хэш-таблица может иметь O (1) вставок и удалений, доступ будет стоить. Другие варианты включают в себя BST и кучи и т. Д. Возможно, стоит рассмотреть потребности вашего приложения в вставке, удалении и доступе, а также выбрать более специализированную структуру.

Также обратите внимание, что если вы хотите добавить элементов в отсортированный массив из n элементов, хорошей идеей может быть эффективная сортировка m элементов, а затем объединение двух массивов; Кроме того, отсортированные массивы могут быть эффективно построены с использованием, например, куч (сортировка кучи).mnm

Patrick87
источник
1
«Хэш-таблица может иметь O (1) вставок и удалений», - обычно амортизируется.
Рафаэль
8
Амортизация ожидается .
Джефф
O(log n)O(2 log n)
8

Если у вас есть причины не использовать кучу, рассмотрите возможность использования сортировки вставками вместо сортировки по пузырькам. Лучше, когда у вас есть несколько несортированных элементов.

увлекаются
источник
8

O(n)

O(lgn)O(n+lgn)O(n)

O(1)

Во всяком случае, я не вижу причин, чтобы разбираться с этой проблемой.

Kirby
источник
2
O
+1 за то, что я неряшливый .. :-)
Кашьяп
4

Patrick87 все это очень хорошо объяснил. Но одной дополнительной оптимизацией, которую вы могли бы сделать, было бы использование чего-то вроде кольцевого буфера: вы можете перемещать элементы справа от позиции вставленного элемента вправо, как обычно. Но вы также можете перемещать предметы слева от правильной позиции влево. Чтобы сделать это, вы должны рассматривать массив как циклический, то есть последний элемент находится прямо перед первым, и он также требует, чтобы вы сохранили индекс, с которого в данный момент начинаются элементы.

Если вы сделаете это, это может означать, что вы делаете примерно вдвое меньше обращений к массиву (при условии равномерного распределения индексов, которые вы вставляете). В случае выполнения бинарного поиска, чтобы найти позицию, тривиально выбрать, сдвинуться влево или вправо. В случае с пузырьковой сортировкой, вам нужно правильно «угадать» перед началом. Но сделать это просто: просто сравните вставленный элемент с медианой массива, что можно сделать при доступе к одному массиву.

svick
источник
4

Я эффективно использовал алгоритм сортировки вставок для этой проблемы. Однажды у нас возникла проблема с производительностью объекта хэш-таблицы, я написал новый объект, который использовал бинарный поиск, который значительно повысил производительность. Чтобы сохранить список отсортированным, он будет отслеживать количество элементов, добавленных с момента последней сортировки (т. Е. Количество несортированных элементов), когда список должен быть отсортирован по запросу поиска, он выполнял сортировку вставкой или быструю сортировку в зависимости от на процент предметов не отсортированных. Использование сортировки вставки было ключевым в улучшении производительности.

Майкл Эриксон
источник
У вас есть формальный результат в отношении амортизированных операционных расходов? И: добро пожаловать!
Рафаэль