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

4.2. Анализ алгоритмов 179

Рекурсия вне себя

Следующие несколько алгоритмов в качестве примера, которые мы изучаем, для решения уникальности элемента

проблема, в которой нам дают диапазон, меня, я + 1..., j, индексов для множества, A, то, которое мы принимаем, дано как вектор STL. Мы хотим определить если элементы этого диапазона, [меня], [я + 1]..., [j], все уникальны, то есть, нет никакого повторного элемента в этой группе записей множества. Первый алгоритм, который мы даем для решения проблемы уникальности элемента, является рекурсивным. Но это использует рекурсию очень неэффективным способом, как показано следующим C ++ внедрение.

bool isUnique (константа vector<int>& прибытие, международное начало, международный конец)

если (начало> = конец) верное возвращение;

если (! isUnique (прибытие, начните, закончите 1)),

возвратитесь ложный;

если (! isUnique (прибытие, start+1, конец))

возвратитесь ложный; возвратитесь (прибытие [начало]! = прибытие [конец]);

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

продолжительность рекурсивного алгоритма, давайте сначала определим, сколько времени мы проводим за пределами рекурсивных вызовов в любой просьбе этой функции. Отметьте, в частности что нет никаких петель - просто сравнения, арифметические операции, элемент множества относится - ences, и прибыль функции. Таким образом нерекурсивная часть каждой просьбы функции бежит в постоянное время, то есть, O (1) время; следовательно, чтобы определить пробег худшего случая - ning время этой функции мы только должны определить общее количество худшего случая звонков, которые мы сделали к функции isUnique.

Позвольте n обозначить, что число записей на рассмотрении, то есть, позволило

n = конец- начинается + 1.

Если n = 1, то продолжительность isUnique - O (1), с тех пор нет никаких рекурсивных вызовов для этого случая. Чтобы характеризовать продолжительность общего случая, impor-tant наблюдение, чтобы сделать является этим, чтобы решить проблему размера n, isUnique

функция сделала два рекурсивных звонка на проблемы размера n- 1. Таким образом, в худшем

случай, призыв к диапазону размера n делает два запроса к диапазонам размера n- 1, который каждый делает двумя запросами к диапазонам размера n- 2, который каждый делает двумя запросами к диапазонам размера n- 3 и так далее. Таким образом, в худшем случае, общем количестве вызовов функции

дан геометрическим суммированием

1 + 2 + 4 + + 2n-1,

который равен 2n- 1 Суждением 4.5. Таким образом, продолжительность худшего случая

функция isUnique является O (2n). Это - невероятно неэффективный метод для решения

проблема уникальности элемента. Его неэффективность прибывает не из факта, что это использует рекурсию - это прибывает из факта, что это использует рекурсию плохо, которая является чем-то, к чему мы обращаемся в Упражнении C-4.2.

180 Глава 4. Аналитические инструменты

Повторяющийся метод для решения проблемы уникальности элемента

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

мычание повторяющийся алгоритм:

bool isUniqueLoop (константа vector<int>& прибытие, международное начало, международный конец)

если (начало> = конец) верное возвращение;

для (интервал i = начало; я <конец; я ++)

для (интервал j = i+1; j <= конец; j ++)

если (прибытие [я] == прибытие [j]) ложное возвращение;

возвратитесь верный;

Эта функция решает проблему уникальности элемента перекручиванием через все отличные пары индексов, меня и j, и проверяющий, вносит ли какой-либо из них пару в указатель элементов, которые равны друг другу. Это делает это использование двух вложенных для петель, такого

то, что первое повторение внешней петли вызывает n- 1 повторение внутренней петли,

второе повторение внешней петли вызывает n- 2 повторения внутренней петли, третье повторение внешней петли вызывает n- 3 повторения внутренней петли и так далее. Таким образом,

продолжительность худшего случая этой функции пропорциональна

1 + 2 + 3 + + (n- 1),

который является O (n2), как мы видели ранее в этой главе (Суждение 4.3).

Используя сортировку как решающий проблему инструмент

Еще лучший алгоритм для проблемы уникальности элемента основан на использовании

сортировка как решающий проблему инструмент. В этом случае, сортируя множество элементов, нам гарантируют тот, любые двойные элементы будут помещены друг рядом с другом. Таким образом это достаточно, чтобы сортировать множество и искать дубликаты среди последовательных элементов. C ++ внедрение этого алгоритма следует.

bool isUniqueSort (константа vector<int>& прибытие, международное начало, международный конец)

если (начало> = конец) верное возвращение;

вектор <интервал> buf (прибытие); //дубликат вида прибытия (buf.begin () +start, buf.begin () +end); //сортируют подмножество для (интервал i = начало; я <конец; я ++) //проверяют на дубликаты

если (buf [я] == buf [i+1]) ложное возвращение;

возвратитесь верный;

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