использовать карту вместо вектора - PullRequest
2 голосов
/ 09 марта 2012

Я расширяю уже существующий код C ++. Один из членов класса относится к типу vector объектов другого класса:

class Road
{
  ....
  vector<Link*> links;  //Link is just another class
}

Другие модули используют этот класс и его член через множество итераторов последовательности. Теперь, расширяя код, мне нужно добавить в класс Link элемент с именем linkID и использовать этот linkID для поиска / доступа к моим объектам «Link».

Проблема: Я не собираюсь искать объект Link (используя LinkID) в векторе, просматривая миллионы элементов, просто чтобы найти конкретный объект Link. Лучшее решение - «карта»! право

....
map<linkID,*link> links
....
lnk=links[linkID]
.........

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

Итак, мой очевидный вопрос: Можно ли использовать карту вместо вектора (как угодно). Другими словами, я хочу создать карту, заполнить ее, а затем обработать ее как вектор. возможный? Спасибо за ваши комментарии

Ответы [ 5 ]

0 голосов
/ 09 марта 2012

Правильное решение, если linkID является членом Link, будет std::set<Link*, OrderByLinkID>. Предикат OrderByLinkID будет принимать два Link* и будет возвращать true, если у первого будет меньший член linkID.

В результате std :: set все еще содержит Link*, и вы можете перебирать их, как std :: vector. Для сравнения, с std :: map вы бы в конечном итоге перебрали std::pair<Link*, LinkID>, что является гораздо большим изменением.

0 голосов
/ 09 марта 2012

Я сделал это много месяцев назад для железнодорожной сети.Базовыми классами были ссылка и узел.Фактический рельс и в конечном счете маршруты были основаны на вершине этих.IIRC I использовал std::list, чтобы содержать ссылки и узлы, и использовал векторы векторов для содержания реальных треков.

0 голосов
/ 09 марта 2012

Маскировка карты как вектора невозможна как таковая.

Теоретически, вы можете попытаться реализовать новый класс, который является производным от вектора (то есть использует std::vector как основуучебный класс).Внутренне он может использовать карту, а снаружи он будет иметь интерфейс вектора (и он будет принят в качестве замены вектора, потому что он является его производным).

На практике вы можете столкнуться сряд проблем, хотя.Очевидно, вы также унаследовали бы внутренние структуры данных вектора, поэтому вам пришлось бы игнорировать их в своей реализации, то есть оставить их пустыми.Вывод из классов STL (кроме basic_) также противоречит рекомендуемой практике и, возможно, рискован, как @Als указывает в комментарии ниже.

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

0 голосов
/ 09 марта 2012

Я думаю, что вы могли бы сделать это создать расширенную структуру данных: vectormap, которая позволяет вам иметь ключ доступа к элементам с помощью linkID и которая также поддерживает операции std::vector.Оператор [] этого объекта может быть перегружен, так что links[3] дает вам позиционный доступ к вектору, а links[linkID] ищет идентификатор ссылки на карте.Такие вещи, как push_back, могут поддерживаться, если код нуждается в них: push_back должен будет вставить элемент в вектор, а затем также сделать map[item->linkID] = item, чтобы ввести его в карту.Вы, вероятно, получите картину.

0 голосов
/ 09 марта 2012

Лучшее решение - «карта»!да?

Да, похоже, карта - самое простое решение вашей проблемы.Но вместо использования оператора [] я бы использовал методы поиска и вставки.

Изначально вы можете изменить код для использования карты этого типа std::map< unsigned int, link* >, поскольку она наиболее похожа на vector< link* >.Тогда вы можете легко переключиться на std::map< LinkId, link* >.

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