Если порядок не имеет значения, я бы просто использовал хеш-таблицу для отображения целых чисел на указатели.std::tr1::unordered_map<int, T *>
(или std::unordered_map<int, unique_ptr<T>>
, если C ++ 0x в порядке).
Элементы хеш-таблицы могут перемещаться, поэтому вам нужно использовать указатель, но он будет поддерживать очень быструю вставку / поиск /удаление.Итерация тоже быстрая, но элементы будут появляться в неопределенном порядке.
В качестве альтернативы, я думаю, вы можете реализовать свою собственную идею в виде очень простой комбинации std::vector
и std::list
.Просто поддерживайте как list<T> my_list
, так и vector<list<T>::iterator> my_vector
.Чтобы добавить объект, поместите его в конец my_list
, а затем вставьте его итератор в my_vector
.(Установите итератор на my_list.end()
и уменьшите его, чтобы получить итератор для последнего элемента.) Для поиска посмотрите в векторе и просто разыщите итератор.Чтобы удалить, удалите из списка (что вы можете сделать с помощью итератора) и установите местоположение в векторе на my_list.end()
.
std::list
гарантирует, что элементы внутри не будут перемещаться при их удалении.
[обновление]
Я чувствую себя мотивированным.Первый проход при реализации:
#include <vector>
#include <list>
template <typename T>
class NairouList {
public:
typedef std::list<T> list_t;
typedef typename list_t::iterator iterator;
typedef std::vector<iterator> vector_t;
NairouList() : my_size(0)
{ }
void push_back(const T &elt) {
my_list.push_back(elt);
iterator i = my_list.end();
--i;
my_vector.push_back(i);
++my_size;
}
T &operator[](typename vector_t::size_type n) {
if (my_vector[n] == my_list.end())
throw "Dave's not here, man";
return *(my_vector[n]);
}
void remove(typename vector_t::size_type n) {
my_list.erase(my_vector[n]);
my_vector[n] = my_list.end();
--my_size;
}
size_t size() const {
return my_size;
}
iterator begin() {
return my_list.begin();
}
iterator end() {
return my_list.end();
}
private:
list_t my_list;
vector_t my_vector;
size_t my_size;
};
В нем отсутствуют некоторые касания качества реализации ... Например, вам, вероятно, нужна дополнительная проверка ошибок (что, если я удалю один и тот же элемент дважды?) И, возможно, немного const
версии operator[]
, begin()
, end()
.Но это только начало.
Тем не менее, для «нескольких тысяч» элементов карта, скорее всего, будет служить как минимум так же.Хорошее практическое правило: «Никогда ничего не оптимизируйте, пока ваш профилировщик не скажет вам».