Массив, который можно быстро изменить - PullRequest
15 голосов
/ 05 января 2009

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

  • Система. Массив - Redim Preserve копирует всю оперативную память из старой в новую, так же медленно, как количество существующих элементов
  • System.Collections. ArrayList - достаточно хорошо?
  • System.Collections. IList - достаточно хорошо?

Ответы [ 5 ]

19 голосов
/ 05 января 2009

Просто суммируем несколько структур данных:

System.Collections.ArrayList : нетипизированные структуры данных устарели. Вместо этого используйте List (of t).

System.Collections.Generic.List (of t) : это представляет массив с изменяемым размером. Эта структура данных использует внутренний массив за сценой. Добавление элементов в List - это O (1), если базовый массив не заполнен, в противном случае его O (n + 1) изменяет размер внутреннего массива и копирует элементы.

List<int> nums = new List<int>(3); // creates a resizable array
                                   // which can hold 3 elements

nums.Add(1);
// adds item in O(1). nums.Capacity = 3, nums.Count = 1

nums.Add(2);
// adds item in O(1). nums.Capacity = 3, nums.Count = 3

nums.Add(3);
// adds item in O(1). nums.Capacity = 3, nums.Count = 3

nums.Add(4);
// adds item in O(n). Lists doubles the size of our internal array, so
// nums.Capacity = 6, nums.count = 4

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

System.Collections.Generic.LinkedList (of t) : если вам не нужен случайный или индексированный доступ к элементам в вашем списке, например, вы только планируете добавлять элементы и выполнять итерацию от первого к наконец, LinkedList - ваш друг. Вставки и удаления - O (1), поиск - O (n).

16 голосов
/ 05 января 2009

Для этого вы должны использовать общий список <> ( System.Collections.Generic.List ). Он работает в постоянное время амортизации .

Он также имеет следующие функции с массивами.

  • Быстрый произвольный доступ (вы можете получить доступ к любому элементу списка в O (1))
  • Это быстро перебрать
  • Медленно вставлять и удалять объекты в начале или в середине (поскольку он должен делать копию всего списка верований)

Если вам нужны быстрые вставки и удаления в начале или конце, используйте связанный список или очереди

3 голосов
/ 05 января 2009

Будет ли работать структура LinkedList для вас? Это (в некоторых случаях) не так интуитивно, как прямой массив, но очень быстро.

  • AddLast для добавления в конец
  • AddBefore / AddAfter для вставки в список
  • AddFirst для добавления в начало

Однако для произвольного доступа это не так быстро, так как вам приходится перебирать структуру для доступа к вашим элементам ... однако он имеет методы .ToList () и .ToArray () для получения копии структуры в списке. / массив формы, так что для доступа на чтение, вы можете сделать это в крайнем случае. Увеличение производительности вставок может перевесить снижение производительности потребности в произвольном доступе или нет. Это будет полностью зависеть от вашей ситуации.

Также есть ссылка, которая поможет вам решить, какой путь выбрать:

Когда использовать связанный список над массивом / списком массивов?

1 голос
/ 05 января 2009

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

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

1 голос
/ 05 января 2009

Что для тебя "достаточно хорошо"? Что именно вы хотите сделать с этой структурой данных?

Нет структуры массива (т.е. доступ O (n)) позволяет вставлять в середину без времени выполнения O (n); вставка в конце - это O (n), в худшем случае O (1) амортизируется для самоизменяющихся массивов, таких как ArrayList.

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

...