Skip to content
Snippets Groups Projects
Commit af56d927 authored by Markus Blatt's avatar Markus Blatt
Browse files

Added a single linked list. Provided a test for it.

[[Imported from SVN: r1096]]
parent 2580172e
No related branches found
No related tags found
No related merge requests found
// -*- 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
...@@ -7,4 +7,5 @@ parsetest ...@@ -7,4 +7,5 @@ parsetest
test-stack test-stack
arraylisttest arraylisttest
smartpointertest smartpointertest
iteratorfacadetest iteratorfacadetest
\ No newline at end of file sllisttest
\ No newline at end of file
# $Id$ # $Id$
TESTPROGS = parsetest test-stack arraylisttest smartpointertest \ TESTPROGS = parsetest test-stack arraylisttest smartpointertest \
iteratorfacadetest sllisttest iteratorfacadetest
# which tests to run # which tests to run
TESTS = $(TESTPROGS) TESTS = $(TESTPROGS)
...@@ -13,6 +13,8 @@ check_PROGRAMS = $(TESTPROGS) ...@@ -13,6 +13,8 @@ check_PROGRAMS = $(TESTPROGS)
parsetest_SOURCES = parsetest.cc parsetest_SOURCES = parsetest.cc
sllisttest_SOURCES = sllisttest.cc
test_stack_SOURCES = test-stack.cc test_stack_SOURCES = test-stack.cc
arraylisttest_SOURCES = arraylisttest.cc arraylisttest_SOURCES = arraylisttest.cc
......
// -*- 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);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment