C++ Карта STL по сравнению с Векторной скоростью

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

Сначала я представил таблицу с вектором и выполнил итерации через символы, проверяющие если данное приспособленное имя символа.

Затем я хотя с помощью карты, в моем случае map<string,symbol>, было бы лучше, чем итерация через вектор все время, но:

Немного трудно объяснить эту часть, но я попробую.

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

Таким образом, я мог использовать карту для получения переменной: SymbolTable[ myVar.Name ]

Но думайте о следующем: Если переменная, все еще с помощью вектора, найдена в первый раз, когда я могу сохранить его точное целочисленное положение в векторе с ним. Это означает: В следующий раз, когда это необходимо, мой интерпретатор знает, что это "кэшировалось" и не ищет таблицу символов его, но делает что-то как SymbolTable.at( myVar.CachedPosition ).

Теперь мой (довольно трудно?) вопрос:

  • Я должен использовать вектор для таблицы символов вместе с кэшированием положения переменной в векторе?

  • Я должен скорее использовать карту? Почему? Как быстро [] оператор?

  • Я должен использовать что-то совершенно другое?

19
задан sub 3 April 2010 в 21:07
поделиться

12 ответов

Фактически у вас есть несколько альтернатив.

Существуют библиотеки :

  • Loki :: AssocVector : интерфейс карты, реализованный на векторе пар, быстрее, чем карта для небольших или замороженных наборов из-за кеширования местонахождение.
  • Boost.MultiIndex : предоставляет как список с быстрым поиском , так и пример реализации списка MRU (наиболее недавно использованного), который кэширует последние элементы, к которым был осуществлен доступ.

Критики

  • Поиск и извлечение карты занимают O (log N) , но элементы могут быть разбросаны по всей памяти, что не очень хорошо сочетается со стратегиями кэширования.
  • Векторы более удобны для кеширования, однако, если вы не отсортируете их, у вас будет O (N) производительность на find , это приемлемо?
  • Почему бы не использовать unordered_map ? Они обеспечивают поиск и извлечение O (1) (хотя константа может быть высокой) и, безусловно, подходят для этой задачи. Если вы посмотрите статью Википедии о Хеш-таблицах , вы поймете, что существует множество доступных стратегий, и вы, безусловно, можете выбрать ту, которая будет соответствовать вашему конкретному шаблону использования.
13
ответ дан 30 November 2019 в 03:24
поделиться

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

Примите совет Нила ; map обычно является хорошей структурой данных для таблицы символов, но вам нужно убедиться, что вы используете ее правильно (и не добавляете символы случайно).

0
ответ дан 30 November 2019 в 03:24
поделиться

a std :: map (O (log (n))) или хеш-таблица ("амортизированная" O (1)) будет первым выбором - используйте специальные механизмы, если вы определили, что это узкое место. Как правило, первой оптимизацией является использование хеша или токенизации ввода.

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


std :: map , вероятно, немного медленнее для небольшого количества элементов (но тогда это не имеет особого значения).

1
ответ дан 30 November 2019 в 03:24
поделиться

Карта - это хорошая вещь для таблицы символов. но оператор [] для карт - нет. В общем, если вы не пишете какой-то тривиальный код, вам следует использовать функции-члены карты insert () и find () вместо operator [] . Семантика operator [] несколько сложна и почти наверняка не сделает то, что вы хотите, если искомого символа нет на карте.

Что касается выбора между map и unordered_map , разница в производительности вряд ли будет значительной при реализации простого интерпретируемого языка. Если вы используете карту, вам гарантировано, что она будет поддерживаться всеми текущими реализациями Standard C ++.

17
ответ дан 30 November 2019 в 03:24
поделиться

Обычно вы должны использовать таблицу символов для поиска переменной по ее имени, которое указано в источнике. В этом случае у вас есть только имя, с которым можно работать, поэтому хранить кэшированную позицию переменной в таблице символов негде. Так что я бы сказал, что карта - хороший выбор. Оператор [] занимает время, пропорциональное журналу количества элементов на карте - если он окажется медленным, вы можете использовать хэш-карту, например std :: tr1 :: unordered_map .

4
ответ дан 30 November 2019 в 03:24
поделиться

Карта имеет значение O (log N), поэтому не так быстро, как позиционный поиск в массиве. Но точные результаты будут зависеть от множества факторов, и поэтому лучший подход - это взаимодействие с контейнером таким образом, чтобы в дальнейшем можно было переключаться между реализациями. То есть напишите функцию «поиска», которая может быть эффективно реализована любым подходящим контейнером, чтобы позволить себе переключаться и сравнивать скорости различных реализаций.

0
ответ дан 30 November 2019 в 03:24
поделиться

Карта будет масштабироваться намного лучше, что будет важной особенностью. Однако не забывайте, что при использовании карты вы можете (в отличие от вектора) брать указатели и ссылки. В этом случае вы можете легко «кэшировать» переменные с картой так же правильно, как и вектор. Карта здесь почти наверняка будет правильным выбором.

0
ответ дан 30 November 2019 в 03:24
поделиться

std :: map operator [] занимает время O (log (n)). Это означает, что он достаточно эффективен, но вам все же следует избегать повторения поиска снова и снова. Возможно, вместо хранения индекса вы можете сохранить ссылку на значение или итератор на контейнер? Это избавляет от необходимости полностью выполнять поиск.

2
ответ дан 30 November 2019 в 03:24
поделиться

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

Реализации карты STL обычно реализуются с самобалансирующимися деревьями , такими как структура данных красно-черное дерево , и их операции занимают время O (logn).

Мой совет - обернуть код манипуляции таблицей в функции,
вроде table_has (name) , table_put (name) и table_get (имя) .

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

0
ответ дан 30 November 2019 в 03:24
поделиться

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

Например, Python (реализация C) преобразует локальные переменные в ссылки по индексу, но глобальные переменные и переменные класса получают ссылки по имени с использованием хеш-таблицы.

Предлагаю посмотреть вводный текст о компиляторах.

2
ответ дан 30 November 2019 в 03:24
поделиться

Оператором карты [] является O (log (n)), см. Википедию: http://en.wikipedia.org/wiki/Map_ (C% 2B% 2B)

Я думаю, как вы » Если вы часто ищете символы, конечно, правильно использовать карту. Возможно, хеш-карта ( std :: unordered_map ) может улучшить вашу производительность.

0
ответ дан 30 November 2019 в 03:24
поделиться

Вы говорите: "Если переменная, все еще использующая вектор, обнаруживается в первый раз , Я могу сохранить его точное целое число в векторе. ".

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

0
ответ дан 30 November 2019 в 03:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: