Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Data Structures and Algorithms in C++ 2e (На ру...docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
2.37 Mб
Скачать

Глава 6. Список и Iterator adTs

Наконец, в Кодовом Фрагменте 6.5, мы представляем запас и вставляем функции. Запасная функция сначала проверяет, превышает ли способность уже n, когда ничто не должно быть сделано. Иначе, это ассигнует новое множество B желаемых размеров, копирует содержание к B, удаляет A и делает B текущим множеством. Функция вставки сначала проверяет, есть ли достаточная способность к еще одному элементу. В противном случае это устанавливает способность максимум в 1 и дважды текущую способность. Затем начинаясь в точке вставки, это перемещает элементы одним положением и хранит новый элемент в желаемом положении.

недействительный ArrayVector:: зарезервируйте (интервал N)

если (способность> = N) возвращение;

Элемент* B = новый Элемент [N]; для (интервал j = 0; j <n; j ++)

B [j] = [j];

// // // //

зарезервируйте, по крайней мере, N, пятна, уже достаточно большие, ассигнуют большее содержание копии множества новому множеству

если (A! = ПУСТОЙ УКАЗАТЕЛЬ), удаляют [] A; //отказываются от старого множества = B; //делают B новой способностью множества = N; //устанавливает новую способность

недействительный ArrayVector:: вставка (интервал i, константа Elem&

если (n> = способность)

зарезервируйте (макс. (1, 2 * способность));

e)

//overflow?

//удвойте размер множества

для (интервал j = n- 1; j> = я; j-)

[j+1] = [j];

[Я] = e; n + +;

//элементы изменения

//вставьте пустое место//еще один элемент

Кодовый Фрагмент 6.5: участник функционирует запас и вставка для класса ArrayVector.

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

Это простое наблюдение позволяет нам показывать, что продолжительность ряда операций, выполненных на первоначально пустом векторе, пропорциональна общему количеству добавленных элементов. Как примечание стенографии, давайте обратимся к вставке элемента, предназначенного, чтобы быть последним элементом в векторе как операция «по толчку». Используя названную амортизацию шаблона, мы показываем ниже того выполнения последовательности операций по толчку на векторе, осуществленном с растяжимым множеством, довольно эффективно. Суждение 6.2: Позвольте V быть вектором, осуществленным посредством растяжимого множества A, как описано выше. Полное время, чтобы выполнить ряд операций по толчку n в V, начинающийся от V являющийся пустым и размер наличия N = 1, является O (n).

Оправдание: чтобы выполнить этот анализ, мы рассматриваем компьютер как монетное

6.1. Векторы 235

прибор, который требует оплаты одного кибердоллара для постоянной суммы

из вычислительного времени. Когда операция выполнена, у нас должно быть достаточно кибер - доллары, доступные в нашем текущем «банковском счете», чтобы заплатить за продолжительность той операции. Таким образом общая сумма кибердолларов, потраченных для любого вычисления, является propor-tional к полному времени, проведенному на том вычислении. Красота использования этого аналитического метода состоит в том, что мы можем запросить чрезмерную цену на некоторые операции, чтобы накопить, чтобы кибердоллары заплатили за других.

Давайте предположим, что одного кибердоллара достаточно, чтобы заплатить за выполнение каждого

выдвиньте операцию в V, исключая время, проведенное для роста множества. Кроме того, давайте предположим, что, выращивая множество от размера k к размеру 2k требует k кибердолларов в течение времени, проведенного, копируя элементы. Мы зарядим каждую операцию по толчку три кибер - доллары. Таким образом мы запрашиваем чрезмерную цену на каждую операцию по толчку, которая не вызывает overflow на два кибердоллара. Думайте о двух кибердолларах, получивших прибыль во вставке, которая не выращивает множество, как «сохраненное» во вставленном элементе.

overflow происходит, когда вектор V имеет 2i элементы для некоторых я³ 0, и

размер множества, используемого V, 2i. Таким образом удвоение размера множества требует 2i

кибердоллары. К счастью, эти кибердоллары могут быть найдены в сохраненных элементах

в клетках 2i-1 через 2i- 1. (См. рисунок 6.3.) Отмечают что предыдущий overflow

произошедший, когда ряд элементов стал более многочисленным, чем 2i-1 впервые,

и таким образом кибердоллары, сохраненные в клетках 2i-1 через 2i- 1, не были ранее

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

за заряженные три кибердоллара и все вычислительное время платят. Таким образом, мы можем заплатить за выполнение операционного использования толчка n 3n кибердоллары.

$ $ $ $$ $ $ $

(a)

0 1 2 3 4 5 6 7

$$

(b)

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Рисунок 6.3: ряд операций по толчку на векторе: (a) множество с 8 клетками полно,

с двумя кибердолларами, «сохраненными» в клетках 4 - 7; (b) операция по толчку вызывает overflow и удвоение способности. За копирование восьми старых элементов к новому множеству платят кибердоллары, уже сохраненные в столе; за вставку нового элемента платит один из кибердолларов, взимаемых к операции по толчку; и два кибердоллара получили прибыль, сохранены в клетке 8.