include/utilities/circular_list.h
author Dmitriy Morozov <dmitriy@mrzv.org>
Sun, 27 Apr 2014 13:49:14 -0700
branchdev
changeset 287 d3a10e66c6ab
parent 20 7bf6aa6b0ab6
permissions -rw-r--r--
Added a practical guide slides and examples to the docs

/**
 * Singly-linked circular list implementation by Donovan Rebbechi <elflord@pegasus.rutgers.edu>.
 * Tiny modifications by DM to make ISO C++ compliant (i.e., so that the compiler stops complaining), 
 * added size(), and boost serialization
 */

#ifndef __CIRCULAR_LIST_H__
#define __CIRCULAR_LIST_H__

#include <iterator>

#include <boost/serialization/access.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/binary_object.hpp>

#include "types.h"


template <class T>
class List
{
	struct Node
	{
		Node(const T& x,Node* y = 0):m_data(x),m_next(y){}
		T m_data;
		Node* m_next;
	
		private:
			// Serialization
			friend class boost::serialization::access;

			template<class Archive>
			void serialize(Archive& ar, version_type )
			{
				ar & make_nvp("data", m_data);
				ar & make_nvp("next", m_next);
			}
	};

	Node* m_node;
	size_t sz;
	
	private:
		// Serialization
		friend class boost::serialization::access;

		template<class Archive>
		void serialize(Archive& ar, version_type )
		{ ar & make_nvp("root", m_node); }

public:
	class const_iterator;
	
	class iterator
		: public std::iterator<std::forward_iterator_tag, T>
	{
		Node* m_rep;
	public:
		friend class List;
		friend class const_iterator;
		typedef T value_type;
		typedef T& reference;
		typedef T* pointer;
		typedef int difference_type;
		typedef std::forward_iterator_tag iterator_category;

		inline iterator(Node* x=0):m_rep(x){}
		inline iterator(const iterator& x):m_rep(x.m_rep) {}
		inline iterator(const const_iterator& x):m_rep(const_cast<Node*>(x.m_rep)) {}			// not very safe
		inline iterator& operator=(const iterator& x)
		{ 
			m_rep=x.m_rep; return *this; 
		}
		inline iterator& operator++()
		{ 
			m_rep = m_rep->m_next; return *this; 
		}
		inline iterator operator++(int)
		{ 
			iterator tmp(*this); m_rep = m_rep->m_next; return tmp; 
		}
		inline reference operator*() const { return m_rep->m_next->m_data; }
		inline pointer operator->() const { return m_rep->m_next; }
		inline bool operator==(const iterator& x) const
		{
			return m_rep == x.m_rep; 
		}	
		inline bool operator!=(const iterator& x) const
		{
			return m_rep != x.m_rep; 
		}	

	};

	class const_iterator
		: public std::iterator<std::forward_iterator_tag, const T>
	{
		const Node* m_rep;
	public:
		friend class List;
		friend class iterator;
		typedef T value_type;
		typedef T& reference;
		typedef T* pointer;
		typedef int difference_type;
		typedef std::forward_iterator_tag iterator_category;
		inline const_iterator(const Node* x=0):m_rep(x){}
		inline const_iterator(const const_iterator& x):m_rep(x.m_rep) {}
		inline const_iterator(const iterator& x):m_rep(x.m_rep){}
		inline const_iterator& operator=(const const_iterator& x)
		{ 
			m_rep=x.m_rep; return *this; 
		}
		inline const_iterator& operator=(const iterator& x)
		{ 
			m_rep=x.m_rep; return *this; 
		}		
		inline const_iterator& operator++()
		{ 
			m_rep = m_rep->m_next; return *this; 
		}
		inline const_iterator operator++(int)
		{ 
			const_iterator tmp(*this); m_rep = m_rep->m_next; return tmp; 
		}
		inline reference operator*() const { return m_rep->m_next->m_data; }
		inline pointer operator->() const { return m_rep->m_next; }
		inline bool operator==(const const_iterator& x) const
		{
			return m_rep == x.m_rep; 
		}
		inline bool operator!=(const const_iterator& x) const
		{
			return m_rep != x.m_rep; 
		}
	};

	typedef			T&				reference;
	typedef			const T&		const_reference;
	typedef			T*				pointer;
	typedef			const T*		const_pointer;

	List() : m_node(new Node(T())), sz(0) { m_node->m_next = m_node; }

	List(const List& L) : m_node(new Node(T())), sz(L.sz)
	{
		m_node->m_next=m_node;
		for ( const_iterator i = L.begin(); i!= L.end(); ++i )
			push_front(*i);
		reverse();
	}

	void reverse()
	{
		if (empty())
			return;
		Node* new_m_node = m_node->m_next->m_next;
		Node* p = m_node; Node* i = m_node->m_next; Node* n;
		do  
		{
			n = i->m_next;
			i->m_next = p;
			p = i; i = n;
		}
		while (p!=m_node);
		m_node = new_m_node;
	}

	void swap(List& x)
	{
		std::swap(m_node, x.m_node);
		std::swap(sz, x.sz);
	}

	List& operator=(const List& x)
	{
		List tmp(x);
		swap(tmp);
		return *this;
	}

	~List() { clear(); delete m_node; }
	void clear() { while (!empty()) pop_front(); sz = 0; }


	inline size_t size() const					{ return sz; }

	inline void push_front(const T&x)
	{
		insert (begin(),x);
	}
	inline void push_back(const T& x)
	{
		insert (end(),x);
	}
	inline void pop_front()
	{
		erase(begin());
	}
	inline bool empty() const { return m_node == m_node->m_next; }

	inline T& front() { return *begin(); }
	inline const T& front() const { return *begin(); }
	inline T& back() { return m_node->m_data; }
	inline const T& back() const { return m_node->m_data; }

	inline iterator begin() { return iterator(m_node->m_next); }
	inline iterator end() { return iterator(m_node); }
	inline const_iterator begin() const 
	{ 
		return const_iterator(m_node->m_next); 
	}
	inline const_iterator end() const 
	{ 
		return const_iterator(m_node); 
	}

	iterator erase (iterator x)
	{
		if (x == end())
			return x;
		
		if (x.m_rep->m_next == m_node)
			m_node = x.m_rep;

		Node* tmp = x.m_rep->m_next;
		x.m_rep->m_next = x.m_rep->m_next->m_next;
		delete tmp;
		--sz;

		return x;
	}

	iterator insert (iterator x, const T& y)
	{
		Node* tmp = new Node(y,x.m_rep->m_next);
		if (x.m_rep == m_node)		// if inserting before end
			m_node = tmp;
		x.m_rep->m_next = tmp;
		++sz;
		
		return x++;					// x points to the new data, return it, and slide it over
	}

	// rotate x to beginning
	void rotate (iterator x)
	{
		if (x == end())
			return;
		Node* sentinel = m_node->m_next;
		m_node->m_next = m_node->m_next->m_next;
		sentinel->m_next = x.m_rep->m_next;
		x.m_rep->m_next = sentinel;
		m_node = x.m_rep; 
	}
};

#endif // __CIRCULAR_LIST_H__