Опубликован: 26.09.2006 | Доступ: свободный | Студентов: 1811 / 503 | Оценка: 4.25 / 4.12 | Длительность: 17:09:00
ISBN: 978-5-9556-0066-6
Специальности: Программист, Математик
Лекция 1:

Вводная

Лекция 1: 123 || Лекция 2 >

Амортизационный анализ работы двоичного счетчика

Рассмотрим работу k -разрядного двоичного сбрасываемого счетчика, реализованного как массив битов A[0 \ldots k-1], хранящего двоичную запись числа x. Будем считать, что A[0] — младший разряд. Пусть первоначально x = 0. Единственной операцией в нашем примере будет операция Increment, увеличивающая x на 1 по модулю 2^k.

Увеличение счетчика на единицу происходит следующим образом: все начальные единичные биты в массиве A, если они есть, становятся нулями, а следующий непосредственно за ними нулевой бит, если он есть, устанавливается в единицу. Стоимость операции Increment линейно зависит от общего количества битов, подвергшихся изменению. Каждое такое изменение будем считать элементарной операцией.

Анализ работы двоичного счетчика методом группировки. Применим метод группировки для анализа сложности n -кратного выполнения операции Increment. Поскольку в худшем случае, когда массив A состоит из одних единиц, меняются все k битов, то n -кратное выполнение операции Increment может быть оценено как O(nk) элементарных операций. Но эта оценка слишком груба.

Чтобы получить более точную оценку, учтем, что не каждый раз значения всех k битов меняются. В самом деле, младший бит A[0] меняется при каждом исполнении операции Increment. Следующий по старшинству бит A[1] меняется только через раз. При счете от нуля до n этот бит меняется [n/2] раз. Бит A[2] меняется только каждый четвертый раз, и так далее. Заметим, что если 0 \le i \le \log_2
n, то в процессе счета от 0 до n разряд A[i] меняется [n/2^i] раз, а если i
> [\log_2 n], то он вообще не меняется. Следовательно, общее количество операций зануления и записи 1 равно

\eq*{
n + [n/2] + [n/4] + \ldots + [n/2]^{[\log n]} < n(1 + 1/2 + 1/4 + \ldots)
= 2n.
}
Тем самым, увеличение двоичного счетчика от 0 до n требует не более O(n) операций, причем константа не зависит от k и равна 2. Учетную стоимость операции Increment можно считать равной O(n)/n = O(1).

Анализ работы двоичного счетчика методом предоплаты. Применим метод предоплаты для анализа сложности n -кратного выполнения операции Increment. Будем считать, что реальная стоимость изменения бита составляет 1 рубль. Установим такие учетные стоимости: 2 рубля за запись единицы, 0 за очистку. При каждой установке бита в единицу одним из двух рублей учетной стоимости будем расплачиваться за реальные затраты на эту установку, а второй рубль, остающийся в резерве, будем "прикреплять" к рассматриваемому биту. Поскольку первоначально все биты были нулевыми, в каждый момент к каждому ненулевому биту будет прикреплен резервный рубль. Стало быть, за очистку любого бита дополнительно платить нам не придется: мы расплатимся за нее рублем, прикрепленным к этому биту в момент его установки.

Теперь легко определить учетную стоимость операции Increment. Поскольку каждая такая операция требует не более одной установки бита, ее учетную стоимость можно считать равной 2 рублям. Следовательно, фактическая стоимость n последовательных операций Increment, начинающихся с нуля, есть O(n), поскольку она не превосходит суммы учетных стоимостей 2n.

Анализ работы двоичного счетчика методом потенциалов. Проанализируем теперь трудоемкость n -кратного выполнения операции Increment с помощью метода потенциалов.

Пусть D_0 — содержимое счетчика в начальный момент, D_i — содержимое счетчика после выполнения i -й операции, \phi(D_i) — число единиц в записи D_i, t_i — число единиц, превращенных в нули при i -й операции. Очевидно, что

\eq*{
\phi(D_i) \le \phi(D_{i-1}) - t_i +1.
}

Пусть далее c_i — реальная стоимость i -й операции Increment, C_i — ее учетная стоимость. Очевидно, что c_i \le t_i + 1. Тогда

C_{i} =c_{i} +\phi (D_{i})-\phi (D_{i-1} )\le t_{i}
+1+\phi (D_{i} )-\phi (D_{i-1} )\le \\
\le t_{i} +1+\phi (D_{i-1})-t_{i} +1-\phi (D_{i-1})=2.

Если счет начинается с нуля, то

\eq*{
\phi (D_{0})=0
}

и

\eq*{
\phi (D_{i} )\ge \phi (D_{0})
}

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

\eq*{
\suml_{i=1}^{n}c_{i}  \le \suml_{i=1}^{n}C_{i}
\le 2n,
}

то есть получаем, что суммарная стоимость n операций есть O(n) с константой (двойкой), не зависящей от k.

Метод потенциалов позволяет разобраться и со случаем, когда счет начинается не с нуля. В этом случае имеем

\eq*{
\begin{gathered}
\suml_{i=1}^{n}C_{i}=\suml_{i=1}^{n}c_{i}
+\phi (D_{n} )-\phi (D_{0}),\\
\suml_{i=1}^{n}c_{i}  =\suml_{i=1}^{n}C_{i}
-\phi (D_{n} )+\phi (D_{0} )\le 2n+\phi (D_{0} )\le 2n+k,
\end{gathered}
}

откуда при достаточно больших значениях n ( n =
\Om(k) ) получаем, что реальная стоимость оценивается как O(n), причем константа в O -записи не зависит ни от k, ни от начального значения счетчика.

Лекция 1: 123 || Лекция 2 >
Антон Сиротинкин
Антон Сиротинкин

на стр 6, лекции 3, Очевидно "Ck <= модуль(Gk(е))*b(k+1)" (1) - , подскажите что значит "модуль" и почему это очевидно...