Разница между std :: list <std :: pair> и std :: map в C ++ stl - PullRequest
38 голосов
/ 02 августа 2010

Подскажите, пожалуйста, разницу между std :: list и std :: map. Могу ли я использовать метод поиска в списке тоже?

Спасибо.

- уточнение

Вопрос отредактирован, чтобы быть более ясным.

Ответы [ 7 ]

109 голосов
/ 02 августа 2010

std::map<X, Y>:

  • - это упорядоченная структура по отношению к ключам (т. Е. При итерации по ней ключи будут постоянно увеличиваться).
  • поддерживает уникальные ключи(X s) только
  • предлагает быстрый метод find() (O(log n)), который находит пару ключ-значение по ключу
  • предлагает оператор индексации map[key], который такжеfast

std::list<std::pair<X, Y> >:

  • - это простая последовательность парных X с и Y с.Они остаются в том порядке, в котором вы их указали.
  • может содержать любое количество дубликатов
  • . Поиск определенного ключа в list - это O(N) (без специального метода)
  • предлагает метод splice.
20 голосов
/ 02 августа 2010

std::pair

std::pair представляет собой шаблонную структуру кортежа, ограниченную двумя элементами, называемыми первым и вторым:

std::pair<int, std::string> myPair ;
myPair.first = 42 ;
myPair.second = "Hello World" ;

std::pair используется STL (и другим кодом) в качестве «универсального контейнера» для объединения двух значений одновременно, без необходимости переопределять еще одно struct.

std::map

std::map - это шаблонный ассоциативный контейнер, связывающий ключи и значения вместе. Самый простой (но не более эффективный) пример:

std::map<int, std::string> myMap ;
myMap[42] = "Fourty Two" ;
myMap[111] = "Hello World" ;
// ...
std::string strText ;  // strText is ""
strText = myMap[111] ; // strText is now "Hello World"
strText = myMap[42] ;  // strText is now "Fourty Two"
strText = myMap[23] ;  // strText is now "" (and myMap has
                       // a new value "" for key 23)

std::pair и std::map

Примечание. Это был ответ на оригинальный неотредактированный вопрос.

Функции std::map должны возвращать итераторы к ключам и значениям одновременно, чтобы оставаться эффективными ... Поэтому очевидным решением является возврат итераторов в пары:

std::map<int, std::string> myMap ;
myMap[42] = "Fourty Two" ;
myMap[111] = "Hello World" ;

myMap.insert(std::make_pair(23, "Bye")) ;

std::map<int, std::string>::iterator it = myMap.find(42) ;
std::pair<int, std::string> keyvalue = *it ;    // We assume 42 does
                                                // exist in the map
int key = keyvalue.first ;
int value = keyvalue.second ;

std::list<std::pair<A,B> > и std::map<A,B>

Примечание: отредактировано после издания вопроса.

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

Карта изначально упорядочена предоставленным функтором, в то время как список будет хранить пары [A, B] там, где вы их положили. Это делает вставку O (log n) для карты, тогда как необработанная вставка внутри списка представляет собой постоянную сложность (поиск, куда ее вставить, является другой проблемой).

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

Таким образом, поиск элемента на карте - это O (log n), тогда как в неупорядоченном списке это O (n). И если список упорядочен, и вы хотите использовать дихотомию, вы не получите ожидаемого прироста производительности, поскольку обход списка элементов в любом случае выполняется поэлементно.

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

3 голосов
/ 02 августа 2010

(отредактировано после уточнения)

std::map оптимизировано для быстрого поиска.У него есть собственный метод find, который использует свою внутреннюю структуру для обеспечения хорошей производительности.В общем случае он будет проверять только ключи log(N), где N - это количество элементов на карте.

std::list<std::pair> - это простой связанный список, поэтому поддерживается только поэлементный обход.Вы можете использовать отдельный алгоритм std::find или std::find_if с пользовательским предикатом, который проверяет только элемент first, чтобы лучше соответствовать семантике std::map::find, но это будет очень медленно.Фактически, он должен будет искать каждую пару в списке для любого неудачного поиска, и будет искать в среднем половину для любого успешного поиска.

2 голосов
/ 02 августа 2010

std:pair содержит ровно два объекта. std:map содержит коллекцию парных объектов.

Вы не можете использовать find () для пары, потому что нечего искать. Вы хотите получить объект pair.First или pair.Second

UPDATE: Предполагая, что вы имели в виду разницу между map<> и list<pair<> >: карта должна быть реализована для быстрого поиска на элементе key. list имеет простой линейный список. Поиск элемента в списке требует прохождения всего списка. Однако std :: find () будет работать на обоих.

1 голос
/ 02 августа 2010

STL-карты - это ассоциативные массивы, обычно реализуемые внутри хеш-карт. Если вы хотите выполнить итерацию по карте STL, она вернет пару STL.

#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
        map<string, int> myMap;
        myMap["myKey"] = 1337;

        map<string, int>::iterator myIterator = myMap.begin();

        pair<string, int> myPair = *myIterator;

        cout<<"the key \""<<myPair.first<<"\" maps to the value of "<<myPair.second<<endl;
        cout<<"the key \"myKey"\" maps to the value of "<<myMap["myKey"]<<endl;
        return 0;
}

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

0 голосов
/ 25 марта 2014

Карта может обеспечить лучшее время поиска в диапазоне O (log n), список может иметь время поиска O (n).

0 голосов
/ 02 августа 2010

std :: pair предназначен только для группировки ровно 2 объектов (скажем, «координаты на странице» составлены из X и Y).

std :: map - это отображение одного набора объектов в другой.

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

Однако вы МОЖЕТЕ использовать std :: pair в качестве значения карты, если вы этого хотите.

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