Сложность реализации динамического массива стека

90
10

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


Какова сложность нажатия, если вместо удвоения мы увеличили размер стека на (n + k)?


Мой подход выглядит следующим образом


Предполагая, что стек пуст, а k = 10, мы увеличиваем стек до 10 элементов. После 10 элементов мы делаем 20 элементов и т.д.


Среднее время для копирования элементов вокруг составляет 10 + 20 + 30 +...


Итак, среднее время для нажатия должно быть порядка O (n)?


Правильно ли мой подход?

спросил(а) 2011-12-29T04:28:00+04:00 8 лет, 9 месяцев назад
1
Решение
57

В зависимости от того, как вы увеличили объем хранилища, а k достаточно мал, он может быть O (1) для всех случаев или что-то еще.


Под "как", я имею в виду, в управляемых языках можно создать новый массив размером n + k, а затем скопировать старый массив (размера n) в новый и, наконец, заменить ссылку старого массива к новому. Это будет: O (1) (создание массива, это предположение) + O (n) (копия данных) + O (1) (справка). Мы игнорируем выполнение сборщика мусора, поскольку оно зависит от реализации. В не управляемых языках можно использовать нечто похожее на realloc так, чтобы старые элементы сохранялись без необходимости копировать, потому что новое хранилище занимает одну и ту же область памяти, только расширенное до количества требуемых элементов. В этом случае это O (1) для всех случаев. Обратите внимание, что, однако, иногда расширение хранилища до количества требуемых элементов невозможно из-за фрагментации памяти, поэтому вместо этого используется подход, подобный управляемым языкам (но выполняется неявно с помощью реализации realloc). Для этого сложность такая же, как и в управляемых языках: O (n).

Что ответ с практической точки зрения, надеюсь, вы найдете ответ с аналитической точки зрения, используя вышеприведенный ответ. Удачи.

ответил(а) 2011-12-29T04:55:00+04:00 8 лет, 9 месяцев назад
92

Ваши вычисления неверны. Существует причина, по которой типичная реализация динамического массива удваивает его размер (или, в более общем плане, увеличивает его размер на x процентов).


Если вы увеличиваете размер от 1 до n = 2 i общее количество элементов, которые вы копируете, равно 1 + 2 + 4 + 8 + 16 +... + 2 я . Если вы суммируете это, оно меньше 2 я + 1 поэтому общая временная сложность O (n) и амортизированная временная сложность одной вставки является O (1). Если n не является степенью двух, вычисление будет немного сложнее, но результат будет таким же.

С другой стороны, если вы увеличиваете размер на k, от 0 до n = я * k, общее количество элементов, которые вы копируете, составляет k + 2k + 3k +... + ik. Если вы суммируете это, это будет (ik + k) * (ik/k)/2 = O (n 2 ). И амортизированная сложность одной вставки будет O (n).


Из-за этого ваше решение намного хуже, чем удвоение размера.

ответил(а) 2011-12-29T14:29:00+04:00 8 лет, 9 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема