Существует ли структура данных, которая не допускает дублирования, а также поддерживает порядок ввода? - PullRequest
5 голосов
/ 30 апреля 2009

Дубликат: Выбор контейнера STL с уникальностью и сохранением порядка вставки

Я ищу структуру данных, которая действует как набор, который не позволяет вставлять дубликаты, но также знает порядок, в котором элементы были вставлены. В основном это будет комбинация набора и списка / вектора.

Я бы просто использовал список / вектор и сам проверял бы наличие дубликатов, но нам нужна быстрая проверка дубликатов, так как размер структуры может стать довольно большим.

Ответы [ 8 ]

6 голосов
/ 30 апреля 2009

Взгляните на Boost.MultiIndex . Возможно, вам придется написать обертку над этим.

2 голосов
/ 30 апреля 2009

A Boost.Bimap с порядком вставки в качестве индекса должно работать (например, boost :: bimap ). Если вы удаляете объекты из структуры данных, вам нужно будет отдельно отслеживать значение следующего порядка вставки.

1 голос
/ 30 апреля 2009

Написание собственного класса, который обертывает вектор и набор, может показаться очевидным решением - не существует стандартного контейнера библиотеки C ++, который делает то, что вы хотите.

0 голосов
/ 30 апреля 2009

У Java это есть в виде упорядоченного набора. Я не думаю, что C ++ имеет это, но это не так сложно реализовать самостоятельно. Ребята из Sun сделали с классом Java расширение хеш-таблицы таким образом, чтобы каждый элемент одновременно вставлялся в хеш-таблицу и хранился в двойном связанном списке. В этом очень мало накладных расходов, особенно если вы предварительно выделяете элементы, которые используются для создания связанного списка из.

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

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

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

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

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

Возможно, вы захотите взглянуть на алгоритм танцующих ссылок.

0 голосов
/ 30 апреля 2009

Предполагая, что вы говорите здесь ANSI C ++, я бы либо написал свой собственный, либо использовал композицию и делегирование для переноса карты для хранения данных и вектора ключей для порядка вставки. В зависимости от характеристик данных вы можете использовать индекс вставки в качестве ключа карты и избегать использования вектора.

0 голосов
/ 30 апреля 2009

Быстрое повторное подтверждение, кажется, является критической частью здесь. Я мог бы использовать какой-то тип карты / словаря и, возможно, сам отслеживать порядок вставки в качестве фактических данных. Таким образом, ключ - это «данные», в которые вы добавляете данные (которые затем хэшируются, и вы не разрешаете дублирование ключей), и в качестве «данных» укажите текущий размер карты. Конечно, это работает, только если у вас нет удалений. Если вам это нужно, просто используйте внешнюю переменную, которую вы увеличиваете при каждой вставке, и относительный порядок сообщит вам, когда что-то было вставлено.

Не обязательно красиво, но не так сложно реализовать.

0 голосов
/ 30 апреля 2009

Звучит как работа для OrderedDictionary .

0 голосов
/ 30 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...