2015-07-01 2 views
4

У меня есть программа, которая использует ArrayList<T>, и этот тип T также реализует Comparable<T>. Мне нужно сохранить этот список отсортированным.структура данных коллекции java для хранения отсортированных предметов

На данный момент, когда я вставляю новый элемент, я добавляю его в ArrayList, а затем вызываю Collections.sort(myArrayList).

Является ли сортировка с Collections.sort каждый раз, когда я вставляю новый элемент, серьезно повреждающий сложность времени выполнения?

Есть ли более подходящая структура данных, которую я могу использовать, чтобы всегда сортировать список? Я знаю структуру, называемую PriorityQueue, но мне также нужно иметь возможность получать элементы списка по индексу.

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

+4

'TreeSet' - ваш друг. –

+0

Любые конкретные причины, по которым вы не можете/не можете вставить какой-либо новый элемент в его отсортированное местоположение? –

+0

@kocko 'TreeSet' также не предоставляет произвольный доступ. –

ответ

2

Кажется, что Collection.Sort - это на самом деле путь сюда, поскольку коллекция уже почти отсортирована, сортировка займет не более O (n) в худшем случае.

0

Вместо того, чтобы использовать Collections.sort(myArrayList) после каждой вставки, вы можете сделать что-то более умное, как вы знаете, каждый раз, когда вы вставляете элемент, ваша коллекция уже заказана.

Collections.sort(myArrayList) принимает 0 (nlogn) раз, вы можете сделать упорядоченную вставку в упорядоченной коллекции в O (n) раз, используя Collections.binarySearch. Если коллекция упорядочена в порядке возрастания Collections.binarySearch возвращает индекс элемента, который вы ищете, если он существует, или (-(insertion point) - 1). Перед вставкой элемента вы можете искать его с Collections.binarySearch (время O (logn)). Сделано, что вы можете получить индекс, в который вставляется новый элемент. Затем вы можете добавить элемент с addAt в O (n). Вся сложность вставки ограничена addAt, поэтому вы можете сделать упорядоченную вставку в ArrayList в O (n) времени.

+0

Из документации 'Collections.sort (Список )' : * «Эта реализация является стабильной, адаптивной итеративной слиянием, которая требует гораздо меньше, чем n lg (n) сравнений, когда входной массив частично сортируется». * –

+0

_ «намного меньше, чем n lg (n)» _ не обязательно среднее значение O (n) в худшем случае. Более того, насколько мне известно, сортировка слияния также требует временную копию коллекции, которая вам не нужна с бинарным поиском (может быть, я ошибаюсь). – mziccard

+0

Как вы отметили сами, список уже отсортирован, но для одного элемента. Наихудшее поведение 'Collections.sort()' не применяется. * «Если входной массив почти отсортирован, для реализации требуется приблизительно n сравнений. Требования к временному хранению варьируются от небольшой константы для почти отсортированных входных массивов ...» * –

3

Список - это упорядоченная коллекция, что означает, что вам нужно иметь доступ с помощью индекса. Если коллекция внутренне перемещает или сортирует элементы, порядок вставки не будет таким же, как порядок элементов во внутренней структуре данных. Таким образом, вы больше не можете зависеть от доступа на основе индексов. Следовательно, Sun не предоставил класс SortedList или TreeList. Вот почему вы используете Collections.sort (..)

Коллекции коллекций Apache предоставляют класс TreeList, но он не является отсортированным списком и называется так, потому что он использует структуру данных дерева для внутреннего хранения элементов. Проверьте его документацию здесь - http://commons.apache.org/proper/commons-collections/javadocs/api-3.2.1/org/apache/commons/collections/list/TreeList.html

-1

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

Например, ArrayList для поиска по индексу и TreeMap (или очередь приоритетов) для сортировки.

+1

-1 простое двоичное дерево может легко поддерживать поиск по индексам O (log n), отслеживая количество детей в каждом поддереве. Или отсортированный массив-список с O (1) извлечением, но O (n) вставляет. –

+0

@ BlueRaja-DannyPflughoeft Пожалуйста, уточните поиск по индексу в дереве. –

+1

В левом поддереве есть 20 элементов и 30 элементов в правом поддереве, и пользователю нужен индекс 25. Поскольку дерево упорядочено, элементы 1-20 находятся в левом поддереве, а 21-50 - справа. Поэтому перейдите в правильное поддерево, ища индекс 5. Я использую именно этот метод для своего [рандомизатора взвешенных позиций] (https://github.com/BlueRaja/Weighted-Item-Randomizer-for-C-Sharp) (в частности [ здесь] (https://github.com/BlueRaja/Weighted-Item-Randomizer-for-C-Sharp/blob/master/Weighted%20Randomizer/DynamicWeightedRandomizer.cs#L415-L433)) –

Смежные вопросы