Split datastruct.h
Split into separate files concatenable_queue.hpp and priority_queue.hpp. Move classes into namespace. Separate unit testse.
This commit is contained in:
		
							parent
							
								
									087799cdca
								
							
						
					
					
						commit
						0f18b7b05a
					
				
							
								
								
									
										23
									
								
								cpp/Makefile
								
								
								
								
							
							
						
						
									
										23
									
								
								cpp/Makefile
								
								
								
								
							|  | @ -6,27 +6,34 @@ CXXFLAGS = -std=c++11 -Wall -Wextra $(OPTFLAGS) $(DBGFLAGS) | |||
| LIB_BOOST_TEST = -l:libboost_unit_test_framework.a | ||||
| 
 | ||||
| .PHONY: all | ||||
| all: run_matching run_matching_dbg test_mwmatching | ||||
| all: run_matching run_matching_dbg test_mwmatching test_concatenable_queue test_priority_queue | ||||
| 
 | ||||
| run_matching: run_matching.cpp mwmatching.h | ||||
| run_matching: run_matching.cpp mwmatching.h concatenable_queue.hpp priority_queue.hpp | ||||
| 	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< | ||||
| 
 | ||||
| run_matching_dbg: OPTFLAGS = -Og | ||||
| run_matching_dbg: DBGFLAGS = -g -fsanitize=address -fsanitize=undefined | ||||
| run_matching_dbg: run_matching.cpp mwmatching.h | ||||
| run_matching_dbg: run_matching.cpp mwmatching.h concatenable_queue.hpp priority_queue.hpp | ||||
| 	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< | ||||
| 
 | ||||
| test_mwmatching: OPTFLAGS = -O1 | ||||
| test_mwmatching: DBGFLAGS = -fsanitize=address -fsanitize=undefined | ||||
| test_mwmatching: test_mwmatching.cpp mwmatching.h | ||||
| test_mwmatching: test_mwmatching.cpp mwmatching.h concatenable_queue.hpp priority_queue.hpp | ||||
| 	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LIB_BOOST_TEST) | ||||
| 
 | ||||
| test_datastruct: OPTFLAGS = -O1 | ||||
| test_datastruct: DBGFLAGS = -fsanitize=address -fsanitize=undefined | ||||
| test_datastruct: test_datastruct.cpp datastruct.h | ||||
| test_concatenable_queue: OPTFLAGS = -O1 | ||||
| test_concatenable_queue: DBGFLAGS = -fsanitize=address -fsanitize=undefined | ||||
| test_concatenable_queue: test_concatenable_queue.cpp concatenable_queue.hpp | ||||
| 	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LIB_BOOST_TEST) | ||||
| 
 | ||||
| test_priority_queue: OPTFLAGS = -O1 | ||||
| test_priority_queue: DBGFLAGS = -fsanitize=address -fsanitize=undefined | ||||
| test_priority_queue: test_priority_queue.cpp priority_queue.hpp | ||||
| 	$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $@ $< $(LIB_BOOST_TEST) | ||||
| 
 | ||||
| .PHONY: clean | ||||
| clean: | ||||
| 	$(RM) run_matching run_matching_dbg test_mwmatching | ||||
| 	$(RM) run_matching run_matching_dbg | ||||
| 	$(RM) test_mwmatching | ||||
| 	$(RM) test_concatenable_queue test_priority_queue | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,17 +1,17 @@ | |||
| /*
 | ||||
|  * Data structures for matching. | ||||
| /**
 | ||||
|  * Concatenable queue data structure. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef MWMATCHING_CONCATENABLE_QUEUE_H_ | ||||
| #define MWMATCHING_CONCATENABLE_QUEUE_H_ | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <cassert> | ||||
| #include <limits> | ||||
| #include <tuple> | ||||
| #include <vector> | ||||
| 
 | ||||
| 
 | ||||
| /* **************************************************
 | ||||
|  * **        class ConcatenableQueue               ** | ||||
|  * ************************************************** */ | ||||
| namespace mwmatching { | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Priority queue supporting efficient merge and split operations. | ||||
|  | @ -836,253 +836,6 @@ private: | |||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* **************************************************
 | ||||
|  * **        class PriorityQueue                   ** | ||||
|  * ************************************************** */ | ||||
| } // namespace mwmatching
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Min-priority queue implemented as a binary heap. | ||||
|  * | ||||
|  * Elements in a heap have a priority and associated "data". | ||||
|  * | ||||
|  * The following operations can be done efficiently: | ||||
|  *  - Insert an element into the queue. | ||||
|  *  - Remove an element from the queue. | ||||
|  *  - Change the priority of a given element. | ||||
|  *  - Find the element with lowest priority in the queue. | ||||
|  */ | ||||
| template <typename PrioType, | ||||
|           typename DataType> | ||||
| class PriorityQueue | ||||
| { | ||||
| public: | ||||
|     typedef unsigned int IndexType; | ||||
|     static constexpr IndexType INVALID_INDEX = | ||||
|         std::numeric_limits<IndexType>::max(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * A Node instance represents an element in a PriorityQueue. | ||||
|      * | ||||
|      * A Node instance must remain valid while it is contained in a queue. | ||||
|      * The containing queue holds a pointer to the Node. | ||||
|      * | ||||
|      * A Node instance may be destructed if it is not contained in any queue. | ||||
|      * Alternatively, a Node instance may be destructed after its containing | ||||
|      * queue instance has been destructed. | ||||
|      */ | ||||
|     class Node | ||||
|     { | ||||
|       public: | ||||
|         /** Construct an invalid node, not contained in any queue. */ | ||||
|         Node() | ||||
|           : index_(INVALID_INDEX) | ||||
|         { } | ||||
| 
 | ||||
|         // Prevent copying.
 | ||||
|         Node(const Node&) = delete; | ||||
|         Node& operator=(const Node&) = delete; | ||||
| 
 | ||||
|         /** Return true if this node is contained in a queue. */ | ||||
|         bool valid() const | ||||
|         { | ||||
|             return (index_ != INVALID_INDEX); | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
|          * Return the priority of this node in the queue. | ||||
|          * | ||||
|          * The node must be contained in a queue. | ||||
|          * This function takes time O(1). | ||||
|          */ | ||||
|         PrioType prio() const | ||||
|         { | ||||
|             assert(index_ != INVALID_INDEX); | ||||
|             return prio_; | ||||
|         } | ||||
| 
 | ||||
|       private: | ||||
|         IndexType       index_; | ||||
|         PrioType        prio_; | ||||
|         DataType        data_; | ||||
| 
 | ||||
|         friend class PriorityQueue; | ||||
|     }; | ||||
| 
 | ||||
|     /** Construct an empty queue. */ | ||||
|     PriorityQueue() | ||||
|     { } | ||||
| 
 | ||||
|     // Prevent copying.
 | ||||
|     PriorityQueue(const PriorityQueue&) = delete; | ||||
|     PriorityQueue& operator=(const PriorityQueue&) = delete; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Remove all elements from the queue. | ||||
|      * | ||||
|      * This function takes time O(n). | ||||
|      */ | ||||
|     void clear() | ||||
|     { | ||||
|         for (Node* node : heap_) { | ||||
|             node->index_ = INVALID_INDEX; | ||||
|         } | ||||
|         heap_.clear(); | ||||
|     } | ||||
| 
 | ||||
|     /** Return true if the queue is empty. */ | ||||
|     bool empty() const | ||||
|     { | ||||
|         return heap_.empty(); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Return the minimum priority of any element in the queue. | ||||
|      * | ||||
|      * The queue must be non-empty. | ||||
|      * This function takes time O(1). | ||||
|      */ | ||||
|     PrioType min_prio() const | ||||
|     { | ||||
|         assert(! heap_.empty()); | ||||
|         Node* top = heap_.front(); | ||||
|         return top->prio_; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Return the element with minimum priority. | ||||
|      * | ||||
|      * The queue must be non-empty. | ||||
|      * This function takes time O(1). | ||||
|      */ | ||||
|     DataType min_elem() const | ||||
|     { | ||||
|         assert(! heap_.empty()); | ||||
|         Node* top = heap_.front(); | ||||
|         return top->data_; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Insert the given node into the queue with associated data. | ||||
|      * | ||||
|      * The node must not currently be contained in any queue. | ||||
|      * This function takes amortized time O(log(n)). | ||||
|      */ | ||||
|     void insert(Node* node, PrioType prio, const DataType& data) | ||||
|     { | ||||
|         assert(node->index_ == INVALID_INDEX); | ||||
| 
 | ||||
|         node->index_ = heap_.size(); | ||||
|         node->prio_ = prio; | ||||
|         node->data_ = data; | ||||
| 
 | ||||
|         heap_.push_back(node); | ||||
|         sift_up(node->index_); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Update priority of an existing node. | ||||
|      * | ||||
|      * This function takes time O(log(n)). | ||||
|      */ | ||||
|     void set_prio(Node* node, PrioType prio) | ||||
|     { | ||||
|         IndexType index = node->index_; | ||||
|         assert(index != INVALID_INDEX); | ||||
|         assert(heap_[index] == node); | ||||
| 
 | ||||
|         PrioType prev_prio = node->prio_; | ||||
|         node->prio_ = prio; | ||||
| 
 | ||||
|         if (prio < prev_prio) { | ||||
|             sift_up(index); | ||||
|         } else if (prio > prev_prio) { | ||||
|             sift_down(index); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Remove the specified element from the queue. | ||||
|      * | ||||
|      * This function takes time O(log(n)). | ||||
|      */ | ||||
|     void remove(Node* node) | ||||
|     { | ||||
|         IndexType index = node->index_; | ||||
|         assert(index != INVALID_INDEX); | ||||
|         assert(heap_[index] == node); | ||||
| 
 | ||||
|         node->index_ = INVALID_INDEX; | ||||
| 
 | ||||
|         Node* move_node = heap_.back(); | ||||
|         heap_.pop_back(); | ||||
| 
 | ||||
|         if (index < heap_.size()) { | ||||
|             heap_[index] = move_node; | ||||
|             move_node->index_ = index; | ||||
|             if (move_node->prio_ < node->prio_) { | ||||
|                 sift_up(index); | ||||
|             } else if (move_node->prio_ > node->prio_) { | ||||
|                 sift_down(index); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     /** Repair the heap along an ascending path to the root. */ | ||||
|     void sift_up(IndexType index) | ||||
|     { | ||||
|         Node* node = heap_[index]; | ||||
|         PrioType prio = node->prio_; | ||||
| 
 | ||||
|         while (index > 0) { | ||||
|             IndexType next_index = (index - 1) / 2; | ||||
|             Node* next_node = heap_[next_index]; | ||||
|             if (next_node->prio_ <= prio) { | ||||
|                 break; | ||||
|             } | ||||
|             heap_[index] = next_node; | ||||
|             next_node->index_ = index; | ||||
|             index = next_index; | ||||
|         } | ||||
| 
 | ||||
|         node->index_ = index; | ||||
|         heap_[index] = node; | ||||
|     } | ||||
| 
 | ||||
|     /** Repair the heap along a descending path. */ | ||||
|     void sift_down(IndexType index) | ||||
|     { | ||||
|         Node* node = heap_[index]; | ||||
|         PrioType prio = node->prio_; | ||||
| 
 | ||||
|         IndexType num_elem = heap_.size(); | ||||
| 
 | ||||
|         while (index < num_elem / 2) { | ||||
|             IndexType next_index = 2 * index + 1; | ||||
|             Node* next_node = heap_[next_index]; | ||||
| 
 | ||||
|             if (next_index + 1 < num_elem) { | ||||
|                 Node* tmp_node = heap_[next_index + 1]; | ||||
|                 if (tmp_node->prio_ <= next_node->prio_) { | ||||
|                     ++next_index; | ||||
|                     next_node = tmp_node; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (next_node->prio_ >= prio) { | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             heap_[index] = next_node; | ||||
|             next_node->index_ = index; | ||||
| 
 | ||||
|             index = next_index; | ||||
|         } | ||||
| 
 | ||||
|         heap_[index] = node; | ||||
|         node->index_ = index; | ||||
|     } | ||||
| 
 | ||||
|     /** Heap data structure. */ | ||||
|     std::vector<Node*> heap_; | ||||
| }; | ||||
| #endif  // MWMATCHING_CONCATENABLE_QUEUE_H_
 | ||||
|  | @ -19,7 +19,8 @@ | |||
| #include <utility> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include "datastruct.h" | ||||
| #include "concatenable_queue.hpp" | ||||
| #include "priority_queue.hpp" | ||||
| 
 | ||||
| 
 | ||||
| namespace mwmatching { | ||||
|  |  | |||
|  | @ -0,0 +1,266 @@ | |||
| /**
 | ||||
|  * Priority queue data structure. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef MWMATCHING_PRIORITY_QUEUE_H_ | ||||
| #define MWMATCHING_PRIORITY_QUEUE_H_ | ||||
| 
 | ||||
| #include <cassert> | ||||
| #include <limits> | ||||
| #include <vector> | ||||
| 
 | ||||
| 
 | ||||
| namespace mwmatching { | ||||
| 
 | ||||
| 
 | ||||
| /**
 | ||||
|  * Min-priority queue implemented as a binary heap. | ||||
|  * | ||||
|  * Elements in a heap have a priority and associated "data". | ||||
|  * | ||||
|  * The following operations can be done efficiently: | ||||
|  *  - Insert an element into the queue. | ||||
|  *  - Remove an element from the queue. | ||||
|  *  - Change the priority of a given element. | ||||
|  *  - Find the element with lowest priority in the queue. | ||||
|  */ | ||||
| template <typename PrioType, | ||||
|           typename DataType> | ||||
| class PriorityQueue | ||||
| { | ||||
| public: | ||||
|     typedef unsigned int IndexType; | ||||
|     static constexpr IndexType INVALID_INDEX = | ||||
|         std::numeric_limits<IndexType>::max(); | ||||
| 
 | ||||
|     /**
 | ||||
|      * A Node instance represents an element in a PriorityQueue. | ||||
|      * | ||||
|      * A Node instance must remain valid while it is contained in a queue. | ||||
|      * The containing queue holds a pointer to the Node. | ||||
|      * | ||||
|      * A Node instance may be destructed if it is not contained in any queue. | ||||
|      * Alternatively, a Node instance may be destructed after its containing | ||||
|      * queue instance has been destructed. | ||||
|      */ | ||||
|     class Node | ||||
|     { | ||||
|       public: | ||||
|         /** Construct an invalid node, not contained in any queue. */ | ||||
|         Node() | ||||
|           : index_(INVALID_INDEX) | ||||
|         { } | ||||
| 
 | ||||
|         // Prevent copying.
 | ||||
|         Node(const Node&) = delete; | ||||
|         Node& operator=(const Node&) = delete; | ||||
| 
 | ||||
|         /** Return true if this node is contained in a queue. */ | ||||
|         bool valid() const | ||||
|         { | ||||
|             return (index_ != INVALID_INDEX); | ||||
|         } | ||||
| 
 | ||||
|         /**
 | ||||
|          * Return the priority of this node in the queue. | ||||
|          * | ||||
|          * The node must be contained in a queue. | ||||
|          * This function takes time O(1). | ||||
|          */ | ||||
|         PrioType prio() const | ||||
|         { | ||||
|             assert(index_ != INVALID_INDEX); | ||||
|             return prio_; | ||||
|         } | ||||
| 
 | ||||
|       private: | ||||
|         IndexType       index_; | ||||
|         PrioType        prio_; | ||||
|         DataType        data_; | ||||
| 
 | ||||
|         friend class PriorityQueue; | ||||
|     }; | ||||
| 
 | ||||
|     /** Construct an empty queue. */ | ||||
|     PriorityQueue() | ||||
|     { } | ||||
| 
 | ||||
|     // Prevent copying.
 | ||||
|     PriorityQueue(const PriorityQueue&) = delete; | ||||
|     PriorityQueue& operator=(const PriorityQueue&) = delete; | ||||
| 
 | ||||
|     /**
 | ||||
|      * Remove all elements from the queue. | ||||
|      * | ||||
|      * This function takes time O(n). | ||||
|      */ | ||||
|     void clear() | ||||
|     { | ||||
|         for (Node* node : heap_) { | ||||
|             node->index_ = INVALID_INDEX; | ||||
|         } | ||||
|         heap_.clear(); | ||||
|     } | ||||
| 
 | ||||
|     /** Return true if the queue is empty. */ | ||||
|     bool empty() const | ||||
|     { | ||||
|         return heap_.empty(); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Return the minimum priority of any element in the queue. | ||||
|      * | ||||
|      * The queue must be non-empty. | ||||
|      * This function takes time O(1). | ||||
|      */ | ||||
|     PrioType min_prio() const | ||||
|     { | ||||
|         assert(! heap_.empty()); | ||||
|         Node* top = heap_.front(); | ||||
|         return top->prio_; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Return the element with minimum priority. | ||||
|      * | ||||
|      * The queue must be non-empty. | ||||
|      * This function takes time O(1). | ||||
|      */ | ||||
|     DataType min_elem() const | ||||
|     { | ||||
|         assert(! heap_.empty()); | ||||
|         Node* top = heap_.front(); | ||||
|         return top->data_; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Insert the given node into the queue with associated data. | ||||
|      * | ||||
|      * The node must not currently be contained in any queue. | ||||
|      * This function takes amortized time O(log(n)). | ||||
|      */ | ||||
|     void insert(Node* node, PrioType prio, const DataType& data) | ||||
|     { | ||||
|         assert(node->index_ == INVALID_INDEX); | ||||
| 
 | ||||
|         node->index_ = heap_.size(); | ||||
|         node->prio_ = prio; | ||||
|         node->data_ = data; | ||||
| 
 | ||||
|         heap_.push_back(node); | ||||
|         sift_up(node->index_); | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Update priority of an existing node. | ||||
|      * | ||||
|      * This function takes time O(log(n)). | ||||
|      */ | ||||
|     void set_prio(Node* node, PrioType prio) | ||||
|     { | ||||
|         IndexType index = node->index_; | ||||
|         assert(index != INVALID_INDEX); | ||||
|         assert(heap_[index] == node); | ||||
| 
 | ||||
|         PrioType prev_prio = node->prio_; | ||||
|         node->prio_ = prio; | ||||
| 
 | ||||
|         if (prio < prev_prio) { | ||||
|             sift_up(index); | ||||
|         } else if (prio > prev_prio) { | ||||
|             sift_down(index); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|      * Remove the specified element from the queue. | ||||
|      * | ||||
|      * This function takes time O(log(n)). | ||||
|      */ | ||||
|     void remove(Node* node) | ||||
|     { | ||||
|         IndexType index = node->index_; | ||||
|         assert(index != INVALID_INDEX); | ||||
|         assert(heap_[index] == node); | ||||
| 
 | ||||
|         node->index_ = INVALID_INDEX; | ||||
| 
 | ||||
|         Node* move_node = heap_.back(); | ||||
|         heap_.pop_back(); | ||||
| 
 | ||||
|         if (index < heap_.size()) { | ||||
|             heap_[index] = move_node; | ||||
|             move_node->index_ = index; | ||||
|             if (move_node->prio_ < node->prio_) { | ||||
|                 sift_up(index); | ||||
|             } else if (move_node->prio_ > node->prio_) { | ||||
|                 sift_down(index); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     /** Repair the heap along an ascending path to the root. */ | ||||
|     void sift_up(IndexType index) | ||||
|     { | ||||
|         Node* node = heap_[index]; | ||||
|         PrioType prio = node->prio_; | ||||
| 
 | ||||
|         while (index > 0) { | ||||
|             IndexType next_index = (index - 1) / 2; | ||||
|             Node* next_node = heap_[next_index]; | ||||
|             if (next_node->prio_ <= prio) { | ||||
|                 break; | ||||
|             } | ||||
|             heap_[index] = next_node; | ||||
|             next_node->index_ = index; | ||||
|             index = next_index; | ||||
|         } | ||||
| 
 | ||||
|         node->index_ = index; | ||||
|         heap_[index] = node; | ||||
|     } | ||||
| 
 | ||||
|     /** Repair the heap along a descending path. */ | ||||
|     void sift_down(IndexType index) | ||||
|     { | ||||
|         Node* node = heap_[index]; | ||||
|         PrioType prio = node->prio_; | ||||
| 
 | ||||
|         IndexType num_elem = heap_.size(); | ||||
| 
 | ||||
|         while (index < num_elem / 2) { | ||||
|             IndexType next_index = 2 * index + 1; | ||||
|             Node* next_node = heap_[next_index]; | ||||
| 
 | ||||
|             if (next_index + 1 < num_elem) { | ||||
|                 Node* tmp_node = heap_[next_index + 1]; | ||||
|                 if (tmp_node->prio_ <= next_node->prio_) { | ||||
|                     ++next_index; | ||||
|                     next_node = tmp_node; | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (next_node->prio_ >= prio) { | ||||
|                 break; | ||||
|             } | ||||
| 
 | ||||
|             heap_[index] = next_node; | ||||
|             next_node->index_ = index; | ||||
| 
 | ||||
|             index = next_index; | ||||
|         } | ||||
| 
 | ||||
|         heap_[index] = node; | ||||
|         node->index_ = index; | ||||
|     } | ||||
| 
 | ||||
|     /** Heap data structure. */ | ||||
|     std::vector<Node*> heap_; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| } // namespace mwmatching
 | ||||
| 
 | ||||
| #endif  // MWMATCHING_PRIORITY_QUEUE_H_
 | ||||
|  | @ -1,33 +1,29 @@ | |||
| /*
 | ||||
|  * Unit tests for data structures. | ||||
|  * Unit tests for ConcatenableQueue data structure. | ||||
|  * | ||||
|  * Depends on the Boost.Test unit test framework. | ||||
|  * Tested with Boost v1.74, available from https://www.boost.org/
 | ||||
|  */ | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <climits> | ||||
| #include <memory> | ||||
| #include <random> | ||||
| #include <set> | ||||
| #include <string> | ||||
| #include <tuple> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| 
 | ||||
| #define BOOST_TEST_MODULE datastruct | ||||
| #include <boost/test/unit_test.hpp> | ||||
| 
 | ||||
| #include "datastruct.h" | ||||
| #include "concatenable_queue.hpp" | ||||
| 
 | ||||
| 
 | ||||
| /* **********  Test ConcatenableQueue  ********** */ | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE(test_concatenable_queue) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_single) | ||||
| { | ||||
|     using Queue = ConcatenableQueue<int, std::string, std::string>; | ||||
|     using Queue = mwmatching::ConcatenableQueue<int, std::string, std::string>; | ||||
|     Queue q("Q"); | ||||
|     BOOST_TEST(q.name() == std::string("Q")); | ||||
| 
 | ||||
|  | @ -49,7 +45,7 @@ BOOST_AUTO_TEST_CASE(test_single) | |||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_simple) | ||||
| { | ||||
|     using Queue = ConcatenableQueue<int, std::string, char>; | ||||
|     using Queue = mwmatching::ConcatenableQueue<int, std::string, char>; | ||||
|     Queue::Node n1, n2, n3, n4, n5; | ||||
| 
 | ||||
|     Queue q1("A"); | ||||
|  | @ -140,7 +136,7 @@ BOOST_AUTO_TEST_CASE(test_simple) | |||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_medium) | ||||
| { | ||||
|     using Queue = ConcatenableQueue<int, char, char>; | ||||
|     using Queue = mwmatching::ConcatenableQueue<int, char, char>; | ||||
| 
 | ||||
|     std::vector<char> queue_names(19); | ||||
|     for (int i = 0; i < 14; i++) { | ||||
|  | @ -255,7 +251,7 @@ BOOST_AUTO_TEST_CASE(test_medium) | |||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_random) | ||||
| { | ||||
|     using Queue = ConcatenableQueue<double, int, int>; | ||||
|     using Queue = mwmatching::ConcatenableQueue<double, int, int>; | ||||
| 
 | ||||
|     constexpr int NUM_NODES = 4000; | ||||
| 
 | ||||
|  | @ -405,238 +401,3 @@ BOOST_AUTO_TEST_CASE(test_random) | |||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
| 
 | ||||
| 
 | ||||
| /* **********  Test PriorityQueue  ********** */ | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE(test_priority_queue) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_empty) | ||||
| { | ||||
|     using Queue = PriorityQueue<int, std::string>; | ||||
|     Queue q; | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_single) | ||||
| { | ||||
|     using Queue = PriorityQueue<int, std::string>; | ||||
|     Queue q; | ||||
| 
 | ||||
|     Queue::Node n1; | ||||
|     BOOST_TEST(n1.valid() == false); | ||||
| 
 | ||||
|     q.insert(&n1, 5, "a"); | ||||
| 
 | ||||
|     BOOST_TEST(n1.valid() == true); | ||||
|     BOOST_TEST(n1.prio() == 5); | ||||
|     BOOST_TEST(q.empty() == false); | ||||
|     BOOST_TEST(q.min_prio() == 5); | ||||
|     BOOST_TEST(q.min_elem() == std::string("a")); | ||||
| 
 | ||||
|     q.set_prio(&n1, 3); | ||||
|     BOOST_TEST(n1.prio() == 3); | ||||
|     BOOST_TEST(q.min_prio() == 3); | ||||
|     BOOST_TEST(q.min_elem() == std::string("a")); | ||||
| 
 | ||||
|     q.remove(&n1); | ||||
|     BOOST_TEST(n1.valid() == false); | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_simple) | ||||
| { | ||||
|     using Queue = PriorityQueue<int, char>; | ||||
|     Queue q; | ||||
|     Queue::Node nodes[10]; | ||||
| 
 | ||||
|     q.insert(&nodes[0], 9, 'a'); | ||||
|     BOOST_TEST(q.min_prio() == 9); | ||||
|     BOOST_TEST(q.min_elem() == 'a'); | ||||
| 
 | ||||
|     q.insert(&nodes[1], 4, 'b'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[2], 7, 'c'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[3], 5, 'd'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[4], 8, 'e'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[5], 6, 'f'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[6], 4, 'g'); | ||||
|     q.insert(&nodes[7], 5, 'h'); | ||||
|     q.insert(&nodes[8], 2, 'i'); | ||||
|     BOOST_TEST(q.min_prio() == 2); | ||||
|     BOOST_TEST(q.min_elem() == 'i'); | ||||
| 
 | ||||
|     q.insert(&nodes[9], 6, 'j'); | ||||
|     BOOST_TEST(q.min_prio() == 2); | ||||
|     BOOST_TEST(q.min_elem() == 'i'); | ||||
| 
 | ||||
|     q.set_prio(&nodes[2], 1); | ||||
|     BOOST_TEST(q.min_prio() == 1); | ||||
|     BOOST_TEST(q.min_elem() == 'c'); | ||||
| 
 | ||||
|     q.set_prio(&nodes[4], 3); | ||||
|     BOOST_TEST(q.min_prio() == 1); | ||||
|     BOOST_TEST(q.min_elem() == 'c'); | ||||
| 
 | ||||
|     q.remove(&nodes[2]); | ||||
|     BOOST_TEST(q.min_prio() == 2); | ||||
|     BOOST_TEST(q.min_elem() == 'i'); | ||||
| 
 | ||||
|     q.remove(&nodes[8]); | ||||
|     BOOST_TEST(q.min_prio() == 3); | ||||
|     BOOST_TEST(q.min_elem() == 'e'); | ||||
| 
 | ||||
|     q.remove(&nodes[4]); | ||||
|     q.remove(&nodes[1]); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'g'); | ||||
| 
 | ||||
|     q.remove(&nodes[3]); | ||||
|     q.remove(&nodes[9]); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'g'); | ||||
| 
 | ||||
|     q.remove(&nodes[6]); | ||||
|     BOOST_TEST(q.min_prio() == 5); | ||||
|     BOOST_TEST(q.min_elem() == 'h'); | ||||
| 
 | ||||
|     BOOST_TEST(q.empty() == false); | ||||
|     q.clear(); | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_increase_prio) | ||||
| { | ||||
|     using Queue = PriorityQueue<int, char>; | ||||
| 
 | ||||
|     Queue q; | ||||
|     Queue::Node n1; | ||||
| 
 | ||||
|     q.insert(&n1, 5, 'a'); | ||||
|     q.set_prio(&n1, 8); | ||||
|     BOOST_TEST(n1.prio() == 8); | ||||
|     BOOST_TEST(q.min_prio() == 8); | ||||
| 
 | ||||
|     q.clear(); | ||||
| 
 | ||||
|     Queue::Node n2, n3, n4; | ||||
| 
 | ||||
|     q.insert(&n1, 9, 'A'); | ||||
|     q.insert(&n2, 4, 'b'); | ||||
|     q.insert(&n3, 7, 'c'); | ||||
|     q.insert(&n4, 5, 'd'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.set_prio(&n2, 8); | ||||
|     BOOST_TEST(n2.prio() == 8); | ||||
|     BOOST_TEST(q.min_elem() == 'd'); | ||||
|     BOOST_TEST(q.min_prio() == 5); | ||||
| 
 | ||||
|     q.set_prio(&n3, 10); | ||||
|     BOOST_TEST(n3.prio() == 10); | ||||
|     BOOST_TEST(q.min_elem() == 'd'); | ||||
| 
 | ||||
|     q.remove(&n4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.remove(&n2); | ||||
|     BOOST_TEST(q.min_prio() == 9); | ||||
|     BOOST_TEST(q.min_elem() == 'A'); | ||||
| 
 | ||||
|     q.remove(&n1); | ||||
|     BOOST_TEST(q.min_elem() == 'c'); | ||||
|     BOOST_TEST(q.min_prio() == 10); | ||||
| 
 | ||||
|     q.remove(&n3); | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_random) | ||||
| { | ||||
|     using Queue = PriorityQueue<int, int>; | ||||
|     Queue q; | ||||
| 
 | ||||
|     const int num_elem = 1000; | ||||
|     std::vector<std::tuple<std::unique_ptr<Queue::Node>, int, int>> elems; | ||||
|     int next_data = 0; | ||||
| 
 | ||||
|     std::mt19937 rng(34567); | ||||
| 
 | ||||
|     auto check = [&q,&elems]() { | ||||
|         int min_prio = q.min_prio(); | ||||
|         int min_data = q.min_elem(); | ||||
|         int best_prio = INT_MAX; | ||||
|         bool found = false; | ||||
|         for (const auto& v : elems) { | ||||
|             int this_prio = std::get<1>(v); | ||||
|             int this_data = std::get<2>(v); | ||||
|             best_prio = std::min(best_prio, this_prio); | ||||
|             if ((this_prio == min_prio) && (this_data == min_data)) { | ||||
|                 found = true; | ||||
|             } | ||||
|         } | ||||
|         BOOST_TEST(found == true); | ||||
|         BOOST_TEST(min_prio == best_prio); | ||||
|     }; | ||||
| 
 | ||||
|     for (int i = 0; i < num_elem; ++i) { | ||||
|         ++next_data; | ||||
|         int prio = std::uniform_int_distribution<>(0, 1000000)(rng); | ||||
|         std::unique_ptr<Queue::Node> nptr(new Queue::Node); | ||||
|         q.insert(nptr.get(), prio, next_data); | ||||
|         elems.push_back(std::make_tuple(std::move(nptr), prio, next_data)); | ||||
|         check(); | ||||
|     } | ||||
| 
 | ||||
|     for (int i = 0; i < 10000; ++i) { | ||||
|         int p = std::uniform_int_distribution<>(0, num_elem - 1)(rng); | ||||
|         Queue::Node* node = std::get<0>(elems[p]).get(); | ||||
|         int prio = std::get<1>(elems[p]); | ||||
|         prio = std::uniform_int_distribution<>(0, 1000000)(rng); | ||||
|         q.set_prio(node, prio); | ||||
|         std::get<1>(elems[p]) = prio; | ||||
|         check(); | ||||
| 
 | ||||
|         p = std::uniform_int_distribution<>(0, num_elem - 1)(rng); | ||||
|         node = std::get<0>(elems[p]).get(); | ||||
|         q.remove(node); | ||||
|         elems.erase(elems.begin() + p); | ||||
|         check(); | ||||
| 
 | ||||
|         ++next_data; | ||||
|         prio = std::uniform_int_distribution<>(0, 1000000)(rng); | ||||
|         std::unique_ptr<Queue::Node> nptr(new Queue::Node); | ||||
|         q.insert(nptr.get(), prio, next_data); | ||||
|         elems.push_back(std::make_tuple(std::move(nptr), prio, next_data)); | ||||
|         check(); | ||||
|     } | ||||
| 
 | ||||
|     for (int i = 0; i < num_elem; ++i) { | ||||
|         int p = std::uniform_int_distribution<>(0, num_elem - 1 - i)(rng); | ||||
|         Queue::Node* node = std::get<0>(elems[p]).get(); | ||||
|         q.remove(node); | ||||
|         elems.erase(elems.begin() + p); | ||||
|         if (! elems.empty()) { | ||||
|             check(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
|  | @ -0,0 +1,252 @@ | |||
| /*
 | ||||
|  * Unit tests for PriorityQueue data structure. | ||||
|  * | ||||
|  * Depends on the Boost.Test unit test framework. | ||||
|  * Tested with Boost v1.74, available from https://www.boost.org/
 | ||||
|  */ | ||||
| 
 | ||||
| #include <algorithm> | ||||
| #include <climits> | ||||
| #include <memory> | ||||
| #include <random> | ||||
| #include <string> | ||||
| #include <tuple> | ||||
| #include <vector> | ||||
| 
 | ||||
| #define BOOST_TEST_MODULE datastruct | ||||
| #include <boost/test/unit_test.hpp> | ||||
| 
 | ||||
| #include "priority_queue.hpp" | ||||
| 
 | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE(test_priority_queue) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_empty) | ||||
| { | ||||
|     using Queue = mwmatching::PriorityQueue<int, std::string>; | ||||
|     Queue q; | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_single) | ||||
| { | ||||
|     using Queue = mwmatching::PriorityQueue<int, std::string>; | ||||
|     Queue q; | ||||
| 
 | ||||
|     Queue::Node n1; | ||||
|     BOOST_TEST(n1.valid() == false); | ||||
| 
 | ||||
|     q.insert(&n1, 5, "a"); | ||||
| 
 | ||||
|     BOOST_TEST(n1.valid() == true); | ||||
|     BOOST_TEST(n1.prio() == 5); | ||||
|     BOOST_TEST(q.empty() == false); | ||||
|     BOOST_TEST(q.min_prio() == 5); | ||||
|     BOOST_TEST(q.min_elem() == std::string("a")); | ||||
| 
 | ||||
|     q.set_prio(&n1, 3); | ||||
|     BOOST_TEST(n1.prio() == 3); | ||||
|     BOOST_TEST(q.min_prio() == 3); | ||||
|     BOOST_TEST(q.min_elem() == std::string("a")); | ||||
| 
 | ||||
|     q.remove(&n1); | ||||
|     BOOST_TEST(n1.valid() == false); | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_simple) | ||||
| { | ||||
|     using Queue = mwmatching::PriorityQueue<int, char>; | ||||
|     Queue q; | ||||
|     Queue::Node nodes[10]; | ||||
| 
 | ||||
|     q.insert(&nodes[0], 9, 'a'); | ||||
|     BOOST_TEST(q.min_prio() == 9); | ||||
|     BOOST_TEST(q.min_elem() == 'a'); | ||||
| 
 | ||||
|     q.insert(&nodes[1], 4, 'b'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[2], 7, 'c'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[3], 5, 'd'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[4], 8, 'e'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[5], 6, 'f'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.insert(&nodes[6], 4, 'g'); | ||||
|     q.insert(&nodes[7], 5, 'h'); | ||||
|     q.insert(&nodes[8], 2, 'i'); | ||||
|     BOOST_TEST(q.min_prio() == 2); | ||||
|     BOOST_TEST(q.min_elem() == 'i'); | ||||
| 
 | ||||
|     q.insert(&nodes[9], 6, 'j'); | ||||
|     BOOST_TEST(q.min_prio() == 2); | ||||
|     BOOST_TEST(q.min_elem() == 'i'); | ||||
| 
 | ||||
|     q.set_prio(&nodes[2], 1); | ||||
|     BOOST_TEST(q.min_prio() == 1); | ||||
|     BOOST_TEST(q.min_elem() == 'c'); | ||||
| 
 | ||||
|     q.set_prio(&nodes[4], 3); | ||||
|     BOOST_TEST(q.min_prio() == 1); | ||||
|     BOOST_TEST(q.min_elem() == 'c'); | ||||
| 
 | ||||
|     q.remove(&nodes[2]); | ||||
|     BOOST_TEST(q.min_prio() == 2); | ||||
|     BOOST_TEST(q.min_elem() == 'i'); | ||||
| 
 | ||||
|     q.remove(&nodes[8]); | ||||
|     BOOST_TEST(q.min_prio() == 3); | ||||
|     BOOST_TEST(q.min_elem() == 'e'); | ||||
| 
 | ||||
|     q.remove(&nodes[4]); | ||||
|     q.remove(&nodes[1]); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'g'); | ||||
| 
 | ||||
|     q.remove(&nodes[3]); | ||||
|     q.remove(&nodes[9]); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'g'); | ||||
| 
 | ||||
|     q.remove(&nodes[6]); | ||||
|     BOOST_TEST(q.min_prio() == 5); | ||||
|     BOOST_TEST(q.min_elem() == 'h'); | ||||
| 
 | ||||
|     BOOST_TEST(q.empty() == false); | ||||
|     q.clear(); | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_increase_prio) | ||||
| { | ||||
|     using Queue = mwmatching::PriorityQueue<int, char>; | ||||
| 
 | ||||
|     Queue q; | ||||
|     Queue::Node n1; | ||||
| 
 | ||||
|     q.insert(&n1, 5, 'a'); | ||||
|     q.set_prio(&n1, 8); | ||||
|     BOOST_TEST(n1.prio() == 8); | ||||
|     BOOST_TEST(q.min_prio() == 8); | ||||
| 
 | ||||
|     q.clear(); | ||||
| 
 | ||||
|     Queue::Node n2, n3, n4; | ||||
| 
 | ||||
|     q.insert(&n1, 9, 'A'); | ||||
|     q.insert(&n2, 4, 'b'); | ||||
|     q.insert(&n3, 7, 'c'); | ||||
|     q.insert(&n4, 5, 'd'); | ||||
|     BOOST_TEST(q.min_prio() == 4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.set_prio(&n2, 8); | ||||
|     BOOST_TEST(n2.prio() == 8); | ||||
|     BOOST_TEST(q.min_elem() == 'd'); | ||||
|     BOOST_TEST(q.min_prio() == 5); | ||||
| 
 | ||||
|     q.set_prio(&n3, 10); | ||||
|     BOOST_TEST(n3.prio() == 10); | ||||
|     BOOST_TEST(q.min_elem() == 'd'); | ||||
| 
 | ||||
|     q.remove(&n4); | ||||
|     BOOST_TEST(q.min_elem() == 'b'); | ||||
| 
 | ||||
|     q.remove(&n2); | ||||
|     BOOST_TEST(q.min_prio() == 9); | ||||
|     BOOST_TEST(q.min_elem() == 'A'); | ||||
| 
 | ||||
|     q.remove(&n1); | ||||
|     BOOST_TEST(q.min_elem() == 'c'); | ||||
|     BOOST_TEST(q.min_prio() == 10); | ||||
| 
 | ||||
|     q.remove(&n3); | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(test_random) | ||||
| { | ||||
|     using Queue = mwmatching::PriorityQueue<int, int>; | ||||
|     Queue q; | ||||
| 
 | ||||
|     const int num_elem = 1000; | ||||
|     std::vector<std::tuple<std::unique_ptr<Queue::Node>, int, int>> elems; | ||||
|     int next_data = 0; | ||||
| 
 | ||||
|     std::mt19937 rng(34567); | ||||
| 
 | ||||
|     auto check = [&q,&elems]() { | ||||
|         int min_prio = q.min_prio(); | ||||
|         int min_data = q.min_elem(); | ||||
|         int best_prio = INT_MAX; | ||||
|         bool found = false; | ||||
|         for (const auto& v : elems) { | ||||
|             int this_prio = std::get<1>(v); | ||||
|             int this_data = std::get<2>(v); | ||||
|             best_prio = std::min(best_prio, this_prio); | ||||
|             if ((this_prio == min_prio) && (this_data == min_data)) { | ||||
|                 found = true; | ||||
|             } | ||||
|         } | ||||
|         BOOST_TEST(found == true); | ||||
|         BOOST_TEST(min_prio == best_prio); | ||||
|     }; | ||||
| 
 | ||||
|     for (int i = 0; i < num_elem; ++i) { | ||||
|         ++next_data; | ||||
|         int prio = std::uniform_int_distribution<>(0, 1000000)(rng); | ||||
|         std::unique_ptr<Queue::Node> nptr(new Queue::Node); | ||||
|         q.insert(nptr.get(), prio, next_data); | ||||
|         elems.push_back(std::make_tuple(std::move(nptr), prio, next_data)); | ||||
|         check(); | ||||
|     } | ||||
| 
 | ||||
|     for (int i = 0; i < 10000; ++i) { | ||||
|         int p = std::uniform_int_distribution<>(0, num_elem - 1)(rng); | ||||
|         Queue::Node* node = std::get<0>(elems[p]).get(); | ||||
|         int prio = std::get<1>(elems[p]); | ||||
|         prio = std::uniform_int_distribution<>(0, 1000000)(rng); | ||||
|         q.set_prio(node, prio); | ||||
|         std::get<1>(elems[p]) = prio; | ||||
|         check(); | ||||
| 
 | ||||
|         p = std::uniform_int_distribution<>(0, num_elem - 1)(rng); | ||||
|         node = std::get<0>(elems[p]).get(); | ||||
|         q.remove(node); | ||||
|         elems.erase(elems.begin() + p); | ||||
|         check(); | ||||
| 
 | ||||
|         ++next_data; | ||||
|         prio = std::uniform_int_distribution<>(0, 1000000)(rng); | ||||
|         std::unique_ptr<Queue::Node> nptr(new Queue::Node); | ||||
|         q.insert(nptr.get(), prio, next_data); | ||||
|         elems.push_back(std::make_tuple(std::move(nptr), prio, next_data)); | ||||
|         check(); | ||||
|     } | ||||
| 
 | ||||
|     for (int i = 0; i < num_elem; ++i) { | ||||
|         int p = std::uniform_int_distribution<>(0, num_elem - 1 - i)(rng); | ||||
|         Queue::Node* node = std::get<0>(elems[p]).get(); | ||||
|         q.remove(node); | ||||
|         elems.erase(elems.begin() + p); | ||||
|         if (! elems.empty()) { | ||||
|             check(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     BOOST_TEST(q.empty() == true); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_SUITE_END() | ||||
|  | @ -9,8 +9,10 @@ echo | |||
| g++ --version | ||||
| echo | ||||
| 
 | ||||
| make -C cpp run_matching test_mwmatching | ||||
| make -C cpp run_matching test_mwmatching test_concatenable_queue test_priority_queue | ||||
| cpp/test_mwmatching | ||||
| cpp/test_concatenable_queue | ||||
| cpp/test_priority_queue | ||||
| 
 | ||||
| echo | ||||
| echo ">> Running test graphs" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue