Очередь с приоритетом может быть реализована на основе конструкции под названием "пирамида" или "heap". Ниже мы будем рассматривать два варианта очередей - с максимальным и минимальным приоритетом. template <class T> class BaseHeap // Очередь с приоритетом { protected: nat _size, max_size; T * heap; // Запрет конструктора копии и оператора присваивания BaseHeap ( const BaseHeap & ); void operator = ( const BaseHeap & ); public: explicit BaseHeap ( nat n ) : _size(0), max_size(n), heap ( new T[n+1] ) {} ~BaseHeap () { delete[] heap; } // Указатель на i-тый элемент ( 0, если i выходит за предел ) const T * operator[] ( nat i ) const { return _size > i ? heap + i + 1 : 0; } T * operator[] ( nat i ) { return _size > i ? heap + i + 1 : 0; } // Количество элементов в очереди nat size() const { return _size; } // Очистить очередь void clear() { _size = 0; } }; template <class T> // Очередь с максимальным приоритетом class MaxHeap : public BaseHeap<T> { // Запрет конструктора копии и оператора присваивания MaxHeap ( const MaxHeap & ); void operator = ( const MaxHeap & ); public: explicit MaxHeap ( nat n ) : BaseHeap<T> ( n ) {} // Поднять i-тый элемент void raise ( nat i ) { if ( i >= _size ) return; for ( ++i; i > 1; ) { const nat j = i >> 1; if ( heap[j] >= heap[i] ) break; _swap ( heap[i], heap[j] ); i = j; } } // Опустить i-тый элемент void down ( nat i ) { for (++i;;) { const nat i1 = i + i; if ( i1 > _size ) break; const nat i2 = i1 + 1; const nat j = i2 > _size ? i1 : heap[i1] >= heap[i2] ? i1 : i2; if ( heap[i] >= heap[j] ) break; _swap ( heap[i], heap[j] ); i = j; } } // Удалить i-тый элемент bool del ( nat i ) { if ( i >= _size ) return false; const nat i1 = i + 1; if ( i1 == _size ) { _size--; return true; } _swap ( heap[i1], heap[_size] ); if ( heap[i1] < heap[_size--] ) down ( i ); else raise ( i ); return true; // Добавить элемент в очередь bool operator << ( const T & o ) { if ( _size == max_size ) return false; heap[++_size] = o; raise ( _size - 1 ); return true; } // Убрать максимальный элемент из очереди bool operator >> ( T & o ) { if ( _size == 0 ) return false; o = heap[1]; _swap ( heap[1], heap[_size--] ); down ( 0 ); return true; } }; template<class T> bool testMaxHeap ( const MaxHeap<T> & heap ) { const nat n = heap.size() / 2; for ( nat j = 0; j < n; ++j ) { const T * t1 = heap[j]; const T * t2 = heap[j+j+1]; if ( t2 && *t2 > *t1 ) return false; const T * t3 = heap[j+j+2]; if ( t3 && *t3 > *t1 ) return false; } return true; }
Для объектов типа-параметра Т должен быть определён оператор >= и
функция _swap, если не подходит стандартная из файла "template.h".
У конструктора имеется единственный параметр - максимальный размер очереди.
Оператор [] возвращает указатель на i-тый элемент ( нумерация начинается с нуля ) или 0, если i выходит за пределы очереди.
Для каждого i-того элемента выполняются 2 неравенства: heap[i] ≥ heap[2 * i + 1] и heap[i] ≥ heap[2 * i + 2].
Функция-член size() возвращает количество элементов в очереди.
Очередь можно очистить при помощи функции-члена clear().
Функция-член raise ( nat i ) поднимает i-тый элемент к началу очереди.
Функция-член down ( nat i ) опускает i-тый элемент к концу очереди.
Функция-член del ( nat i ) удаляет i-тый элемент из очереди.
Оператор << добавляет элемент в очередь, если позволяет её размер.
Оператор >> выносит первый элемент из очереди.
Исходные тексты находятся в файле heap.h. Наверх |