Advertisement
Guest User

Untitled

a guest
May 20th, 2018
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.68 KB | None | 0 0
  1. /** Класс представляющий очередь с приоритетом. */
  2. template <class T, class K>
  3. class PriorityQueue {
  4. public:
  5.     /** Инициализируем отношение порядка на ключах. */
  6.     PriorityQueue(function<int(const T, const T)> cmp) {
  7.         compare = cmp;
  8.     }
  9.  
  10.     /** Проверка очереди на пустоту **/
  11.     bool isEmpty() {
  12.         return heap.empty();
  13.     }
  14.  
  15.     /** Операция добавления элемента в очередь в соотв. с приорететом **/
  16.     void insert(T element) {
  17.         // Элемент ставится в конец кучи
  18.         // и поднимается обменами к нужной позиции.
  19.         heap.push_back(element);
  20.         int i = (int)heap.size() - 1;
  21.         while (i > 0 && compare(heap[(i - 1) / 2], heap[i]) < 0) {
  22.             swap(heap[(i - 1) / 2], heap[i]);
  23.             heap[i]->setIndex(i);
  24.             i = (i - 1) / 2;
  25.         }
  26.  
  27.         heap[i]->setIndex(i);
  28.     }
  29.  
  30.     /** Операция изменения ключа у элемента очереди ptr. */
  31.     void changeKey(T ptr, K key) {
  32.         ptr->setKey(key);
  33.         int i = ptr->getIndex();
  34.  
  35.         while(i > 0 && compare(heap[(i - 1) / 2], heap[i]) < 0) {
  36.             swap(heap[(i - 1) / 2], heap[i]);
  37.             heap[i]->setIndex(i);
  38.             i = (i - 1) / 2;
  39.         }
  40.  
  41.         ptr->setIndex(i);
  42.     }
  43.  
  44.     /** Снимает с дерева элемент с наибольшим приоритетом,
  45.       * восстанавливает порядок элементов в очереди **/
  46.     T extractRoot() {
  47.         if (heap.empty()) {
  48.             __throw_underflow_error("Error: PriorityQueue is empty!");
  49.         }
  50.  
  51.         T result = heap[0];
  52.         swap(heap[0], heap[heap.size() - 1]);
  53.         heap.pop_back();
  54.  
  55.         if (!heap.empty()) {
  56.             heap[0]->setIndex(0);
  57.             returnHeapOrder();
  58.         }
  59.  
  60.         return result;
  61.     }
  62.  
  63. private:
  64.     function<int(const T, const T)> compare;  // Функция реализующая отношение строго порядка
  65.     vector<T>heap;                            // Куча для хранения данных
  66.  
  67.     /** Служебная функция: восстанавливает кучу после удаления корня.
  68.       *  Элемент опускается обменами на нужную позицию в соотв. с приоритетом **/
  69.     void returnHeapOrder()
  70.     {
  71.         size_t index = 0, child_1, child_2, swap_child;
  72.         while(true)
  73.         {
  74.             // Находим дочерние вершины
  75.             child_1 = 2 * index + 1;
  76.             child_2 = 2 * index + 2;
  77.  
  78.             if (child_1 >= heap.size())
  79.                 child_1 = index;
  80.             if (child_2 >= heap.size())
  81.                 child_2 = index;
  82.  
  83.             // Сравниваем с текущей
  84.             int cmp_1 = compare(heap[index], heap[child_1]);
  85.             int cmp_2 = compare(heap[index], heap[child_2]);
  86.             if ((cmp_1 == 0 || cmp_1 > 0)  && (cmp_2 == 0 || cmp_2 > 0))
  87.                 break; // Элемент на нужном месте
  88.  
  89.             // Производим необходимый обмен
  90.             if (compare (heap[child_1],  heap[child_2]) > 0)
  91.                 swap_child = child_1;
  92.             else
  93.                 swap_child = child_2;
  94.  
  95.             swap(heap[index], heap[swap_child]);
  96.             heap[index]->setIndex(index);
  97.             heap[swap_child]->setIndex(swap_child);
  98.             index = swap_child;
  99.         }
  100.     }
  101. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement