From af56d927cedf2aa0abd73885ff4ec4c63206d2d7 Mon Sep 17 00:00:00 2001 From: Markus Blatt <mblatt@dune-project.org> Date: Tue, 16 Nov 2004 14:44:59 +0000 Subject: [PATCH] Added a single linked list. Provided a test for it. [[Imported from SVN: r1096]] --- common/sllist.hh | 355 ++++++++++++++++++++++++++++++++++++++ common/test/.gitignore | 3 +- common/test/Makefile.am | 4 +- common/test/sllisttest.cc | 90 ++++++++++ 4 files changed, 450 insertions(+), 2 deletions(-) create mode 100644 common/sllist.hh create mode 100644 common/test/sllisttest.cc diff --git a/common/sllist.hh b/common/sllist.hh new file mode 100644 index 000000000..1ce1d1266 --- /dev/null +++ b/common/sllist.hh @@ -0,0 +1,355 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#ifndef __DUNE__SLLIST_HH__ +#define __DUNE__SLLIST_HH__ + +#include <memory> +#include <dune/common/iteratorfacades.hh> + +namespace Dune +{ + /** + * @file + * This file implements a single linked list together with + * the necessary iterators. + * @author Markus Blatt + */ + /** + * @addtogroup Common + * + * @{ + */ + template<typename T, class A> + class SLListIterator; + + template<typename T, class A> + class SLListConstIterator; + + /** + * @brief A single linked list. + * + * The list is capabale of insertions at the front and at + * the end and of removing elements at the front. Those + * operations require constant time. + */ + template<typename T, class A=std::allocator<T> > + class SLList + { + class Element; + friend class SLListIterator<T,A>; + friend class SLListConstIterator<T,A>; + + public: + + /** + * @brief The type we store. + */ + typedef T MemberType; + + /** + * @brief The allocator to use. + */ + typedef typename A::template rebind<Element>::other Allocator; + + /** + * @brief The mutable iterator of the list. + */ + typedef SLListIterator<T,A> iterator; + + /** + * @brief The mutable iterator of the list. + */ + typedef SLListConstIterator<T,A> const_iterator; + SLList(); + + /** + * @brief Add a new entry to the end of the list. + * @param item The item to add. + */ + inline void push_back(const MemberType& item); + + /** + * @brief Add a new entry to the beginning of the list. + * @param item The item to add. + */ + inline void push_front(const MemberType& item); + + /** + * @brief Remove the first item in the list. + */ + inline void pop_front(); + + /** + * @brief Remove the first item in the list. + * @return The last item in the list or 0 if the list is empty. + /** @brief Remove all elements from the list. */ + inline void clear(); + + /** + * @brief Get an iterator pointing to the first + * element in the list. + * + * @return An iterator pointing to the first + * element or the end if the list is empty. + */ + inline iterator begin(); + + /** + * @brief Get an iterator pointing to the first + * element in the list. + * + * @return An iterator pointing to the first + * element or the end if the list is empty. + */ + inline const_iterator begin() const; + /** + * @brief Get an iterator pointing to the + * end of the list. + * + * @return An iterator pointing to the end. + */ + inline iterator end(); + + /** + * @brief Get an iterator pointing to the + * end of the list. + * + * @return An iterator pointing to the end. + */ + inline const_iterator end() const; + + private: + struct Element + { + /** + * @brief The next element in the list. + */ + Element* next_; + /** + * @brief The element we hold. + */ + MemberType item_; + + Element(const MemberType& item); + + }; + + /** @brief The first element in the list. */ + Element* head_; + + /** @brief The last element in the list. */ + Element* tail_; + + /** @brief The allocator we use. */ + Allocator allocator_; + + + }; + + /** + * @brief A mutable iterator for the SLList. + */ + template<typename T, class A> + class SLListIterator : public Dune::ForwardIteratorFacade<SLListIterator<T,A>, T, T&, std::size_t> + { + friend class SLListConstIterator<T,A>; + + public: + inline SLListIterator(typename SLList<T,A>::Element* item) + : current_(item) + {} + + /** + * @brief Dereferencing function for the iterator facade. + * @return A reference to the element at the current position. + */ + inline T& dereference() const + { + return current_->item_; + } + + /** + * @brief Equality test for the iterator facade. + * @param other The other iterator to check. + * @return true If the other iterator is at the same position. + */ + inline bool equals(const SLListConstIterator<T,A>& other) const + { + return current_==other.current_; + } + + + /** + * @brief Equality test for the iterator facade. + * @param other The other iterator to check. + * @return true If the other iterator is at the same position. + */ + inline bool equals(const SLListIterator<T,A>& other) const + { + return current_==other.current_; + } + + /** + * @brief Increment function for the iterator facade. + */ + inline void increment() + { + current_ = current_->next_; + } + + private: + /** @brief The current element. */ + typename SLList<T,A>::Element* current_; + }; + + /** + * @brief A constant iterator for the SLList. + */ + template<class T, class A> + class SLListConstIterator : public Dune::ForwardIteratorFacade<SLListConstIterator<T,A>, const T, const T&, std::size_t> + { + friend class SLListIterator<T,A>; + + public: + inline SLListConstIterator(typename SLList<T,A>::Element* item) + : current_(item) + {} + + inline SLListConstIterator(const SLListIterator<T,A>& other) + { + current_=other.current_; + } + + /** + * @brief Dereferencing function for the facade. + * @return A reference to the element at the current position. + */ + inline const T& dereference() const + { + return current_->item_; + } + + /** + * @brief Equality test for the iterator facade. + * @param other The other iterator to check. + * @return true If the other iterator is at the same position. + */ + inline bool equals(const SLListConstIterator<T,A>& other) const + { + return current_==other.current_; + } + + + /** + * @brief Equality test for the iterator facade. + * @param other The other iterator to check. + * @return true If the other iterator is at the same position. + */ + inline bool equals(const SLListIterator<T,A>& other) const + { + return current_==other.current_; + } + + /** + * @brief Increment function for the iterator facade. + */ + inline void increment() + { + current_ = current_->next_; + } + + private: + /** @brief The current element. */ + typename SLList<T,A>::Element* current_; + }; + + + template<typename T, class A> + SLList<T,A>::Element::Element(const T& item) + : item_(item) + {} + + template<typename T, class A> + SLList<T,A>::SLList() + : head_(0), tail_(0), allocator_() + {} + + template<typename T, class A> + inline void SLList<T,A>::push_back(const T& item) + { + if(tail_!=0) { + tail_->next_ = allocator_.allocate(1); + tail_ = tail_->next_; + tail_->item_=item; + tail_->next_=0; + }else{ + tail_=head_=allocator_.allocate(1); + tail_->next_=0; + tail_->item_=item; + } + } + + template<typename T, class A> + inline void SLList<T,A>::push_front(const T& item) + { + if(head_==0) { + head_ = tail_ = allocator_.allocate(1); + head_->item_=item; + head_->next_=0; + }else{ + Element* added = allocator_.allocate(1); + added->item_=item; + added->next_=head_; + head_=added; + } + } + + template<typename T, class A> + inline void SLList<T,A>::pop_front() + { + assert(head_!=0); + Element* tmp = head_; + head_=head_->next_; + allocator_.destroy(tmp); + allocator_.deallocate(tmp, 1); + } + + template<typename T, class A> + inline void SLList<T,A>::clear() + { + while(head_) { + Element* current = head_; + head_=current->next_; + allocator_.destroy(current); + allocator_.deallocate(current, 1); + } + tail_ = head_; + } + + template<typename T, class A> + inline SLListIterator<T,A> SLList<T,A>::begin() + { + return iterator(head_); + } + + template<typename T, class A> + inline SLListConstIterator<T,A> SLList<T,A>::begin() const + { + return const_iterator(head_); + } + + + template<typename T, class A> + inline SLListIterator<T,A> SLList<T,A>::end() + { + return iterator(static_cast<Element*>(0)); + } + + template<typename T, class A> + inline SLListConstIterator<T,A> SLList<T,A>::end() const + { + return const_iterator(static_cast<Element*>(0)); + } +} +/** @} */ +#endif diff --git a/common/test/.gitignore b/common/test/.gitignore index d4d9f5d27..d1a2c7540 100644 --- a/common/test/.gitignore +++ b/common/test/.gitignore @@ -7,4 +7,5 @@ parsetest test-stack arraylisttest smartpointertest -iteratorfacadetest \ No newline at end of file +iteratorfacadetest +sllisttest \ No newline at end of file diff --git a/common/test/Makefile.am b/common/test/Makefile.am index 6f84b63d5..e6fcceab8 100644 --- a/common/test/Makefile.am +++ b/common/test/Makefile.am @@ -1,7 +1,7 @@ # $Id$ TESTPROGS = parsetest test-stack arraylisttest smartpointertest \ - iteratorfacadetest + sllisttest iteratorfacadetest # which tests to run TESTS = $(TESTPROGS) @@ -13,6 +13,8 @@ check_PROGRAMS = $(TESTPROGS) parsetest_SOURCES = parsetest.cc +sllisttest_SOURCES = sllisttest.cc + test_stack_SOURCES = test-stack.cc arraylisttest_SOURCES = arraylisttest.cc diff --git a/common/test/sllisttest.cc b/common/test/sllisttest.cc new file mode 100644 index 000000000..ff8a64540 --- /dev/null +++ b/common/test/sllisttest.cc @@ -0,0 +1,90 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#include <dune/common/sllist.hh> +#include <dune/common/test/iteratortest.hh> +#include <dune/common/poolallocator.hh> +#include <iostream> + +template<class A> +void randomizeListBack(Dune::SLList<double,A>& alist){ + using namespace Dune; + + srand((unsigned)time(0)); + + int lowest=0, highest=1000, range=(highest-lowest)+1; + + for(int i=0; i < 10; i++) + alist.push_back((range*(rand()/(RAND_MAX+1.0)))); +} + +template<class A> +void randomizeListFront(Dune::SLList<double,A>& alist){ + using namespace Dune; + + srand((unsigned)time(0)); + + int lowest=0, highest=1000, range=(highest-lowest)+1; + + for(int i=0; i < 10; i++) + alist.push_back((range*(rand()/(RAND_MAX+1.0)))); +} + +int testPushPop(){ + using namespace Dune; + int ret=0; + + Dune::SLList<int,PoolAllocator<int,8*1024-16> > alist; + + if(alist.begin() != alist.end()) { + ret++; + std::cout<<"For empty list begin and end iterator do not match! "<<__FILE__<<":"<<__LINE__<<std::endl; + ret++; + } + + alist.push_back(1); + if(*(alist.begin())!=1) { + std::cout<<"Entry should be 1! Push back failed! "<<__FILE__<<":"<<__LINE__<<std::endl; + ret++; + } + + alist.push_back(2); + if(*(alist.begin())!=1) { + ret++; + std::cout<<"Entry should be 2! Push back failed! "<<__FILE__<<":"<<__LINE__<<std::endl; + } + + alist.push_front(3); + if(*(alist.begin())!=3) { + ret++; + std::cout<<"Entry should be 3! Push front failed! "<<__FILE__<<":"<<__LINE__<<std::endl; + } + + alist.pop_front(); + if(*(alist.begin())!=1) { + ret++; + std::cout<<"Entry should be 1! Push back failed! "<<__FILE__<<":"<<__LINE__<<std::endl; + } + return ret; +} + +int main() +{ + int ret=0; + + Dune::SLList<double> list; + Dune::SLList<double,Dune::PoolAllocator<double, 8*1024-20> > list1; + + randomizeListBack(list1); + randomizeListFront(list); + + ret+=testIterator(list); + ret+=testIterator(list1); + ret+=testPushPop(); + + list.clear(); + list1.clear(); + randomizeListBack(list); + randomizeListFront(list1); + exit(ret); + +} -- GitLab