Большие массивы обозначений O и вставки в связанный список - PullRequest
20 голосов
/ 14 октября 2011

Большие массивы обозначений O и вставки связанных списков:

Согласно академической литературе для массивов это постоянная O (1), а для связанных списков - линейная O (n).

Массив занимает только одно умножение и сложение.

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

Вопрос в том, точно ли O (1) и O (n)Опишите стоимость индексации / поиска для массивов и связанных списков соответственно?

Ответы [ 6 ]

38 голосов
/ 14 октября 2011

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

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

В Википедии есть хороший график: http://en.wikipedia.org/wiki/Linked_list#Linked_lists_vs._dynamic_arrays

                          Linked list   Array   Dynamic array   Balanced tree

Indexing                          Θ(n)   Θ(1)       Θ(1)             Θ(log n)
Insert/delete at beginning        Θ(1)   N/A        Θ(n)             Θ(log n)
Insert/delete at end              Θ(1)   N/A        Θ(1) amortized   Θ(log n)
Insert/delete in middle     search time 
                                + Θ(1)   N/A        Θ(n)             Θ(log n)
Wasted space (average)            Θ(n)    0         Θ(n)[2]          Θ(n)
2 голосов
/ 14 октября 2011

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

Вставки в массив зависят от того, куда вы вставляете, так как вам нужно будет сдвинуть существующие значения. В худшем случае (вставка в массив [0]) - O (x).

Вставка в список - O (1), потому что вам нужно только изменить следующий / предыдущий указатели смежных элементов.

0 голосов
/ 08 октября 2015

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


Согласно академической литературе для массивов это постоянная O (1), а для связанных списков - линейная O (n).

Стоит понять, почему академическая литература цитирует вставку массива как O (1) для массива. Есть несколько концепций для понимания:

  • Массив определяется как несортированный (если явно не указано иное).
  • Длина массива, определяемая как количество элементов, содержащихся в массиве, может быть произвольно увеличена или уменьшена за O (1) времени, и максимальный размер не ограничен массива.

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

  • Вставить и удалить равны O (1), поскольку массив является несортированной структурой данных.

  • Вставка не назначение

Подумайте, что на самом деле означает добавить элемент в несортированную структуру данных. Поскольку не существует определенного порядка сортировки, любой порядок на самом деле происходит произвольно и не имеет значения. Если вы думаете с точки зрения объектно-ориентированного API, сигнатура метода будет выглядеть примерно так:

Array.insert(Element e)

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

LinkedList.insert(Element e)
SortedArray.insert(Element e)

Во всех этих случаях вызывающая сторона метода insert не указывает, где вставляемое значение заканчивается хранением - это внутренняя деталь структуры данных. Кроме того, для вызывающей стороны не имеет смысла пытаться вставить элемент в определенном месте в структуре данных - для отсортированной или несортированной структуры данных. Для (несортированного) связанного списка этот список по определению не отсортирован, и поэтому порядок сортировки не имеет значения. Для отсортированного массива операция вставки по определению вставит элемент в определенную точку массива.

Таким образом, нет смысла определять операцию вставки массива как:

Array.insert(Element e, Index p)

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

Почему это неправильное представление возникает с массивами, а не с другими структурами данных? Возможно, потому что программисты привыкли иметь дело с массивами, используя оператор присваивания:

array[0] = 10
array[1] = 20

Оператор присваивания присваивает значениям массива явный порядок. Здесь важно отметить, что назначение отличается от insert :

  • insert : сохранить заданное значение в структуре данных без изменения существующих элементов.
  • вставить в несортированный : сохранить заданное значение в структуре данных без изменения существующих элементов, и порядок поиска не важен.
  • вставка в отсортированном виде : сохранить заданное значение в структуре данных без изменения существующих элементов, и порядок поиска важен.
  • назначить [x] = v : перезаписать существующие данные в местоположении x с заданным значением v .

несортированный массив не имеет порядка сортировки, и, следовательно, insert не требует разрешения переопределения позиции. insert - это не то же самое, что assignment .Массив insert определяется следующим образом:

Array.insert(v):    
    array.length = array.length + 1
    // in standard algorithmic notation, arrays are defined from 1..n not 0..n-1
    array[array.length] = v

, что O (1).

0 голосов
/ 15 ноября 2012

Давным-давно в системе, в которой было больше ОЗУ, чем дискового пространства, я реализовал индексированный связанный список, который был проиндексирован при вводе вручную или при загрузке с диска.Каждая запись добавлялась к следующему индексу в памяти, и файл на диске открывал запись, добавленную до конца закрытым.

Программа распродавала аукционные продажи на компьютере Radio I Shack Model I и записи на диск былитолько для защиты от перебоев в подаче электроэнергии и для архивированной записи, так как для соблюдения временных ограничений данные должны были быть получены из ОЗУ и распечатаны в обратном порядке, чтобы покупатель мог спросить, был ли первый найденный товар последним, который он приобрел.Каждый покупатель и продавец были связаны с последним проданным товаром, а этот предмет был связан с товаром перед ним.Это был только один список ссылок, который просматривался снизу вверх.

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

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

0 голосов
/ 14 октября 2011

На какую литературу вы ссылаетесь?Размер массива определяется при его создании и никогда не изменяется впоследствии.Вставка действительно возможна только на свободные слоты в конце массива.Любой другой тип вставки может потребовать изменения размера, и это, безусловно, не O(1).Размер связанного списка зависит от реализации, но всегда должен быть как минимум достаточно большим, чтобы хранить все его элементы.Элементы могут быть вставлены в любое место в списке, и поиск соответствующего индекса требует обхода.

0 голосов
/ 14 октября 2011

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

...