Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
adjustable_priority_queue.h
Go to the documentation of this file.
1// Copyright 2010-2024 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_
15#define OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_
16
17#include <stddef.h>
18
19#include <functional>
20#include <list>
21#include <vector>
22
23#include "ortools/base/macros.h"
24
25template <typename T, typename Comparator>
27 public:
28 explicit LowerPriorityThan(Comparator* compare) : compare_(compare) {}
29 bool operator()(T* a, T* b) const { return (*compare_)(*a, *b); }
30
31 private:
32 Comparator* compare_;
33};
34
35template <typename T, typename Comp = std::less<T> >
37 public:
38 // The objects references 'c' and 'm' are not required to be alive for the
39 // lifetime of this object.
41 explicit AdjustablePriorityQueue(const Comp& c) : c_(c) {}
46
47 void Add(T* val) {
48 // Extend the size of the vector by one. We could just use
49 // vector<T>::resize(), but maybe T is not default-constructible.
50 elems_.push_back(val);
51 AdjustUpwards(elems_.size() - 1);
52 }
53
54 void Remove(T* val) {
55 int end = elems_.size() - 1;
56 int i = val->GetHeapIndex();
57 if (i == end) {
58 elems_.pop_back();
59 return;
60 }
61 elems_[i] = elems_[end];
62 elems_[i]->SetHeapIndex(i);
63 elems_.pop_back();
64 NoteChangedPriority(elems_[i]);
65 }
66
67 bool Contains(const T* val) const {
68 int i = val->GetHeapIndex();
69 return (i >= 0 && i < elems_.size() && elems_[i] == val);
70 }
71
72 void NoteChangedPriority(T* val) {
73 LowerPriorityThan<T, Comp> lower_priority(&c_);
74 int i = val->GetHeapIndex();
75 int parent = (i - 1) / 2;
76 if (lower_priority(elems_[parent], val)) {
77 AdjustUpwards(i);
78 } else {
79 AdjustDownwards(i);
80 }
81 }
82 // If val ever changes its priority, you need to call this function
83 // to notify the pq so it can move it in the heap accordingly.
84
85 T* Top() { return elems_[0]; }
86
87 const T* Top() const { return elems_[0]; }
88
89 void AllTop(std::vector<T*>* topvec) {
90 topvec->clear();
91 if (Size() == 0) return;
92 std::list<int> need_to_check_children;
93 need_to_check_children.push_back(0);
94 // Implements breadth-first search down tree, stopping whenever
95 // there's an element < top
96 while (!need_to_check_children.empty()) {
97 int ind = need_to_check_children.front();
98 need_to_check_children.pop_front();
99 topvec->push_back(elems_[ind]);
100 int leftchild = 1 + 2 * ind;
101 if (leftchild < Size()) {
102 if (!LowerPriorityThan<T, Comp>(&c_)(elems_[leftchild], elems_[ind])) {
103 need_to_check_children.push_back(leftchild);
104 }
105 int rightchild = leftchild + 1;
106 if (rightchild < Size() &&
107 !LowerPriorityThan<T, Comp>(&c_)(elems_[rightchild], elems_[ind])) {
108 need_to_check_children.push_back(rightchild);
109 }
110 }
111 }
112 }
113 // If there are ties for the top, this returns all of them.
114
115 void Pop() { Remove(Top()); }
116
117 int Size() const { return elems_.size(); }
118
119 // Returns the number of elements for which storage has been allocated.
120 int Capacity() const { return elems_.capacity(); }
121
122 // Allocates storage for a given number of elements.
123 void SetCapacity(size_t c) { elems_.reserve(c); }
124
125 bool IsEmpty() const { return elems_.empty(); }
126
127 void Clear() { elems_.clear(); }
128
129 // CHECKs that the heap is actually a heap (each "parent" of >=
130 // priority than its child).
131 void CheckValid() {
132 for (int i = 0; i < elems_.size(); ++i) {
133 int left_child = 1 + 2 * i;
134 if (left_child < elems_.size()) {
135 CHECK(
136 !(LowerPriorityThan<T, Comp>(&c_))(elems_[i], elems_[left_child]));
137 }
138 int right_child = left_child + 1;
139 if (right_child < elems_.size()) {
140 CHECK(
141 !(LowerPriorityThan<T, Comp>(&c_))(elems_[i], elems_[right_child]));
142 }
143 }
144 }
145
146 // This is for debugging, e.g. the caller can use it to
147 // examine the heap for rationality w.r.t. other parts of the
148 // program.
149 const std::vector<T*>* Raw() const { return &elems_; }
150
151 private:
152 void AdjustUpwards(int i) {
153 T* const t = elems_[i];
154 while (i > 0) {
155 const int parent = (i - 1) / 2;
156 if (!c_(*elems_[parent], *t)) {
157 break;
158 }
159 elems_[i] = elems_[parent];
160 elems_[i]->SetHeapIndex(i);
161 i = parent;
162 }
163 elems_[i] = t;
164 t->SetHeapIndex(i);
165 }
166
167 void AdjustDownwards(int i) {
168 T* const t = elems_[i];
169 while (true) {
170 const int left_child = 1 + 2 * i;
171 if (left_child >= elems_.size()) {
172 break;
173 }
174 const int right_child = left_child + 1;
175 const int next_i = (right_child < elems_.size() &&
176 c_(*elems_[left_child], *elems_[right_child]))
178 : left_child;
179 if (!c_(*t, *elems_[next_i])) {
180 break;
181 }
182 elems_[i] = elems_[next_i];
183 elems_[i]->SetHeapIndex(i);
184 i = next_i;
185 }
186 elems_[i] = t;
187 t->SetHeapIndex(i);
188 }
189
190 Comp c_;
191 std::vector<T*> elems_;
192};
193
194#endif // OR_TOOLS_BASE_ADJUSTABLE_PRIORITY_QUEUE_H_
int right_child
AdjustablePriorityQueue(AdjustablePriorityQueue &&)=default
bool Contains(const T *val) const
int Capacity() const
Returns the number of elements for which storage has been allocated.
AdjustablePriorityQueue & operator=(AdjustablePriorityQueue &&)=default
AdjustablePriorityQueue & operator=(const AdjustablePriorityQueue &)=delete
void SetCapacity(size_t c)
Allocates storage for a given number of elements.
void AllTop(std::vector< T * > *topvec)
void Pop()
If there are ties for the top, this returns all of them.
AdjustablePriorityQueue(const AdjustablePriorityQueue &)=delete
AdjustablePriorityQueue()=default
const std::vector< T * > * Raw() const
bool operator()(T *a, T *b) const
LowerPriorityThan(Comparator *compare)
int64_t b
Definition table.cc:45
int64_t a
Definition table.cc:44
std::optional< int64_t > end