Связанный список vs Vector

В последние несколько дней я готовился к самому первому телефонному интервью для разработки программного обеспечения. При исследовании вопросов я придумал эту статью.

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

"Когда вы используете связанный список по отношению к вектору?"

Теперь из опыта и исследований это две очень разные структуры данных, связанный список - динамический массив, а вектор - 2d-точка в пространстве. Единственная корреляция, которую я вижу между двумя, заключается в том, что вы используете вектор как связанный список, например myVector(my value, pointer to neighbor)

Мысли?

Ответы

Ответ 1

Вектор - это другое имя для динамических массивов. Это имя используется для структуры данных динамического массива в С++. Если у вас есть опыт работы на Java, вы можете узнать их с именем ArrayList. (Java также имеет старый класс коллекции Vector, который не используется в настоящее время из-за проблем в том, как он был разработан.)

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

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

Ответ 2

Я знаю, что для этого спрашивающего немного поздно, но это очень проницательное видео от Бьярна Страуструпа (изобретателя C++) о том, почему вы должны избегать связанных списков с современным оборудованием. https://www.youtube.com/watch?v=YQs6IC-vgmo С быстрым распределением памяти на компьютерах сегодня гораздо быстрее создать копию вектора с обновленными элементами.

Ответ 3

Мне не нравится номер один здесь, поэтому я решил поделиться некоторыми фактическими исследованиями, проведенными Herb Sutter от Microsoft. Результаты теста состояли из до 100 тыс. Единиц в контейнере, но также утверждали, что он будет продолжать выполнять связанный список даже на полмиллиона объектов. Если вы не планируете свой контейнер с миллионами объектов, ваш контейнер по умолчанию для динамического контейнера должен быть вектором. Я обобщил более или менее то, что он говорит, но также будет ссылаться ссылка внизу:

"[Даже если] вы предварительно распределяете узлы в связанном списке, что дает вам половину производительности назад, но еще хуже [чем вектор]. Почему? В первую очередь это больше пространства - накладные расходы на элемент ( является частью причины) - указатели вперед и назад, вовлеченные в связанный список, - но также (и, что более важно,) порядок доступа. Связанный список должен пересекаться, чтобы найти точку вставки, выполняя весь этот преследующий указатель, который это то же самое, что делал вектор, но то, что на самом деле происходит, состоит в том, что prefetchers быстрее. Выполнение линейных обходов с данными, которые эффективно отображаются в памяти (выделение и использование, скажем, вектора указателей, которые определяется и выкладывается), он будет превосходить связанные списки почти по каждому сценарию".

https://youtu.be/TJHgp1ugKGM?t=2948

Ответ 4

Используйте вектор, если только "размер данных большой" или "важна сильная гарантия безопасности".

размер данных большой : - вставка вектора в середине занимает линейное время (из-за необходимости перемешать вещи вокруг), но другие - операции с постоянным временем (например, переход на nth node). Поэтому нет больших накладных расходов, если размер данных мал.

В соответствии с "Стандартами кодирования на С++ Книга Андрея Александреску и Херба Саттера"

"Использование вектора для небольших списков почти всегда превосходит использование списка. Несмотря на то, что вставка в середине последовательности представляет собой операцию с линейным временем для вектора и операцию с постоянным временем для списка, вектор обычно превосходит список, когда контейнеры являются относительно небольшими из-за его лучшего постоянного коэффициента, и список преимуществ Big-Oh не срабатывает до тех пор, пока размеры данных не увеличатся".

надежная гарантия безопасности Список обеспечивает надежную гарантию безопасности. http://www.cplusplus.com/reference/list/list/insert/

Ответ 5

Как коррекция времени и удаления Big O в связанном списке, если у вас есть указатель, который содержит позицию текущего элемента, и методы, используемые для перемещения по всему списку (например, .moveToStart(), .moveToEnd(), .next() и т.д.), вы можете удалить и вставить в постоянное время.