diff --git a/Examples/src/DataHeap/Makefile b/Examples/src/DataHeap/Makefile deleted file mode 100644 index b7441e20f..000000000 --- a/Examples/src/DataHeap/Makefile +++ /dev/null @@ -1,71 +0,0 @@ -############################################################ -# -# An example of Makefile for the course on -# Advanced Programming for Scientific Computing -# It should be modified for adapting it to the various examples -# -############################################################ -# -# The environmental variable PACS_ROOT should be set to the -# root directory where the examples reside. In practice, the directory -# where this file is found. The resolution of PACS_ROOT is made in the -# Makefile.h file, where other important variables are also set. -# The only user defined variable that must be set in this file is -# the one indicating where Makefile.h resides - -MAKEFILEH_DIR=../../ -# -include $(MAKEFILEH_DIR)/Makefile.inc -# -# You may have an include file also in the current directory -# --include Makefile.inc - -# -# The general setting is as follows: -# mains are identified bt main_XX.cpp -# all other files are XX.cpp -# - -# get all files *.cpp -SRCS=$(wildcard *.cpp) -# get the corresponding object file -OBJS = $(SRCS:.cpp=.o) -# get all headers in the working directory -HEADERS=$(wildcard *.hpp) -# -exe_sources=$(filter main%.cpp,$(SRCS)) -EXEC=$(exe_sources:.cpp=) - -#========================== ORA LA DEFINIZIONE DEGLI OBIETTIVI -.phony= all clean distclean doc - -.DEFAULT_GOAL = all - -all: $(DEPEND) $(EXEC) - -clean: - -\rm -f $(EXEC) $(OBJS) - -distclean: - $(MAKE) clean - -\rm -r -f ./doc - -\rm *.out *.bak *~ - -doc: - doxygen $(DOXYFILE) - -$(EXEC): $(OBJS) - -$(OBJS): $(SRCS) - -$(DEPEND): $(SRCS) - g++ $(CPPFLAGS) -MM $(SRCS) -MF $(DEPEND) - - - --include $(DEPEND) - - - - diff --git a/Examples/src/DataHeap/README.md b/Examples/src/DataHeap/README.md deleted file mode 100644 index af38c631f..000000000 --- a/Examples/src/DataHeap/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# A heap # - -A heap is a data structure that allows you to store a set of elements and keep track of the smallest element in the set (according to a given ordering relation). It is useful for implementing priority queues. - -The standard library provides a `std::heap` that implements a heap class and a `make_heap` function that takes a vector and turns it into a heap. It also provides `push_heap` and `pop_heap` methods that allow you to add and remove elements from the heap. It also provide `std::priority_queue`, a container adapter +for a priority queue. - -However those implementations operate on the data vector directly. In this implementation the heap structure is placed instead on top an existing data vector, whose elements are not moved by the heap operations. In other words, this heap is implemented through an indirection table. It may be useful when you whant to have an heap view of some data in a vector but at the same time you want to keep the position of the elements in the vector unchanged. - -In this implementation the data vector is stored as private member and made avaliable, as a contant reference, through the method `data()`. It is constant since the user should not be allowed to change the vector. - - -## Main heapView operations ## -The heap operations are: -- top(): returns the smallest element in the heap -- pop(): removes the smallest element from the heap, returning a pair contianing the value. Note that the data vector is unchenged! -- add(value): adds an element to the heap. The index of the added element is returned. The data vector increases its size by one: the added element is added to the back of the data vector. -- update(index,value): updates the value of the element in the data vector at the given index. The index is returned. -- remove(index): removes the element at the given index from the heap. The index is returned. The data vector is unchanged! -- operator[](index): returns the value of the element at the given index in the data vector (not is the heap). - -** A note ** I have chosen to compose the heap with the vector. I could have chosen aggregation instead, with the internal vector being a reference to an external vector. The advantage of composition is that the heap can be used as a stand alone object. The advantage of aggregation is that the heap can be used to view a subset of an external vector. I have chosen composition because I think that the heap should be a stand alone object, for safety. Having the vector as an external resource could induce the user to change the vector in a way that is not compatible with the heap structure. For example, the user could remove an element from the vector without updating the heap. This would break the heap structure. - -# What do I learn here? # -- How to implement a heap data structure -- How to use a heap -- A use of std::optional -- Use of standard exceptions -- An important algorithm - -# A final note: heap and ordered sets # -You can keep track of the smallest elements in a set by using an ordered set. However, the heap is more efficient for this purpose. The ordered set keeps all elements ordered by exploiting a binary data structure. In a heap we use a linear structure and we keep track only of the smallest element. The heap is more efficient when you need to keep track of the smallest element only. The ordered set is more efficient when you need to keep all elements in order. - diff --git a/Examples/src/DataHeap/heapView.hpp b/Examples/src/DataHeap/heapView.hpp deleted file mode 100644 index 73923b83c..000000000 --- a/Examples/src/DataHeap/heapView.hpp +++ /dev/null @@ -1,436 +0,0 @@ -// -// Created by forma on 18/06/23. -// - -#ifndef EXAMPLES_HEAPVIEW_HPP -#define EXAMPLES_HEAPVIEW_HPP -#include "heapViewTraits.hpp" -#include -#include -#include -#include -#include -#include -#include - - -/*! - * @brief A heap view is a data structure that allows you to have - * values stored in a and operate on them as a heap without moving them around in memory. - * - * The heap view is a wrapper around a vector of data elements. The heap view - * maintains a heap of indices into the vector. The heap view also maintains a - * vector of indices into the heap. The heap view is a view of the data - * elements, so the data elements are not moved around in memory. The heap - * view is a heap of indices, so the indices are moved around in memory - * not the data. The heap view maintains a mapping from data - * indices to indices into the heap. - * - * @note At the moment is is not implemented as a view since it has a copy of - * the data vector and not a reference. A view would be better. - * @tparam ElementType The type stored in the data vector. It should be - * comparable with the comparison operator. - * @tparam CompOp Comparison operator for the data elements. It should be proper comparison operator on DataElementType. - * @tparam Traits The traits for the heap view. It should provide the definition of the internal types. - */ -namespace apsc -{ -template , - class Traits=heapViewTraits > -class HeapView -{ -public: - using Index = Traits::Index; - using DataVector = Traits::DataVector; - using DataIndex = Traits::DataIndex; - using ElementType = Traits::ElementType; - using HeapIndex = Traits::HeapIndex; - using HeapIter = Traits::HeapIter; - - HeapView() = default; - /*! - * @brief Construct a heap view from a vector of data elements. - * @param data The vector of data elements. - * @param comp The comparison operator for the data elements. Defaults to the - * default constructed one. - */ - template - explicit HeapView(T &&data, CompOp comp = CompOp{}) - : data_(std::forward(data)), comp_(comp) - { - if(data_.size() == 0) - { - throw std::invalid_argument( - "HeapView: data vector must have at least one element"); - } - heapIndex_.reserve(data_.size()); - heapIter_.reserve(data_.size()); - for(Index i = 0; i < data_.size(); ++i) - { - heapIndex_.push_back(i); - heapIter_.push_back(i); - } - for(Index i = data_.size() / 2; i > 0; --i) - { - siftDown(i); - } - siftDown(0); - } - HeapView(const HeapView &other) = default; - HeapView(HeapView &&other) noexcept = default; - HeapView &operator=(const HeapView &other) = default; - HeapView &operator=(HeapView &&other) noexcept = default; - /*! - * @brief Construct a heap view from a vector of data elements. - * @param data The data - */ - template - void - setData(T &&data) - { - data_ = std::forward(data); - heapIndex_.clear(); - heapIter_.clear(); - heapIndex_.reserve(data_.size()); - heapIter_.reserve(data_.size()); - for(Index i = 0; i < data_.size(); ++i) - { - heapIndex_.emplace_back(i); - heapIter_.emplace_back(i); - } - if(data_.size()!=0) - { -// to avoid problems with subtraction of unsigned I treat index 0 specially - for(Index i = data_.size() / 2; i > 0; --i) - { - siftDown(i); - } - siftDown(0); - } - } - /*! - * @brief Reserves capacity. - */ - void - reserve(std::size_t n) - { - data_.resize(n); - heapIndex_.reserve(n); - heapIter_.resize(n); - } - /* @brief Returns the underlying data vector. - * @return The underlying data vector. - * @note The data vector is given as a const reference: you cannot - * change from the outside the content of the internal data vector. - */ - auto const & - data() const - { - return data_; - } - /*! - * Adds a new element to the heap view. - * @param e The element to add - * @return The index in the heap where the element was added - */ - template - Index - add(E &&e) - { - Index i = this->size(); - data_.emplace_back(std::forward(e)); - heapIndex_.emplace_back(data_.size() - 1u); - heapIter_.emplace_back(i); - return siftUp(i); - } - /*! - * @brief Remove an element from the heap view. - * @param i The index of the element to remove. - * @return The index in the heap where the element was removed. - * @note The element is not removed from the data vector. - */ - Index - remove(DataIndex i) - { - auto where = heapIter_[i]; - if(not where.has_value()) - { - throw std::invalid_argument("HeapView: trying to remove an element not in the heap"); - } - this->swap(*where, heapIndex_.size() - 1); - heapIndex_.pop_back(); - heapIter_[i].reset(); - return siftDown(siftUp(*where)); - } - /*! - * @brief Update an element in the heap view. - * - * This function updates an element in the heap view. It does not change the - * position of the element in the data. If the element is changed so that it - * is no longer in the correct position in the heap, then the heap will be - * rearranged - * @note the value of the data element is changed - * @param i The index in the data where we have to change the element - * @param e The new value - * @return The position in the hoep of the new value - */ - Index - update(DataIndex i, const ElementType &e) - { - data_[i] = e; - auto where = heapIter_[i]; - if (not where.has_value()) - { - // add again the value to the heap - where=heapIndex_.size(); - heapIndex_.push_back(i); - heapIter_[i]=where; - return siftUp(*where); - } - return siftDown(siftUp(*where)); - } - /*! - * @brief The size of the heap - * @return The size - */ - Index - size() const - { - return heapIndex_.size(); - } - /*! - * The i-th element in the data - * @param i The data index - * @return the value - */ - const ElementType & - operator[](DataIndex i) const - { - return data_[i]; - } - /*! The top element in the heap - * @note This is the element at the top of the heap, not the element at the - * top of the data. - * @return the element value - */ - const ElementType & - top() const - { - return data_[heapIndex_[0]]; - } - /*! - * @brief The top element in the heap and its index in the data - * @return The pair index, value - */ - std::pair - topPair() const - { - return std::make_pair(heapIndex_[0], data_[heapIndex_[0]]); - } - /*! - * Checks if the heap is empty - * @return a boolean - */ - [[nodiscard]] - bool empty() const - { - return heapIndex_.empty(); - } - /*! - * @brief Clear the heap - */ - void - clear() - { - data_.resize(0); - heapIndex_.clear(); - heapIter_.clear(); - } - /*! - * @brief Pops the top element from the heap - * @return The value of the top element - * @details The top element is removed from the heap but NOT from the data - */ - DataElementType - pop() - { - return this->popPair().second; - } - - /*! - * @brief pops the top element from the heap - * @return the index and value of the top element - * @details The top element is removed from the heap but NOT from the data - */ - std::pair - popPair() - { - auto const [where, e] = this->topPair(); - remove(where); // remove data element from the heap - return std::make_pair(where, e); - } - /*! - * @brief The data value at index i in the heap - * @param i The index - * @return The ith data value in the heap - */ - auto - heapValue(DataIndex i) const - { - return data_[heapIndex_[i]]; - } - /* @brief The index of the data value in the heap - * @param i The index in the data - * @return The index in the heap - */ - auto - heapIndex(DataIndex i) const - { - return heapIndex_[i]; - } - /*! - * @brief Check iif the heap is ssane - * @return true is heap is sane - */ - bool - check() const - { - for(Index i = 0; i < heapIndex_.size(); ++i) - { - auto const [left, right] = children(i); - if(left) - { - if(comp_(data_[heapIndex_[*left]], data_[heapIndex_[i]])) - { - return false; - } - } - if(right) - { - if(comp_(data_[heapIndex_[*right]], data_[heapIndex_[i]])) - { - return false; - } - } - } - return true; - } -/* -Comparing two elements using the given ordering relation -*/ - bool - compare(DataIndex i, DataIndex j) const - { - return compHeapView_(i,j); - } - -private: - /*! - * @brief The parent of a node in the heap - * @param i the index - * @return the index of the parent - */ - Index - parent(Index i) const noexcept - { - return (i == 0u) ? 0u : (i - 1u) / 2u; - }; - /*! - * The indexex of the chirldens of a node in the heap - * @param i The index - * @return A pair of optionals. The first is the left child, the second is - * the right child. If the child does not exist, the optional is empty. - */ - std::pair, std::optional> - children(Index i) const noexcept - { - if(2 * i + 1u < heapIndex_.size()) - { - if(2 * i + 2u < heapIndex_.size()) - { - return std::make_pair(std::optional(2 * i + 1u), - std::optional(2 * i + 2u)); - } - else - { - return std::make_pair(std::optional(2 * i + 1u), - std::optional()); - } - } - else - { - return std::make_pair(std::optional(), std::optional()); - } - } - /*! - * Swap two elements in the heap - * - * Data is untouched. Only th eheap index are swappend and the heap iterators - * are updated - * @param i The first element - * @param j The second element - */ - void - swap(Index i, Index j) - { - std::swap(heapIndex_[i], heapIndex_[j]); - heapIter_[heapIndex_[i]] = i; - heapIter_[heapIndex_[j]] = j; - } - //! Moves an element up the heap until it is in the correct position - Index - siftUp(Index i) - { - while(i > 0 && compHeapView_(heapIndex_[i], heapIndex_[parent(i)])) - { - this->swap(i, parent(i)); - i = parent(i); - } - return i; - } - //! Moves an element down the heap until it is in the correct position - Index - siftDown(Index i) - { - auto [left, right] = children(i); - while(left) - { - Index j = *left; - if(right && compHeapView_(heapIndex_[*right], heapIndex_[*left])) - { - j = *right; - } - if(compHeapView_(heapIndex_[j], heapIndex_[i])) - { - this->swap(i, j); - i = j; - std::tie(left, right) = children(i); - } - else - { - break; - } - } - return i; - } - - //! The data - DataVector data_; - //! The heap index - HeapIndex heapIndex_; - //! The heap iterators. In fact, it is a reverse map from data index to heap - //! index - HeapIter heapIter_; - //! The comparison operator for the heap - bool - compHeapView_(DataIndex i, DataIndex j) const - { - return comp_(data_[i], data_[j]); - }; - //! The comparison operator for the data (user defined or defaulted to less) - CompOp comp_ = CompOp{}; - //static auto constexpr noData=std::numeric_limits::max(); -}; -} // namespace apsc - -#endif // EXAMPLES_HEAPVIEW_HPP diff --git a/Examples/src/DataHeap/heapViewTraits.hpp b/Examples/src/DataHeap/heapViewTraits.hpp deleted file mode 100644 index 673de6812..000000000 --- a/Examples/src/DataHeap/heapViewTraits.hpp +++ /dev/null @@ -1,45 +0,0 @@ -// -// Created by forma on 20/06/23. -// - -#ifndef EXAMPLES_HEAPVIEWTRAITS_HPP -#define EXAMPLES_HEAPVIEWTRAITS_HPP -#include -#include - - -namespace apsc -{ - -/*! -@brief Traits for the heapView class -@tparam DataElementType The type of the elements stored in the heap -*/ -template -struct heapViewTraits -{ - //! The type of the index - using Index = typename std::vector::size_type; - //! The type of the vector storing the data - using DataVector = std::vector; - //! The type of the indixes of the heap (it is the same as the type of the indexes of the data vector) - using DataIndex = Index; - /*! The type of the elements stored in the heap. - * It is the same as the type of the elements stored in the data vector - * @note We need a comparison operator on this type - */ - using ElementType = DataElementType; - /*! The internal structure keeping the indexes of the heap - * - * HeapIndex(i) returns the index of the i-th element in the heap - */ - using HeapIndex = std::vector; - /*! An internal structure storing the indexes of the data vector - * HeapIter(i) returns the index of the i-th heap element in the data vector - * We have HeapIndex(HeapIter(i))=i if i is a valid index of the heap - */ - using HeapIter = std::vector>; -}; - -} // namespace apsc -#endif // EXAMPLES_HEAPVIEWTRAITS_HPP diff --git a/Examples/src/DataHeap/main.cpp b/Examples/src/DataHeap/main.cpp deleted file mode 100644 index 4eb682ca8..000000000 --- a/Examples/src/DataHeap/main.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include "heapView.hpp" -int main() { - std::vector data = {9, 5, 7, 3, 2, 6}; - apsc::HeapView heapView(data); - - std::cout << "The top element is: " << heapView.top() << std::endl; - // addinga na element - heapView.add(-3); - std::cout<<" after adding a new value (-3) "; - std::cout << "The top element is: " << heapView.top() << std::endl; - heapView.pop(); - std::cout<<" after popPing the top element "; - std::cout << "The top element is: " << heapView.top() << std::endl; - heapView.update(1, -10); - std::cout<<" after changing a value (-10) "; - std::cout << "The top element is: " << heapView.top() << std::endl; - - auto const & data2 = heapView.data(); - std::cout << "The origine data is: \n"; - for (auto const & d : data2) - std::cout << d << " "; - std::cout << std::endl; - std::cout << "The heap is: \n"; - while (heapView.empty() == false) { - std::cout << heapView.popPair().second << " "; - } - std::cout << std::endl; - return 0; -} diff --git a/Examples/src/HeapView/HeapViewTraits.hpp b/Examples/src/HeapView/HeapViewTraits.hpp deleted file mode 100644 index 21d44d44f..000000000 --- a/Examples/src/HeapView/HeapViewTraits.hpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Created by forma on 20/06/23. -// - -#ifndef EXAMPLES_HEAPVIEWTRAITS_HPP -#define EXAMPLES_HEAPVIEWTRAITS_HPP -#include -#include -namespace apsc -{ -template struct heapViewTraits -{ - using Index = std::size_t; - using DataType = std::vector; - using DataIndex = std::size_t; - using ElementType = DataElementType; - using HeapIndex = std::vector; - using HeapIter = std::vector>; -}; -} // namespace apsc -#endif // EXAMPLES_HEAPVIEWTRAITS_HPP diff --git a/Examples/src/HeapView/heapView.hpp b/Examples/src/HeapView/heapView.hpp index 491a4fbb0..73923b83c 100644 --- a/Examples/src/HeapView/heapView.hpp +++ b/Examples/src/HeapView/heapView.hpp @@ -4,7 +4,7 @@ #ifndef EXAMPLES_HEAPVIEW_HPP #define EXAMPLES_HEAPVIEW_HPP -#include "HeapViewTraits.hpp" +#include "heapViewTraits.hpp" #include #include #include @@ -12,20 +12,11 @@ #include #include #include -/* -template -concept heapViewCompOp = requires(T comp) -{ - using Index = typename heapViewTraits::Index; - { comp.operator()(Index,Index) } - ->std::convertible_to; -}; -*/ -namespace apsc -{ + + /*! - * @brief A heap view is a data structure that allows you to store a heap of - * values and operate on them without moving them around in memory. + * @brief A heap view is a data structure that allows you to have + * values stored in a and operate on them as a heap without moving them around in memory. * * The heap view is a wrapper around a vector of data elements. The heap view * maintains a heap of indices into the vector. The heap view also maintains a @@ -35,35 +26,27 @@ namespace apsc * not the data. The heap view maintains a mapping from data * indices to indices into the heap. * - * @note At the moment is is not implemented as a view since it is composed with - * the data vector. The reason is that a view is too dangerous, since the user - * may modify the data without updating the heap. - * @tparam DataElementType The type stored in the data vector. It should be + * @note At the moment is is not implemented as a view since it has a copy of + * the data vector and not a reference. A view would be better. + * @tparam ElementType The type stored in the data vector. It should be * comparable with the comparison operator. - * @tparam CompOp Comparison operator for the data elements. It should be - * a total order: every pair of element is comparable and the relation is a - * partial ordering relation + * @tparam CompOp Comparison operator for the data elements. It should be proper comparison operator on DataElementType. + * @tparam Traits The traits for the heap view. It should provide the definition of the internal types. */ -template > +namespace apsc +{ +template , + class Traits=heapViewTraits > class HeapView { public: - //! The type of the index used to address internal vectors - using Index = typename heapViewTraits::Index; - /*! - The type of the sequential random access data stored in the heap. - It should be comparable w.r.t. the given comparison operator - */ - using DataType = typename heapViewTraits::DataType; - //! The type of the sequantial randoma acces container used to address the data vector - using DataIndex = typename heapViewTraits::DataIndex; - //! The type of data - using ElementType = typename heapViewTraits::ElementType; - //! The structure used to keep the indexes in the data vector - using HeapIndex = typename heapViewTraits::HeapIndex; - //! The structure with the map data index -> position in the heap - using HeapIter = typename heapViewTraits::HeapIter; - //! Default constuctor + using Index = Traits::Index; + using DataVector = Traits::DataVector; + using DataIndex = Traits::DataIndex; + using ElementType = Traits::ElementType; + using HeapIndex = Traits::HeapIndex; + using HeapIter = Traits::HeapIter; + HeapView() = default; /*! * @brief Construct a heap view from a vector of data elements. @@ -101,7 +84,7 @@ class HeapView * @brief Construct a heap view from a vector of data elements. * @param data The data */ - template + template void setData(T &&data) { @@ -112,8 +95,8 @@ class HeapView heapIter_.reserve(data_.size()); for(Index i = 0; i < data_.size(); ++i) { - heapIndex_.push_back(i); - heapIter_.push_back(i); + heapIndex_.emplace_back(i); + heapIter_.emplace_back(i); } if(data_.size()!=0) { @@ -125,25 +108,15 @@ class HeapView siftDown(0); } } - /*! - * @brief Set the comparison operator for the data elements. - * @param comp The comparison operator between data elements - * @note Danger: use it only if the heap is currently empty - */ - void - setCompOp(CompOp comp) - { - comp_ = comp; - } /*! * @brief Reserves capacity. */ void reserve(std::size_t n) { - data_.reserve(n); + data_.resize(n); heapIndex_.reserve(n); - heapIter_.reserve(n); + heapIter_.resize(n); } /* @brief Returns the underlying data vector. * @return The underlying data vector. @@ -165,25 +138,28 @@ class HeapView add(E &&e) { Index i = this->size(); - data_.push_back(std::forward(e)); - heapIndex_.push_back(data_.size() - 1u); - heapIter_.push_back(i); + data_.emplace_back(std::forward(e)); + heapIndex_.emplace_back(data_.size() - 1u); + heapIter_.emplace_back(i); return siftUp(i); } /*! * @brief Remove an element from the heap view. * @param i The index of the element to remove. * @return The index in the heap where the element was removed. - * noData if error. + * @note The element is not removed from the data vector. */ Index remove(DataIndex i) - { + { auto where = heapIter_[i]; - if (!where.has_value()) - return noData; // ERROR CONDITION! + if(not where.has_value()) + { + throw std::invalid_argument("HeapView: trying to remove an element not in the heap"); + } this->swap(*where, heapIndex_.size() - 1); heapIndex_.pop_back(); + heapIter_[i].reset(); return siftDown(siftUp(*where)); } /*! @@ -201,9 +177,9 @@ class HeapView Index update(DataIndex i, const ElementType &e) { - auto where = heapIter_[i]; data_[i] = e; - if (!where.has_value()) + auto where = heapIter_[i]; + if (not where.has_value()) { // add again the value to the heap where=heapIndex_.size(); @@ -244,7 +220,7 @@ class HeapView } /*! * @brief The top element in the heap and its index in the data - * @return The pait index, value + * @return The pair index, value */ std::pair topPair() const @@ -266,21 +242,31 @@ class HeapView void clear() { - data_.clear(); + data_.resize(0); heapIndex_.clear(); heapIter_.clear(); } /*! - * pop the top element from the heap + * @brief Pops the top element from the heap + * @return The value of the top element + * @details The top element is removed from the heap but NOT from the data + */ + DataElementType + pop() + { + return this->popPair().second; + } + + /*! + * @brief pops the top element from the heap * @return the index and value of the top element * @details The top element is removed from the heap but NOT from the data */ std::pair - pop() + popPair() { auto const [where, e] = this->topPair(); remove(where); // remove data element from the heap - heapIter_[where]=std::nullopt; return std::make_pair(where, e); } /*! @@ -337,8 +323,6 @@ Comparing two elements using the given ordering relation { return compHeapView_(i,j); } - //! to indicate no data (could have used optional here) - static auto constexpr noData=std::numeric_limits::max(); private: /*! @@ -431,7 +415,7 @@ Comparing two elements using the given ordering relation } //! The data - DataType data_; + DataVector data_; //! The heap index HeapIndex heapIndex_; //! The heap iterators. In fact, it is a reverse map from data index to heap @@ -445,6 +429,7 @@ Comparing two elements using the given ordering relation }; //! The comparison operator for the data (user defined or defaulted to less) CompOp comp_ = CompOp{}; + //static auto constexpr noData=std::numeric_limits::max(); }; } // namespace apsc diff --git a/Examples/src/HeapView/mainHeap.cpp b/Examples/src/HeapView/mainHeap.cpp index ae1df1a0b..fdc62ef90 100644 --- a/Examples/src/HeapView/mainHeap.cpp +++ b/Examples/src/HeapView/mainHeap.cpp @@ -3,6 +3,24 @@ // #include "heapView.hpp" #include +#include +// A small function to print a heap stored in a vector +void printHeap(auto const & heap, std::size_t idx = 0, std::size_t indent = 0) { + if (idx < heap.size()) { + printHeap(heap, 2*idx + 2, indent + 4); + std::cout << std::setw(indent) << ' '; + std::cout << heap[idx] << "\n"; + printHeap(heap, 2*idx + 1, indent + 4); + } +} +void printHeapView(auto const & heapView) { + std::vector heap; + for(auto i = 0u; i < heapView.size(); ++i) + { + heap.push_back(heapView.heapValue(i)); + } + printHeap(heap); +} int main() @@ -18,21 +36,15 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; - auto [index, value] = heapView.pop(); + auto [index, value] = heapView.popPair(); std::cout << "heapView pop = " << index << " " << value << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; @@ -41,10 +53,7 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; @@ -53,10 +62,7 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; @@ -65,10 +71,7 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; @@ -81,21 +84,15 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; - auto [index, value] = heapView.pop(); + auto [index, value] = heapView.popPair(); std::cout << "heapView pop = " << index << " " << value << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; @@ -104,10 +101,7 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; @@ -116,10 +110,7 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; @@ -128,35 +119,29 @@ main() std::cout << "heapView top = " << heapView.top() << std::endl; std::cout << "heapView size = " << heapView.size() << std::endl; std::cout << "current values in the heap = " << std::endl; - for(auto i = 0u; i < heapView.size(); ++i) - { - std::cout << heapView.heapValue(i) << " "; - } + printHeapView(heapView); std::cout << std::endl; std::cout << "Heap is sane? " << std::boolalpha << heapView.check() << std::endl; std::cout<< "Emptying heap\n"; auto currentSize=heapView.size(); std::vector currentHeapElements; - for (auto i=0;i