/* * $Revision: 2615 $ * * last checkin: * $Author: gutwenger $ * $Date: 2012-07-16 14:23:36 +0200 (Mo, 16. Jul 2012) $ ***************************************************************/ /** \file * \brief Declaration and implementation of singly linked lists * (SListPure and SList) and iterators (SListConstIterator * and SListIterator). * * \author Carsten Gutwenger * * \par License: * This file is part of the Open Graph Drawing Framework (OGDF). * * \par * Copyright (C)
* See README.txt in the root directory of the OGDF installation for details. * * \par * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * Version 2 or 3 as published by the Free Software Foundation; * see the file LICENSE.txt included in the packaging of this file * for details. * * \par * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * \par * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * \see http://www.gnu.org/copyleft/gpl.html ***************************************************************/ #ifdef _MSC_VER #pragma once #endif #ifndef OGDF_SLIST_H #define OGDF_SLIST_H #include "../internal/basic/list_templates.h" namespace ogdf { template class SListPure; template class StackPure; template class SListIterator; template class SListConstIterator; //! The parameterized class \a SListElement represents the structure for elements of singly linked lists. template class SListElement { friend class SListPure; friend class StackPure; friend class SListIterator; friend class SListConstIterator; SListElement *m_next; //!< Pointer to successor element. E m_x; //!< Stores the content. //! Constructs an SListElement. SListElement() : m_next(0) { } //! Constructs an SListElement. SListElement(const E &x) : m_next(0), m_x(x) { } //! Constructs an SListElement. SListElement(const E &x, SListElement *next) : m_next(next), m_x(x) { } OGDF_NEW_DELETE }; // class SListElement //! The parameterized class \a SListIterator encapsulates a pointer to an slist element. /** * It is used in order to iterate over singly linked lists, * and to specify a position in a singly linked list. It is possible that * an iterator encapsulates a null pointer. */ template class SListIterator { SListElement *m_pX; //!< Pointer to slist element. friend class SListConstIterator; friend class SListPure; //! Conversion to pointer to slist element. operator SListElement *() { return m_pX; } //! Conversion to pointer to slist element. operator const SListElement *() const { return m_pX; } public: //! Constructs an iterator pointing to no element. SListIterator() : m_pX(0) { } //! Constructs an iterator pointing to \a pX. SListIterator(SListElement *pX) : m_pX(pX) { } //! Constructs an iterator that is a copy of \a it. SListIterator(const SListIterator &it) : m_pX(it.m_pX) { } //! Returns true iff the iterator points to an element. bool valid() const { return m_pX != 0; } //! Equality operator. bool operator==(const SListIterator &it) const { return m_pX == it.m_pX; } //! Inequality operator. bool operator!=(const SListIterator &it) const { return m_pX != it.m_pX; } //! Returns successor iterator. SListIterator succ() const { return m_pX->m_next; } //! Returns a reference to the element content. E &operator*() const { return m_pX->m_x; } //! Assignment operator. SListIterator &operator=(const SListIterator &it) { m_pX = it.m_pX; return *this; } //! Increment operator (prefix). SListIterator &operator++() { m_pX = m_pX->m_next; return *this; } //! Increment operator (postfix). SListIterator operator++(int) { SListIterator it = *this; m_pX = m_pX->m_next; return it; } OGDF_NEW_DELETE }; // class SListIterator //! The parameterized class \a SListIterator encapsulates a constant pointer to an slist element. /** * It is used in order to iterate over singly linked lists, * and to specify a position in a singly linked list. It is possible that * an iterator encapsulates a null pointer. In contrast to SListIterator, * it is not possible to change the slist element pointed to. */ template class SListConstIterator { const SListElement *m_pX; //!< Pointer to slist element. friend class SListPure; //! Conversion to pointer to slist element. operator const SListElement *() { return m_pX; } public: //! Constructs an iterator pointing to no element. SListConstIterator() : m_pX(0) { } //! Constructs an iterator pointing to \a pX. SListConstIterator(const SListElement *pX) : m_pX(pX) { } //! Constructs an iterator that is a copy of \a it. SListConstIterator(const SListIterator &it) : m_pX((const SListElement *)it) { } //! Constructs an iterator that is a copy of \a it. SListConstIterator(const SListConstIterator &it) : m_pX(it.m_pX) { } //! Returns true iff the iterator points to an element. bool valid() const { return m_pX != 0; } //! Equality operator. bool operator==(const SListConstIterator &it) const { return m_pX == it.m_pX; } //! Inequality operator. bool operator!=(const SListConstIterator &it) const { return m_pX != it.m_pX; } //! Returns successor iterator. SListConstIterator succ() const { return m_pX->m_next; } //! Returns a reference to the element content. const E &operator*() const { return m_pX->m_x; } //! Assignment operator. SListConstIterator &operator=(const SListConstIterator &it) { m_pX = it.m_pX; return *this; } //! Increment operator (prefix). SListConstIterator &operator++() { m_pX = m_pX->m_next; return *this; } //! Increment operator (postfix). SListConstIterator operator++(int) { SListConstIterator it = *this; m_pX = m_pX->m_next; return it; } OGDF_NEW_DELETE }; // class SListConstIterator //! The parameterized class \a SListPure represents singly linked lists with content type \a E. /** * Elements of the list are instances of type SListElement. * Use SListConstIterator or SListIterator in order to iterate over the list. * * In contrast to SList, instances of \a SListPure do not store the length of the list. * * @tparam E is the data type stored in list elements. */ template class SListPure { SListElement *m_head; //!< Pointer to first element. SListElement *m_tail; //!< Pointer to last element. public: //! Constructs an empty singly linked list. SListPure() : m_head(0), m_tail(0) { } //! Constructs a singly linked list that is a copy of \a L. SListPure(const SListPure &L) : m_head(0), m_tail(0) { copy(L); } // destruction ~SListPure() { clear(); } typedef E value_type; typedef SListElement element_type; typedef SListConstIterator const_iterator; typedef SListIterator iterator; //! Returns true iff the list is empty. bool empty() const { return m_head == 0; } //! Returns the length of the list /** * Notice that this method requires to run through the whole list and takes linear running time! */ int size() const { int count = 0; for (SListElement *pX = m_head; pX; pX = pX->m_next) ++count; return count; } //! Returns an iterator to the first element of the list. /** * If the list is empty, a null pointer iterator is returned. */ SListConstIterator begin() const { return m_head; } //! Returns an iterator to the first element of the list. /** * If the list is empty, a null pointer iterator is returned. */ SListIterator begin() { return m_head; } //! Returns an iterator to one-past-last element of the list. /** * This is always a null pointer iterator. */ SListConstIterator end() const { return SListConstIterator(); } //! Returns an iterator to one-past-last element of the list. /** * This is always a null pointer iterator. */ SListIterator end() { return SListIterator(); } //! Returns an iterator to the last element of the list. /** * If the list is empty, a null pointer iterator is returned. */ SListConstIterator rbegin() const { return m_tail; } //! Returns an iterator to the last element of the list. /** * If the list is empty, a null pointer iterator is returned. */ SListIterator rbegin() { return m_tail; } //! Returns an iterator pointing to the element at position \a pos. /** * The running time of this method is linear in \a pos. */ SListConstIterator get(int pos) const { SListElement *pX; for(pX = m_head; pX != 0; pX = pX->m_next) if (pos-- == 0) break; return pX; } //! Returns an iterator pointing to the element at position \a pos. /** * The running time of this method is linear in \a pos. */ SListIterator get(int pos) { SListElement *pX; for(pX = m_head; pX != 0; pX = pX->m_next) if (pos-- == 0) break; return pX; } //! Returns the position (starting with 0) of \a it in the list. /** * Positions are numbered 0,1,... * \pre \a it is an iterator pointing to an element in this list. */ int pos(SListConstIterator it) const { OGDF_ASSERT(it.valid()) int p = 0; for(SListElement *pX = m_head; pX != 0; pX = pX->m_next, ++p) if (pX == it) break; return p; } //! Returns a reference to the first element. /** * \pre The list is not empty! */ const E &front() const { OGDF_ASSERT(m_head != 0) return m_head->m_x; } //! Returns a reference to the first element. /** * \pre The list is not empty! */ E &front() { OGDF_ASSERT(m_head != 0) return m_head->m_x; } //! Returns a reference to the last element. /** * \pre The list is not empty! */ const E &back() const { OGDF_ASSERT(m_tail != 0) return m_tail->m_x; } //! Returns a reference to the last element. /** * \pre The list is not empty! */ E &back() { OGDF_ASSERT(m_tail != 0) return m_tail->m_x; } //! Returns an iterator to the cyclic successor of \a it. /** * \pre \a it points to an element in this list! */ SListConstIterator cyclicSucc(SListConstIterator it) const { const SListElement *pX = it; return (pX->m_next) ? pX->m_next : m_head; } //! Returns an iterator to the cyclic successor of \a it. /** * \pre \a it points to an element in this list! */ SListIterator cyclicSucc(SListIterator it) { SListElement *pX = it; return (pX->m_next) ? pX->m_next : m_head; } //! Assignment operator. SListPure &operator=(const SListPure &L) { clear(); copy(L); return *this; } //! Adds element \a x at the begin of the list. SListIterator pushFront(const E &x) { m_head = OGDF_NEW SListElement(x,m_head); if (m_tail == 0) m_tail = m_head; return m_head; } //! Adds element \a x at the end of the list. SListIterator pushBack(const E &x) { SListElement *pNew = OGDF_NEW SListElement(x); if (m_head == 0) m_head = m_tail = pNew; else m_tail = m_tail->m_next = pNew; return m_tail; } //! Inserts element \a x after \a pBefore. /** * \pre \a pBefore points to an element in this list. */ SListIterator insertAfter(const E &x, SListIterator itBefore) { SListElement *pBefore = itBefore; OGDF_ASSERT(pBefore != 0) SListElement *pNew = OGDF_NEW SListElement(x,pBefore->m_next); if (pBefore == m_tail) m_tail = pNew; return (pBefore->m_next = pNew); } //! Removes the first element from the list. /** * \pre The list is not empty! */ void popFront() { OGDF_ASSERT(m_head != 0) SListElement *pX = m_head; if ((m_head = m_head->m_next) == 0) m_tail = 0; delete pX; } //! Removes the first element from the list and returns it. /** * \pre The list is not empty! */ E popFrontRet() { E el = front(); popFront(); return el; } //! Removes the succesor of \a pBefore. /** * \pre \a pBefore points to an element in this list. */ void delSucc(SListIterator itBefore) { SListElement *pBefore = itBefore; OGDF_ASSERT(pBefore != 0) SListElement *pDel = pBefore->m_next; OGDF_ASSERT(pDel != 0) if ((pBefore->m_next = pDel->m_next) == 0) m_tail = pBefore; delete pDel; } //! Moves the first element of this list to the begin of list \a L2. void moveFrontToFront(SListPure &L2) { OGDF_ASSERT(m_head != 0) OGDF_ASSERT(this != &L2) SListElement *pX = m_head; if ((m_head = m_head->m_next) == 0) m_tail = 0; pX->m_next = L2.m_head; L2.m_head = pX; if (L2.m_tail == 0) L2.m_tail = L2.m_head; } //! Moves the first element of this list to the end of list \a L2. void moveFrontToBack(SListPure &L2) { OGDF_ASSERT(m_head != 0) OGDF_ASSERT(this != &L2) SListElement *pX = m_head; if ((m_head = m_head->m_next) == 0) m_tail = 0; pX->m_next = 0; if (L2.m_head == 0) L2.m_head = L2.m_tail = pX; else L2.m_tail = L2.m_tail->m_next = pX; } //! Moves the first element of this list to list \a L2 inserted after \a itBefore. /** * \pre \a itBefore points to an element in \a L2. */ void moveFrontToSucc(SListPure &L2, SListIterator itBefore) { OGDF_ASSERT(m_head != 0) OGDF_ASSERT(this != &L2) SListElement *pBefore = itBefore; SListElement *pX = m_head; if ((m_head = m_head->m_next) == 0) m_tail = 0; pX->m_next = pBefore->m_next; pBefore->m_next = pX; if (pBefore == L2.m_tail) L2.m_tail = pX; } //! Removes all elements from the list. void clear() { if (m_head == 0) return; #if (_MSC_VER == 1100) // workaround for bug in Visual Studio 5.0 while (!empty()) popFront(); #else if (doDestruction((E*)0)) { for(SListElement *pX = m_head; pX != 0; pX = pX->m_next) pX->m_x.~E(); } OGDF_ALLOCATOR::deallocateList(sizeof(SListElement),m_head,m_tail); #endif m_head = m_tail = 0; } //! Appends \a L2 to this list and makes \a L2 empty. void conc(SListPure &L2) { if (m_head) m_tail->m_next = L2.m_head; else m_head = L2.m_head; if (L2.m_tail != 0) m_tail = L2.m_tail; L2.m_head = L2.m_tail = 0; } //! Reverses the order of the list elements. void reverse() { SListElement *p, *pNext, *pPred = 0; for(p = m_head; p; p = pNext) { pNext = p->m_next; p->m_next = pPred; pPred = p; } swap(m_head,m_tail); } //! Conversion to const SListPure. const SListPure &getListPure() const { return *this; } //! Sorts the list using Quicksort. void quicksort() { ogdf::quicksortTemplate(*this); } //! Sorts the list using Quicksort and comparer \a comp. template void quicksort(const COMPARER &comp) { ogdf::quicksortTemplate(*this,comp); } //! Sorts the list using bucket sort. /** * @param l is the lowest bucket that will occur. * @param h is the highest bucket that will occur. * @param f returns the bucket for each element. * \pre The bucket function \a f will only return bucket values between \a l * and \a h for this list. */ void bucketSort(int l, int h, BucketFunc &f); //! Sorts the list using bucket sort. void bucketSort(BucketFunc &f); //! Randomly permutes the elements in the list. void permute() { permute(size()); } //! Scans the list for the specified element and returns its position in the list, or -1 if not found. int search (const E& e) const { int x = 0; for(SListConstIterator i = begin(); i.valid(); ++i, ++x) if(*i == e) return x; return -1; } //! Scans the list for the specified element (using the user-defined comparer) and returns its position in the list, or -1 if not found. template int search (const E& e, const COMPARER &comp) const { int x = 0; for(SListConstIterator i = begin(); i.valid(); ++i, ++x) if(comp.equal(*i,e)) return x; return -1; } protected: void copy(const SListPure &L) { for(SListElement *pX = L.m_head; pX != 0; pX = pX->m_next) pushBack(pX->m_x); } void permute(const int n); OGDF_NEW_DELETE }; // class SListPure //! The parameterized class \a SList represents singly linked lists with content type \a E. /** * Elements of the list are instances of type SListElement. * Use SListConstIterator or SListIterator in order to iterate over the list. * In contrast to SListPure, instances of \a SList store the length of the list * and thus allow constant time access to the length. * * @tparam E is the data type stored in list elements. */ template class SList : private SListPure { int m_count; //!< The length of the list. public: //! Constructs an empty singly linked list. SList() : m_count(0) { } //! Constructs a singly linked list that is a copy of \a L. SList(const SList &L) : SListPure(L), m_count(L.m_count) { } // destruction ~SList() { } typedef E value_type; typedef SListElement element_type; typedef SListConstIterator const_iterator; typedef SListIterator iterator; //! Returns true iff the list is empty. bool empty() const { return SListPure::empty(); } //! Returns the length of the list. int size() const { return m_count; } //! Returns an iterator to the first element of the list. /** * If the list is empty, a null pointer iterator is returned. */ const SListConstIterator begin() const { return SListPure::begin(); } //! Returns an iterator to the first element of the list. /** * If the list is empty, a null pointer iterator is returned. */ SListIterator begin() { return SListPure::begin(); } //! Returns an iterator to one-past-last element of the list. /** * This is always a null pointer iterator. */ SListConstIterator end() const { return SListConstIterator(); } //! Returns an iterator to one-past-last element of the list. /** * This is always a null pointer iterator. */ SListIterator end() { return SListIterator(); } //! Returns an iterator to the last element of the list. /** * If the list is empty, a null pointer iterator is returned. */ const SListConstIterator rbegin() const { return SListPure::rbegin(); } //! Returns an iterator to the last element of the list. /** * If the list is empty, a null pointer iterator is returned. */ SListIterator rbegin() { return SListPure::rbegin(); } //! Returns an iterator pointing to the element at position \a pos. /** * The running time of this method is linear in \a pos. */ SListConstIterator get(int pos) const { return SListPure::get(pos); } //! Returns an iterator pointing to the element at position \a pos. /** * The running time of this method is linear in \a pos. */ SListIterator get(int pos) { return SListPure::get(pos); } //! Returns the position (starting with 0) of \a it in the list. /** * Positions are numbered 0,1,... * \pre \a it is an iterator pointing to an element in this list. */ int pos(SListConstIterator it) const { return SListPure::pos(it);; } //! Returns a reference to the first element. /** * \pre The list is not empty! */ const E &front() const { return SListPure::front(); } //! Returns a reference to the first element. /** * \pre The list is not empty! */ E &front() { return SListPure::front(); } //! Returns a reference to the last element. /** * \pre The list is not empty! */ const E &back() const { return SListPure::back(); } //! Returns a reference to the last element. /** * \pre The list is not empty! */ E &back() { return SListPure::back(); } //! Returns an iterator to the cyclic successor of \a it. /** * \pre \a it points to an element in this list! */ SListConstIterator cyclicSucc(SListConstIterator it) const { return SListPure::cyclicSucc(it); } //! Returns an iterator to the cyclic successor of \a it. /** * \pre \a it points to an element in this list! */ SListIterator cyclicSucc(SListIterator it) { return SListPure::cyclicSucc(it); } //! Assignment operator. SList &operator=(const SList &L) { SListPure::operator=(L); m_count = L.m_count; return *this; } //! Adds element \a x at the begin of the list. SListIterator pushFront(const E &x) { ++m_count; return SListPure::pushFront(x); } //! Adds element \a x at the end of the list. SListIterator pushBack(const E &x) { ++m_count; return SListPure::pushBack(x); } //! Inserts element \a x after \a pBefore. /** * \pre \a pBefore points to an element in this list. */ SListIterator insertAfter(const E &x, SListIterator itBefore) { ++m_count; return SListPure::insertAfter(x, itBefore); } //! Removes the first element from the list. /** * \pre The list is not empty! */ void popFront() { --m_count; SListPure::popFront(); } //! Removes the first element from the list and returns it. /** * \pre The list is not empty! */ E popFrontRet() { E el = front(); popFront(); return el; } //! Removes the succesor of \a pBefore. /** * \pre \a pBefore points to an element in this list. */ void delSucc(SListIterator itBefore) { --m_count; SListPure::delSucc(itBefore); } //! Moves the first element of this list to the begin of list \a L2. void moveFrontToFront(SList &L2) { SListPure::moveFrontToFront(L2); --m_count; ++L2.m_count; } //! Moves the first element of this list to the end of list \a L2. void moveFrontToBack(SList &L2) { SListPure::moveFrontToBack(L2); --m_count; ++L2.m_count; } //! Moves the first element of this list to list \a L2 inserted after \a itBefore. /** * \pre \a itBefore points to an element in \a L2. */ void moveFrontToSucc(SList &L2, SListIterator itBefore) { SListPure::moveFrontToSucc(L2,itBefore); --m_count; ++L2.m_count; } //! Removes all elements from the list. void clear() { m_count = 0; SListPure::clear(); } //! Appends \a L2 to this list and makes \a L2 empty. void conc(SList &L2) { SListPure::conc(L2); m_count += L2.m_count; L2.m_count = 0; } //! Reverses the order of the list elements. void reverse() { SListPure::reverse(); } //! Conversion to const SListPure. const SListPure &getListPure() const { return *this; } //! Sorts the list using Quicksort. void quicksort() { ogdf::quicksortTemplate(*this); } //! Sorts the list using Quicksort and comparer \a comp. template void quicksort(const COMPARER &comp) { ogdf::quicksortTemplate(*this,comp); } //! Sorts the list using bucket sort. /** * @param l is the lowest bucket that will occur. * @param h is the highest bucket that will occur. * @param f returns the bucket for each element. * \pre The bucket function \a f will only return bucket values between \a l * and \a h for this list. */ void bucketSort(int l, int h, BucketFunc &f) { SListPure::bucketSort(l,h,f); } //! Sorts the list using bucket sort. void bucketSort(BucketFunc &f) { SListPure::bucketSort(f); } //! Randomly permutes the elements in the list. void permute() { SListPure::permute(m_count); } //! Scans the list for the specified element and returns its position in the list, or -1 if not found. int search (const E& e) const { return SListPure::search(e); } //! Scans the list for the specified element (using the user-defined comparer) and returns its position in the list, or -1 if not found. template int search (const E& e, const COMPARER &comp) const { return SListPure::search(e, comp); } OGDF_NEW_DELETE }; // class SList // sorts list L using bucket sort // computes l and h value template void SListPure::bucketSort(BucketFunc &f) { // if less than two elements, nothing to do if (m_head == m_tail) return; int l, h; l = h = f.getBucket(m_head->m_x); SListElement *pX; for(pX = m_head->m_next; pX; pX = pX->m_next) { int i = f.getBucket(pX->m_x); if (i < l) l = i; if (i > h) h = i; } bucketSort(l,h,f); } // sorts list L using bucket sort template void SListPure::bucketSort(int l, int h, BucketFunc &f) { // if less than two elements, nothing to do if (m_head == m_tail) return; Array *> head(l,h,0), tail(l,h); SListElement *pX; for (pX = m_head; pX; pX = pX->m_next) { int i = f.getBucket(pX->m_x); if (head[i]) tail[i] = (tail[i]->m_next = pX); else head[i] = tail[i] = pX; } SListElement *pY = 0; for (int i = l; i <= h; i++) { pX = head[i]; if (pX) { if (pY) pY->m_next = pX; else m_head = pX; pY = tail[i]; } } m_tail = pY; pY->m_next = 0; } // permutes elements in list randomly; n is the length of the list template void SListPure::permute(const int n) { Array *> A(n+1); A[n] = 0; int i = 0; SListElement *pX; for (pX = m_head; pX; pX = pX->m_next) A[i++] = pX; A.permute(0,n-1); for (i = 0; i < n; i++) { A[i]->m_next = A[i+1]; } m_head = A[0]; m_tail = A[n-1]; } // prints list to output stream os using delimiter delim template void print(ostream &os, const SListPure &L, char delim = ' ') { SListConstIterator pX = L.begin(); if (pX.valid()) { os << *pX; for(++pX; pX.valid(); ++pX) os << delim << *pX; } } // prints list to output stream os using delimiter delim template void print(ostream &/*os*/, const SList &L, char delim = ' ') { print(L.getListPure(), delim); } // output operator template ostream &operator<<(ostream &os, const SListPure &L) { print(os,L); return os; } template ostream &operator<<(ostream &os, const SList &L) { return operator<<(os,L.getListPure()); } // sort array using bucket sort and bucket object f; // the values of f must be in the interval [min,max] template void bucketSort(Array &a, int min, int max, BucketFunc &f) { if (a.low() >= a.high()) return; Array > bucket(min,max); int i; for(i = a.low(); i <= a.high(); ++i) bucket[f.getBucket(a[i])].pushBack(a[i]); i = a.low(); for(int j = min; j <= max; ++j) { SListConstIterator it = bucket[j].begin(); for(; it.valid(); ++it) a[i++] = *it; } } } // namespace ogdf #endif