337 lines
8.9 KiB
C
337 lines
8.9 KiB
C
|
#ifndef __lst_h__
|
||
|
#define __lst_h__
|
||
|
|
||
|
#ifndef ASSERT
|
||
|
#define ASSERT( x )
|
||
|
#endif // #ifndef ASSERT
|
||
|
|
||
|
#include <functional>
|
||
|
|
||
|
|
||
|
// lst bidirectional linked-list template class
|
||
|
// Here are some examples of the usage:
|
||
|
//
|
||
|
// lst< int > MyList;
|
||
|
//
|
||
|
// for( int i = 0; i < 10; i++ ) {
|
||
|
// MyList . push_front( i );
|
||
|
// }
|
||
|
//
|
||
|
//
|
||
|
// lst< int > TestList;
|
||
|
// TestList . insert( TestList . begin(), MyList . begin(), MyList . end() );
|
||
|
//
|
||
|
// const lst< int > cList = MyList;
|
||
|
//
|
||
|
// lst< int >::const_iterator I = cList . begin();
|
||
|
// while( I != cList . end() ) {
|
||
|
// int Num = *I;
|
||
|
// I++;
|
||
|
// }
|
||
|
//
|
||
|
//
|
||
|
// the const_iterator is used to iterate through a const List
|
||
|
//
|
||
|
//
|
||
|
|
||
|
template< class T, class Operator_Eq = std::equal_to<T> >
|
||
|
class lst {
|
||
|
|
||
|
private: // Data types and typedefs
|
||
|
|
||
|
typedef T value_type;
|
||
|
typedef value_type* pointer;
|
||
|
typedef value_type& reference;
|
||
|
typedef const value_type& const_reference;
|
||
|
typedef lst< value_type > self;
|
||
|
Operator_Eq _FnEq;
|
||
|
|
||
|
class node {
|
||
|
public:
|
||
|
node( node* pP, node* pN, const_reference t ) : pNext( pN ), pPrev( pP ), data( t ) { ; }
|
||
|
node( void ) : pNext( NULL ), pPrev( NULL ) { ; }
|
||
|
node* pNext;
|
||
|
node* pPrev;
|
||
|
value_type data;
|
||
|
};
|
||
|
|
||
|
public:
|
||
|
// iterator class for iterating through the list
|
||
|
class iterator {
|
||
|
friend lst;
|
||
|
private:
|
||
|
typedef iterator self;
|
||
|
node* pNode;
|
||
|
|
||
|
iterator( node* pN ) : pNode( pN ) { ; }
|
||
|
|
||
|
public:
|
||
|
iterator( void ) : pNode( NULL ) { ; }
|
||
|
~iterator( void ) { ; }
|
||
|
|
||
|
iterator( self& r ) { *this = r; }
|
||
|
|
||
|
iterator& operator=( iterator& r ) { pNode = r . pNode; return *this; }
|
||
|
bool operator==( const self& r ) const { return pNode == r . pNode; }
|
||
|
operator!=( const self& r ) const { return pNode != r . pNode; }
|
||
|
reference operator*() { return pNode -> data; }
|
||
|
self& operator++() {
|
||
|
pNode = pNode -> pNext;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
self operator++( int ) {
|
||
|
self tmp = *this;
|
||
|
++*this;
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
self& operator--() {
|
||
|
pNode = pNode -> pPrev;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
self operator--(int) {
|
||
|
self tmp = *this;
|
||
|
--*this;
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
// const_iterator class for iterating through a const list
|
||
|
class const_iterator {
|
||
|
friend lst;
|
||
|
|
||
|
private:
|
||
|
|
||
|
typedef const_iterator self;
|
||
|
const node* pNode;
|
||
|
const_iterator( const node* pN ) : pNode( pN ) { ; }
|
||
|
|
||
|
public:
|
||
|
const_iterator( void ) : pNode( NULL ) { ; }
|
||
|
~const_iterator( void ) { ; }
|
||
|
|
||
|
const_iterator( const self& r ) { *this = r; }
|
||
|
|
||
|
const_iterator& operator=( const const_iterator& r ) { pNode = r . pNode; return *this;}
|
||
|
bool operator==( const self& r ) const { return pNode == r . pNode; }
|
||
|
operator!=( const self& r ) const { return pNode != r . pNode; }
|
||
|
const_reference operator*() const { return pNode -> data; }
|
||
|
|
||
|
self& operator++() {
|
||
|
pNode = pNode -> pNext;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
self operator++( int ) {
|
||
|
self tmp = *this;
|
||
|
++*this;
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
self& operator--() {
|
||
|
pNode = pNode -> pPrev;
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
self operator--(int) {
|
||
|
self tmp = *this;
|
||
|
--*this;
|
||
|
return tmp;
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
|
||
|
// Data
|
||
|
node* m_pNode;
|
||
|
size_t m_nItems;
|
||
|
|
||
|
public:
|
||
|
// construction / destruction
|
||
|
lst( void ) {
|
||
|
empty_initialize();
|
||
|
};
|
||
|
|
||
|
lst( const self& rList ) { empty_initialize(); *this = rList; }
|
||
|
~lst( void ) { clear(); delete m_pNode; m_pNode = NULL; }
|
||
|
|
||
|
bool operator==( const self& rList ) const {
|
||
|
if( size() != rList . size() ) { return false; }
|
||
|
|
||
|
self::const_iterator IThis = begin();
|
||
|
self::const_iterator IThat = rList . begin();
|
||
|
|
||
|
while( IThis != end() ) {
|
||
|
if( !_FnEq( *IThis, *IThat ) ) {
|
||
|
return false;
|
||
|
}
|
||
|
++IThat;
|
||
|
++IThis;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Member Fns
|
||
|
self& operator=( const self& rList ) {
|
||
|
clear();
|
||
|
insert( begin(), rList . begin(), rList . end() );
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
void empty_initialize( void ) {
|
||
|
m_pNode = new node;
|
||
|
m_pNode -> pNext = m_pNode;
|
||
|
m_pNode -> pPrev = m_pNode;
|
||
|
m_nItems = 0;
|
||
|
}
|
||
|
|
||
|
void clear( void ) {
|
||
|
node* pCur = m_pNode -> pNext;
|
||
|
while( pCur != m_pNode ) {
|
||
|
node* pTmp = pCur;
|
||
|
pCur = pCur -> pNext;
|
||
|
--m_nItems;
|
||
|
delete pTmp;
|
||
|
pTmp = NULL;
|
||
|
}
|
||
|
m_pNode -> pNext = m_pNode;
|
||
|
m_pNode -> pPrev = m_pNode;
|
||
|
|
||
|
}
|
||
|
|
||
|
// Return the size of the list
|
||
|
size_t size( void ) const { return m_nItems; }
|
||
|
bool empty( void ) const { return 0 == size(); }
|
||
|
|
||
|
// Return an iterator to the position after the last element in the list
|
||
|
// N.B. ---- Don't dereference end()!!!!!!
|
||
|
// N.B. ---- end()++ is undefined!!!!!!
|
||
|
iterator end( void ) { return iterator( m_pNode ); }
|
||
|
const_iterator end( void ) const { return const_iterator( m_pNode ); }
|
||
|
|
||
|
// Return an iterator to the position of the first element of the list
|
||
|
// You may dereference begin()
|
||
|
iterator begin( void ) { return iterator( m_pNode -> pNext ); }
|
||
|
const_iterator begin( void ) const { return const_iterator( m_pNode -> pNext ); }
|
||
|
|
||
|
// Returns a reference to the first element in the list
|
||
|
reference front( void ) { return *begin(); }
|
||
|
const_reference front( void ) const { return *begin(); }
|
||
|
|
||
|
// Returns a reference to the last element in the list
|
||
|
reference back( void ) { return *(--end()); }
|
||
|
const_reference back( void ) const { return *(--end()); }
|
||
|
|
||
|
// add an object to the front of the list
|
||
|
void push_front( const_reference x ) { insert(begin(), x); }
|
||
|
|
||
|
// add an object to the end of the list
|
||
|
void push_back( const_reference x ) { insert(end(), x); }
|
||
|
|
||
|
// Insert an item before the item that position points to
|
||
|
void insert( iterator position, const_reference r ) {
|
||
|
node* pTmp = new node( position . pNode -> pPrev, position . pNode, r );
|
||
|
( position . pNode -> pPrev ) -> pNext = pTmp;
|
||
|
position . pNode -> pPrev = pTmp;
|
||
|
++m_nItems;
|
||
|
}
|
||
|
|
||
|
// Insert items first through last to the list at position position
|
||
|
void insert( iterator position, iterator first, iterator last ) {
|
||
|
for ( ; first != last; ++first) {
|
||
|
insert(position, *first);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Insert items first through last to the list at position position
|
||
|
void insert( iterator position, const_iterator first, const_iterator last ) {
|
||
|
for ( ; first != last; ++first) {
|
||
|
insert(position, *first);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Pop the first element from the list
|
||
|
void pop_front( void ) { erase(begin()); }
|
||
|
|
||
|
|
||
|
// Pop the last element from the list
|
||
|
void pop_back( void ) {
|
||
|
iterator tmp = end();
|
||
|
erase(--tmp);
|
||
|
}
|
||
|
|
||
|
|
||
|
// erase the item at position pos in the list
|
||
|
void erase( iterator pos ) {
|
||
|
ASSERT( pos != end() );
|
||
|
( pos . pNode -> pPrev ) -> pNext = pos . pNode -> pNext;
|
||
|
( pos . pNode -> pNext ) -> pPrev = pos . pNode -> pPrev;
|
||
|
--m_nItems;
|
||
|
delete pos . pNode;
|
||
|
pos . pNode = NULL;
|
||
|
|
||
|
}
|
||
|
|
||
|
// erase the items in the range first through last
|
||
|
void erase( iterator first, iterator last ) {
|
||
|
while (first != last) erase(first++);
|
||
|
}
|
||
|
|
||
|
|
||
|
const_iterator find( const_reference x ) const {
|
||
|
return find( begin(), end(), x );
|
||
|
}
|
||
|
|
||
|
iterator find( const_reference x ) {
|
||
|
return find( begin(), end(), x );
|
||
|
}
|
||
|
|
||
|
iterator find( iterator first, iterator last, const_reference x ) {
|
||
|
while( first != last ) {
|
||
|
if( _FnEq(*first, x) ) {
|
||
|
return first;
|
||
|
}
|
||
|
first++;
|
||
|
}
|
||
|
return end();
|
||
|
}
|
||
|
|
||
|
const_iterator find( const_iterator first, const_iterator last, const_reference x ) const {
|
||
|
while( first != last ) {
|
||
|
if( _FnEq(*first, x) ) {
|
||
|
return first;
|
||
|
}
|
||
|
first++;
|
||
|
}
|
||
|
return end();
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
template< class T, class F >
|
||
|
lst< T >::iterator find( lst< T >& rLst, F& f ) {
|
||
|
lst< T >::iterator I = rLst . begin();
|
||
|
while( rLst . end() != I ) {
|
||
|
if( f( *I ) ) {
|
||
|
return I;
|
||
|
}
|
||
|
++I;
|
||
|
}
|
||
|
return I;
|
||
|
}
|
||
|
|
||
|
template< class T, class F >
|
||
|
void for_each( lst< T >& rLst, F& f ) {
|
||
|
lst< T >::iterator I = rLst . begin();
|
||
|
while( rLst . end() != I ) {
|
||
|
f( *I );
|
||
|
++I;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif //__lst_h__
|