В стандартной библиотеке используется макс-хип.Макс-хип – это представленное в виде массива двоичное дерево, для которого значение ключа в каждом узле больше либо равно значению ключа в каждом из узлов-потомков. (Подробное обсуждение макс-хипа можно найти в [SEDGEWICK88]. Альтернативой ему является мин-хип,для
которого значение ключа в каждом узле меньше либо равно значению ключа в каждом из узлов-потомков.)В реализации из стандартной библиотеки самое большое значение (корень дерева) всегда оказывается в начале массива. Например, приведенная последовательность букв удовлетворяет требованиям, накладываемым на хип:
X T O G S M N A E R A I
В данном примере X – это корневой узел, слева от него находится T, а справа – O. Обратите внимание, что потомки не обязательно должны быть упорядочены (т.е. значение в левом узле не обязано быть меньше, чем в правом). G и S – потомки узла T, а M и N – потомки узла O. Аналогично A и E – потомки G, R и A – потомки S, I – левый потомок M, а N – листовой узел без потомков.
Четыре обобщенных алгоритма для работы с хипом: make_heap(), pop_heap(), push_heap() и sort_heap() – поддерживают его создание и различные манипуляции. В последних трех алгоритмах предполагается, что последовательность, ограниченная
С++ для начинающих
1163
парой итераторов, – действительно хип (в противном случае поведение программы не определено). Заметим, что список нельзя использовать как контейнер для хранения хипа, поскольку он не поддерживает произвольный доступ. Встроенный массив для размещения хипа использовать можно, но в этом случае трудно применять алгоритмы pop_heap() и push_heap(), так как они требуют изменения размера контейнера. Мы опишем все четыре алгоритма, а затем проиллюстрируем их работу на примере небольшой программы.
template< class RandomAccessIterator > void
make_heap( RandomAccessIterator first, RandomAccessIterator last );
template< class RandomAccessIterator, class Compare > void
make_heap( RandomAccessIterator first,
Алгоритм make_heap()
RandomAccessIterator last, Compare comp );
make_heap() преобразует в хип последовательность, ограниченную диапазоном [first,last). В первом варианте для сравнения используется оператор “меньше”, определенный для типа элементов контейнера, а во втором – операция comp.
template< class RandomAccessIterator > void
pop_heap( RandomAccessIterator first, RandomAccessIterator last );
template< class RandomAccessIterator, class Compare > void
pop_heap( RandomAccessIterator first,
Алгоритм pop_heap()
RandomAccessIterator last, Compare comp );
pop_heap() в действительности не исключает наибольший элемент, а переупорядочивает хип. Он переставляет элементы в позициях first и last-1,а затем перестраивает в хип последовательность в диапазоне [first,last-1).После этого “вытолкнутый” элемент можно получить посредством функции-члена back() контейнера либо по-настоящему исключить его с помощью pop_back(). В первом варианте при сравнении используется оператор “меньше”, определенный для типа элементов контейнера, а во втором – операция comp.
С++ для начинающих
1164
template< class RandomAccessIterator > void
push_heap( RandomAccessIterator first, RandomAccessIterator last );
template< class RandomAccessIterator, class Compare > void
push_heap( RandomAccessIterator first,
Алгоритм push_heap()
RandomAccessIterator last, Compare comp );
push_heap() предполагает, что последовательность, ограниченная диапазоном [first,last-1), – хип и что новый добавляемый к хипу элемент находится в позиции last-1.Все элементы в диапазоне [first,last) реорганизуются в новый хип. Перед вызовом push_heap() необходимо вставить новый элемент в конец контейнера, возможно, применив функцию push_back() (это показано в примере ниже). В первом варианте при сравнении используется оператор “меньше”, определенный для типа элементов контейнера; во втором – операция comp.
template< class RandomAccessIterator > void
sort_heap( RandomAccessIterator first, RandomAccessIterator last );
template< class RandomAccessIterator, class Compare > void
sort_heap( RandomAccessIterator first,
Алгоритм sort_heap()
RandomAccessIterator last, Compare comp );
sort_heap() сортирует последовательность в диапазоне [first,last), предполагая, что это правильно построенный хип; в противном случае поведение программы не определено. (Разумеется, после сортировки хип перестает быть хипом!) В первом варианте при сравнении используется оператор “меньше”, определенный для типа элементов контейнера, а во втором – операция comp.
для объявления указателя на функцию, 372 для улучшения читабельности, 295, 369 как синоним существующего имени типа, 431 массива указателей на функции, 369
typename, 242
использование с параметрами шаблона функции, 480
U
unexpected(), функция
для обработки нераспознанных исключений, 547
unique(), обобщенный алгоритм удаление дубликатов из вектора, 557
unique_copy(), обобщенный алгоритм
запись целых чисел из вектора в стандартный вывод, 579
using-директивы, 423–26
влияние на разрешение перегрузки функции, 463
для объявления перегруженных функций, 437–38
сравнение с using-объявлениями,423–26using-объявления,422–23
влияние на разрешение перегрузки функции, 462
для объявления перегруженных функций, 434–36
сравнение с using-директивами,423–26 utility, заголовочный файл, 127
V
vector, заголовочный файл, 70, 121, 256 void
в списке параметров функции, 325 указатель, 179
void*
преобразование в void* как стандартное преобразование, 456
volatile, квалификатор, 127
С++ для начинающих
для типа параметра, в связи с перегрузкой функций, 432
для функции-члена,611–14
использование преобразования квалификаторов, 471
преобразование квалификаторов, 449
W
while, инструкция, 213–16
сравнение с инструкциями for и do-while, 209
А
абстракция объекта, класс комплексных чисел как
пример, 154 стандартная библиотека, преимущества
использования, 165 автоматические объекты, 388–90
объявление с ключевым словом register, 389– 90
особенности хранения, 388
адапторы функций, для объектов-функций, 573
адапторы функций, 573 адрес(а)
как значение указателя, 88 конкретизированных шаблонов функций, 484
алгоритм(ы)
функция выведение аргумента шаблона, 489
разрешение перегрузки, 511 шаблон как, 475
аргумент(ы), 321 передача, 345
использование указателей для, 87 передача по значению, 327 по умолчанию, 340–43
должны быть хвостовыми, 341
ивиртуальные функции, 913
иустоявшие функции, 472–73
тип
преобразования, разрешение перегрузки функции, 444–60
преобразования, расширение типа, 451–53преобразования, ссылок, 457–59преобразования, стандартные, 453–57
больше (>), оператор поддержка в арифметических типах данных,
30
булевский(е)
константы, операторы, дающие в результате, 146
стандартные преобразования при разрешении перегрузки функции, 453
тип bool, 108–10
В
вектор(ы)
find(), обобщенный алгоритм, 554 емкость, связь с размером, 258 идиоматическое употребление в STL, 123 объектов класса, 689–96присваивание, сравнение со встроенными
массивами, 122 сравнение со списками, 251–52
требования к вставке и доступу, 252 увеличение размера, 253–56
вертикальная табуляция ()
как escape-последовательность, 77 взятия адреса (&) оператор
использование в определении ссылки, 104, 105
использование с именем функции, 367 как унарный оператор, 141
взятия индекса оператор ([]), 736 использование в векторах, 121 использование в классе bitset, 168 использование в отображениях, 294
отсутствие поддержки в контейнерах multimap и multiset, 312
взятия остатка, оператор (%), 142
видимость определения символической константы, 386
переменных в условии цикла, 211, 379–81роль в выборе функции-кандидата при
разрешении перегрузки функции, 460 требование к встроенным функциям, 353, 387 членов класса, 607, 645–52
висячий
проблемы висячего else, описание и устранение, 195
указатель, 389
как проблема динамически выделенного объекта, 394
возврат каретки (\\r)
как escape-последовательность, 77 время жизни, 381
auto_ptr, влияние на динамически выделенные объекты, 395