MAXimal | |
добавлено: 17 Jul 2009 23:00 Содержание [скрыть] Рандомизированная кучаРандомизированная куча (randomized heap) — это куча, которая за счёт применения генератора случайных чисел позволяет выполнять все необходимые операции за логарифмическое ожидаемое время. Кучей называется бинарное дерево, для любой вершины которого справедливо, что значение в этой вершине меньше либо равно значений во всех её потомках (это куча для минимума; разумеется, симметрично можно определить кучу для максимума). Таким образом, в корне кучи всегда находится минимум. Стандартный набор операций, определяемый для куч, следующий:
Рандомизированная куча позволяет выполнять все эти операции за ожидаемое время Структура данныхСразу опишем структуру данных, описывающую бинарную кучу: struct tree { T value; tree * l, * r; };В вершине дерева хранится значение ![]() ![]() ![]() Выполнение операцийНетрудно понять, что все операции над кучей сводятся к одной операции: слиянию двух куч в одну. Действительно, добавление элемента в кучу равносильно слиянию этой кучи с кучей, состоящей из единственного добавляемого элемента. Нахождение минимума вообще не требует никаких действий — минимумом просто является корень кучи. Извлечение минимума эквивалентно тому, что куча заменяется результатом слияния левого и правого поддерева корня. Наконец, удаление произвольного элемента аналогично удалению минимума: всё поддерево с корнем в этой вершине заменяется результатом слияния двух поддеревьев-сыновей этой вершины. Итак, нам фактически надо реализовать только операцию слияния двух куч, все остальные операции тривиально сводятся к этой операции. Пусть даны две кучи Таким образом, чтобы достичь логарифмической асимптотики в среднем, нам надо указать способ выбора одного из двух сыновей с тем, чтобы в среднем длина проходимого пути получалась бы порядка логарифма от количества элементов в куче. Нетрудно догадаться, что производить этот выбор мы будем случайно, таким образом, реализация операции слияния получается такой: tree * merge (tree * t1, tree * t2) { if (!t1 || !t2) return t1 ? t1 : t2; if (t2->value < t1->value) swap (t1, t2); if (rand() & 1) swap (t1->l, t1->r); t1->l = merge (t1->l, t2); return t1; } Здесь сначала проверяется, если хотя бы одна из куч пуста, то никаких действий по слиянию производить не надо. Иначе, мы делаем, чтобы куча АсимптотикаВведём случайную величину Математическое ожиданиеУтверждается, что математическое ожидание Доказывается это легко по индукции. Пусть Тогда справедливо: Превышение ожидаемой оценкиДокажем, что вероятность превышения полученной выше оценки мала: ![]() Обозначим через Асимптотика алгоритмаТаким образом, алгоритм Более того, для любой положительной константы
|