Динамический массив — различия между версиями
Ilyal (обсуждение | вклад) (→Источники информации) |
м (rollbackEdits.php mass rollback) |
||
(не показано 9 промежуточных версий 5 участников) | |||
Строка 7: | Строка 7: | ||
Определим операции, которые мы будем применять к динамическому массиву:<br> | Определим операции, которые мы будем применять к динамическому массиву:<br> | ||
=== get(i) === | === get(i) === | ||
− | :Возвращает значение <tex>i</tex>-ой ячейки массива. Время выполнения | + | :Возвращает значение <tex>i</tex>-ой ячейки массива. Время выполнения {{---}} <tex>O(1)</tex>. |
=== set(i,x) === | === set(i,x) === | ||
− | :В <tex>i</tex>-ую ячейку массива записывается элемент <tex>x</tex>. Время выполнения | + | :В <tex>i</tex>-ую ячейку массива записывается элемент <tex>x</tex>. Время выполнения {{---}} <tex>O(1)</tex>. |
=== add(x) === | === add(x) === | ||
− | :Добавление в массив элемента <tex>x</tex>. Время выполнения | + | :Добавление в массив элемента <tex>x</tex>. Время выполнения {{---}} <tex>O(1)</tex>; в худшем случае, при котором необходимо перенести все элементы из текущего массива во вдвое больший массив {{---}} <tex>O(n)</tex> (<tex>n</tex> {{---}} размер массива). |
=== del() === | === del() === | ||
− | :Удаляет последний элемент массива. В случае, если | + | :Удаляет последний элемент массива. В случае, если количество элементов в массиве в <tex>C</tex> раз меньше его длины, то происходит сжатие в <tex>B</tex> раз. (<tex>C,B</tex> {{---}} константы, зависящие от реализации). Время выполнения операции в худшем случае {{---}} <tex>O(n)</tex>. |
=== size() === | === size() === | ||
− | :Возвращает количество элементов массива. Время выполнения | + | :Возвращает количество элементов массива. Время выполнения {{---}} <tex>O(1)</tex>. |
== Амортизационная стоимость каждой операции == | == Амортизационная стоимость каждой операции == | ||
Строка 23: | Строка 23: | ||
==== Стоимость операции add(x) ==== | ==== Стоимость операции add(x) ==== | ||
[[Файл:Безымянный1.png|400px|thumb|right|Иллюстрация]] | [[Файл:Безымянный1.png|400px|thumb|right|Иллюстрация]] | ||
− | Пусть у нас единицей стоимости операции является одна монетка. Тогда при каждой операции '''add(x)''', при которой нам не требуется копирование, мы будем использовать три монетки. Из них одна пойдёт на стоимость самой этой операции, а две будут в резерве (пусть, если мы добавили <tex>i</tex>-ый элемент, мы будем класть по одной монетке к элементам с номерами <tex>i</tex> и <tex>i-\frac{n}{2}</tex>). В итоге, к тому моменту, как массив будет заполнен, рядом с каждым элементом будет лежать по одной монетке, которую мы и можем использовать на его копирование в новый массив. Таким образом, амортизационная стоимость каждой операции '''add(x)''' {{---}} <tex>3</tex>, и среднее время её работы {{---}} <tex>O(1)</tex>. | + | Пусть у нас единицей стоимости операции является одна монетка. Тогда при каждой операции '''add(x)''', при которой нам не требуется копирование, мы будем использовать три монетки. Из них одна пойдёт на стоимость самой этой операции, а две будут в резерве (пусть, если мы добавили <tex>i</tex>-ый элемент, мы будем класть по одной монетке к элементам с номерами <tex dpi=150>i</tex> и <tex dpi=150>i-\frac{n}{2}</tex>). В итоге, к тому моменту, как массив будет заполнен, рядом с каждым элементом будет лежать по одной монетке, которую мы и можем использовать на его копирование в новый массив. Таким образом, амортизационная стоимость каждой операции '''add(x)''' {{---}} <tex>3</tex>, и среднее время её работы {{---}} <tex>O(1)</tex>. |
==== Стоимость операции del() ==== | ==== Стоимость операции del() ==== | ||
− | При каждой операции будем использовать | + | При каждой операции будем использовать две монетки. Одну из них потратим на само удаление элемента, другую на элемент, стоящий на позиции <tex>i \bmod \dfrac{n}{4}</tex>. Тогда даже в самом худшем случае (только что расширились, а потом <tex>\dfrac{n}{4}</tex> удалили) у каждого элемента из первых <tex>\dfrac{n}{4}</tex> будет по монете и на удаление надо будет потратить только <tex>1</tex> монету. |
+ | |||
=== Метод потенциалов === | === Метод потенциалов === | ||
За потенциал примем число: | За потенциал примем число: | ||
Строка 31: | Строка 32: | ||
2s-c, & \text{if } s\geqslant\frac{1}{2}c \\ | 2s-c, & \text{if } s\geqslant\frac{1}{2}c \\ | ||
\frac{1}{2}c-s, & \text{if } s<\frac{1}{2}c | \frac{1}{2}c-s, & \text{if } s<\frac{1}{2}c | ||
− | \end{cases}</tex> | + | \end{cases}</tex>, где <tex>c</tex> {{---}} размер массива, <tex>s</tex> {{---}} число элементов массива. |
− | |||
− | где <tex>c</tex> {{---}} размер массива, <tex>s</tex> {{---}} число элементов массива. | ||
==== Стоимость операции '''add(x)''' ==== | ==== Стоимость операции '''add(x)''' ==== | ||
Строка 42: | Строка 41: | ||
* <tex dpi=150>\frac{s}{c}<\frac{1}{2}, \frac{s+1}{c}\geqslant\frac{1}{2}</tex>, массив не расширяется: | * <tex dpi=150>\frac{s}{c}<\frac{1}{2}, \frac{s+1}{c}\geqslant\frac{1}{2}</tex>, массив не расширяется: | ||
− | <tex dpi=150>a_i = t_i + \Phi(c, s+1)-\Phi(c, s)= 1 +(2(s+1)-c)-(\frac{1}{2}c - s)= 3+ | + | <tex dpi=150>a_i = t_i + \Phi(c, s+1)-\Phi(c, s)= 1 +(2(s+1)-c)-(\frac{1}{2}c - s)= 3+3s-\frac{3}{2}c= 3 + \frac{s}{c}3c-\frac{3}{2}c <3+\frac{3}{2}c-\frac{3}{2}c=3</tex> |
* <tex dpi=150>\frac{s}{c}<\frac{1}{2}, \frac{s+1}{c}<\frac{1}{2}</tex>, массив не расширяется: <tex dpi=150>a_i = t_i + \Phi(c, s + 1) - \Phi(c, s) = 1 + (\frac{1}{2}c - (s + 1)) - (\frac{1}{2}c - s) = 0</tex> | * <tex dpi=150>\frac{s}{c}<\frac{1}{2}, \frac{s+1}{c}<\frac{1}{2}</tex>, массив не расширяется: <tex dpi=150>a_i = t_i + \Phi(c, s + 1) - \Phi(c, s) = 1 + (\frac{1}{2}c - (s + 1)) - (\frac{1}{2}c - s) = 0</tex> | ||
Строка 53: | Строка 52: | ||
* <tex dpi=150>\frac{1}{4}<\frac{s}{c}<\frac{1}{2}</tex>, массив не сужается: <tex dpi=150>a_i = t_i + \Phi(c, s - 1) - \Phi(c, s) = 1 + (\frac{1}{2}c-(s-1))-(\frac{1}{2}c-s)= 2</tex> | * <tex dpi=150>\frac{1}{4}<\frac{s}{c}<\frac{1}{2}</tex>, массив не сужается: <tex dpi=150>a_i = t_i + \Phi(c, s - 1) - \Phi(c, s) = 1 + (\frac{1}{2}c-(s-1))-(\frac{1}{2}c-s)= 2</tex> | ||
* <tex dpi=150>\frac{s}{c}\geqslant\frac{1}{2}, \frac{s-1}{c}<\frac{1}{2}\Rightarrow s=\frac{1}{2}c</tex>, массив не сужается: <tex dpi=150>a_i = t_i + \Phi(c, s - 1) - \Phi(c, s) =1 +(\frac{1}{2}c-(s-1))-(2s-c)=2+\frac{3}{2}c-3s = 2</tex> | * <tex dpi=150>\frac{s}{c}\geqslant\frac{1}{2}, \frac{s-1}{c}<\frac{1}{2}\Rightarrow s=\frac{1}{2}c</tex>, массив не сужается: <tex dpi=150>a_i = t_i + \Phi(c, s - 1) - \Phi(c, s) =1 +(\frac{1}{2}c-(s-1))-(2s-c)=2+\frac{3}{2}c-3s = 2</tex> | ||
− | * <tex dpi=150>\frac{s}{c}>\frac{1}{2}</tex>, массив не сужается: <tex dpi=150>a_i = t_i + \Phi(c, s - 1) - \Phi(c, s) = 1 + (2(s-1)-c)-(2s-c)= | + | * <tex dpi=150>\frac{s}{c}>\frac{1}{2}</tex>, массив не сужается: <tex dpi=150>a_i = t_i + \Phi(c, s - 1) - \Phi(c, s) = 1 + (2(s-1)-c)-(2s-c)=0</tex> |
− | Средняя стоимость операции | + | Средняя стоимость операции {{---}} <tex>2</tex>, а среднее время работы {{---}} <tex>O(1)</tex>. |
==Динамические массивы в современных языках программирования== | ==Динамические массивы в современных языках программирования== | ||
Строка 66: | Строка 65: | ||
==Источники информации== | ==Источники информации== | ||
* [[wikipedia:Dynamic_array | Wikipedia {{---}} Dynamic array]] | * [[wikipedia:Dynamic_array | Wikipedia {{---}} Dynamic array]] | ||
− | * [[wikipedia:Динамический_массив | Wikipedia {{---}} Динамический массив]] | + | * [[wikipedia:ru:Динамический_массив | Wikipedia {{---}} Динамический массив]] |
[[Категория: Дискретная математика и алгоритмы]] | [[Категория: Дискретная математика и алгоритмы]] | ||
[[Категория: Амортизационный анализ]] | [[Категория: Амортизационный анализ]] |
Текущая версия на 19:05, 4 сентября 2022
Определение: |
Массив — набор однотипных переменных, доступ к которым осуществляется по индексу. Динамический массив может изменять свой размер в зависимости от количества элементов в нём. |
Содержание
Операции
Определим операции, которые мы будем применять к динамическому массиву:
get(i)
- Возвращает значение -ой ячейки массива. Время выполнения — .
set(i,x)
- В -ую ячейку массива записывается элемент . Время выполнения — .
add(x)
- Добавление в массив элемента . Время выполнения — ; в худшем случае, при котором необходимо перенести все элементы из текущего массива во вдвое больший массив — ( — размер массива).
del()
- Удаляет последний элемент массива. В случае, если количество элементов в массиве в раз меньше его длины, то происходит сжатие в раз. ( — константы, зависящие от реализации). Время выполнения операции в худшем случае — .
size()
- Возвращает количество элементов массива. Время выполнения — .
Амортизационная стоимость каждой операции
Пусть наш массив расширяется в
раза, и уменьшается в раза, когда длина массива в раза больше количества элементов в массиве. В этом случае амортизационная стоимость каждой операции будет .Метод предоплаты
Стоимость операции add(x)
Пусть у нас единицей стоимости операции является одна монетка. Тогда при каждой операции add(x), при которой нам не требуется копирование, мы будем использовать три монетки. Из них одна пойдёт на стоимость самой этой операции, а две будут в резерве (пусть, если мы добавили
-ый элемент, мы будем класть по одной монетке к элементам с номерами и ). В итоге, к тому моменту, как массив будет заполнен, рядом с каждым элементом будет лежать по одной монетке, которую мы и можем использовать на его копирование в новый массив. Таким образом, амортизационная стоимость каждой операции add(x) — , и среднее время её работы — .Стоимость операции del()
При каждой операции будем использовать две монетки. Одну из них потратим на само удаление элемента, другую на элемент, стоящий на позиции
. Тогда даже в самом худшем случае (только что расширились, а потом удалили) у каждого элемента из первых будет по монете и на удаление надо будет потратить только монету.Метод потенциалов
За потенциал примем число:
, где — размер массива, — число элементов массива.Стоимость операции add(x)
- , массив расширяется:
- , массив не расширяется:
- , массив не расширяется:
- , массив не расширяется:
В итоге, средняя стоимость операции —
, а среднее время работы — .Стоимость операции del()
- , массив сужается:
- , массив не сужается:
- , массив не сужается:
- , массив не сужается:
Средняя стоимость операции —
, а среднее время работы — .Динамические массивы в современных языках программирования
Динамические массивы широко применяются во многих языках программирования. Рассмотрим, как эта структура данных реализуется в С++ и Java.
С++ — vector
В С++ динамический массив используется в структуре vector, она описана в STL(<vector>). Стратегия расширения проста: при попытке записи в массив нового элемента в момент полного заполнения памяти происходит увеличение размера в
раза при компиляции GNU C++ и в раза при компиляции Microsoft Visual C++. При удалении элементов уменьшение размера массива никогда не происходит. При инициализации vector по-умолчанию начальный размер равен .Java — ArrayList
В Java структура ArrayList основана на динамическом массиве. При превышении максимального на данный момент размера происходит увеличение в
раза. Причем начальный размер равен . Как и в vector, в ArrayList не предусмотрено изменение размера при удалении элементов. Для принудительного изменения размера следует использовать метод trimToSize().