kicad/polygon/kbool/include/_dl_itr.cpp

2379 lines
58 KiB
C++

/*! \file kbool/include/kbool/_dl_itr.cpp
\brief Double Linked list with Iterators on list
\author Probably Klaas Holwerda
Copyright: 2001-2004 (C) Probably Klaas Holwerda
Licence: wxWidgets Licence
RCS-ID: $Id: _dl_itr.cpp,v 1.1 2005/05/24 19:13:35 titato Exp $
*/
#ifdef __GNUG__
#pragma implementation
#endif
#ifdef __UNIX__
#include "../include/_dl_itr.h"
#endif
//=======================================================================
// implementation class DL_Node
//=======================================================================
/*! \class DL_Node
* This class is used in the class DL_List to contain the items of the list. This can be a
* pointer to an object or the object itself. The class contains a next and a previous pointer
* to connect the nodes in the list. \n
* class Dtype | Object stored at the node
*/
/*!
Construct a node for a list object
\param it Item the node will contain
*/
template <class Dtype>
DL_Node<Dtype>::DL_Node(Dtype it) // + init nodeitem
:_item(it)
{}
/*!
Template constructor no contents
Construct a node for a list object
*/
template <class Dtype>
DL_Node<Dtype>::DL_Node()
:_item(0)
{}
/*!
Destruct a node object
*/
template <class Dtype>
DL_Node<Dtype>::~DL_Node()
{
}
//=======================================================================
// implementation class DL_List
//=======================================================================
/*! \class DL_List
* class is the base class for implementing a double linked list. The Root node marks the begining and end of the list. The
* lists consists of nodes double linked with a next and previous pointer DL_Node The nodes are cyclic connected to the root
* node. The list is meant to be used with an iterator class, to traverse the nodes. More then 1 iterator can be attached to the
* list. The list keeps track of the number of iterators that are attached to it. Depending on this certain operations are allowed
* are not. For instance a node can only be deleted if there is only one iterator attached to the list.
* class | Dtype | Object contaning List Nodes
*/
/*!
Construct a node object
\par Example:
How to construct a list of type integer:
\code
DL_List<int> * a_list = new DL_List<int>();
\endcode
*/
template <class Dtype>
DL_List<Dtype>::DL_List()
:_nbitems(0), _iterlevel(0)
{
_root = new DL_Node<Dtype>();
_root->_next=_root;
_root->_prev=_root;
}
/*!
//Destruct a list object
\par Example:
How to construct a list of type integer:
\code
DL_List<int> * a_list = new DL_List<int>(); # declaration and allocation
delete a_list; #delete it (must have no iterators attached to it)
\endcode
*/
template <class Dtype>
DL_List<Dtype>::~DL_List()
{
if (_iterlevel != 0)
throw Bool_Engine_Error("DL_List::~DL_List()\n_iterlevel > 0 ","list error", 0, 1);
remove_all(false);
delete _root;
_root=0;_nbitems=0; //reset memory used (no lost pointers)
}
/*!
Error report for list error inside DL_List class
the error function is used internally in the list class to report errors,
the function will generate a message based on the error code.
Then an exeption will be generated using the global booleng class instance. \n
tcarg: class | Dtype | item object in list
\par Example
to call error from inside an DL_List class
\code
Error("remove_all",ITER_GT_O);
\endcode
\param function string that generated this error
\param error code to generate a message for
*/
template <class Dtype>
void DL_List<Dtype>::Error(const char* function,Lerror a_error)
{
char buf[100];
strcpy(buf,"DL_List<Dtype>::");
strcat(buf,function);
switch (a_error)
{
case NO_MES: strcat(buf,""); break;
case EMPTY: strcat(buf,"list is empty"); break;
case ITER_GT_0: strcat(buf,"more then zero iter"); break;
case NO_LIST: strcat(buf,"no list attached"); break;
case SAME_LIST: strcat(buf,"same list not allowed"); break;
case AC_ITER_LIST_OTHER: strcat(buf,"iter not allowed on other list"); break;
default: strcat(buf,"unhandled error"); break;
}
throw Bool_Engine_Error(buf,"list error", 0, 1);
}
/*!
is list empty (contains items or not)? \n
class | Dtype | item object in list
\return returns true is list is empty else false
\par Example
too see if list is empty
\code
DL_List<int> _intlist; #create a list of integers
if (_intlist.Empty())
cout << "empty";
\endcode
*/
template <class Dtype>
bool DL_List<Dtype>::empty()
{
return(bool)(_nbitems==0);
}
/*!
number of items in list \n
class | Dtype | item object in list
\return return number of items in the list
\par Example
too see if list contains only one object
\code
DL_List <int> _intlist; #create a list of integers
if (_intlist.count() == 1)
cout << "one object in list";
\endcode
*/
template <class Dtype>
int DL_List<Dtype>::count()
{
return _nbitems;
}
/*!
remove all objects from the list\n
class | Dtype | item object in list
\note
The objects itself are not deleted, only removed from the list.
The user is responsible for memory management.
\note
The iterator level must be zero to be able to use this function,
else an error will be generated
\note
Use this function if an iterator is not needed to do more complex things.
This will save time, since the iterator does not have to be created.
\par Example
too insert integer a and b into list and remove_all directly
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
int b=345;
_intlist.insbegin(a);
_intlist.insbegin(b);
_intlist.remove_all();
\endcode
*/
template <class Dtype>
void DL_List<Dtype>::remove_all( bool deleteObject )
{
if (_iterlevel > 0 )
Error("remove_all()",ITER_GT_0);
Dtype* obj;
DL_Node<Dtype> *node;
for (int i=0; i<_nbitems; i++)
{
node = _root->_next;
_root->_next = node->_next;
if ( deleteObject == true )
{
obj=(Dtype*)(node->_item);
delete obj;
}
delete node;
}
_nbitems=0;_iterlevel=0; //reset memory used (no lost pointers)
_root->_prev=_root;
}
/*!
remove the object at the begin of the list (head).
\note
The object itself is not deleted, only removed from the list.
The user is responsible for memory management.
\note
The iterator level must be zero to be able to use this function, else an error will be generated
\note
The list must contain objects, else an error will be generated.
\note
Use this function if an iterator is not needed to do more complex things. This will save time, since the iterator does not
have to be created.
\par Example:
too insert integer a at begin of list and remove it directly.
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
_intlist.insbegin(a)
_intlist.removehead();
\endcode
*/
template <class Dtype>
void DL_List<Dtype>::removehead()
{
if (_iterlevel > 0 )
Error("removehead()",ITER_GT_0);
if(_nbitems==0)
Error("removehead()",EMPTY);
DL_Node<Dtype>* node=_root->_next;
node->_prev->_next = node->_next; // update forward link
node->_next->_prev = node->_prev; // update backward link
_nbitems--;
delete node; // delete list node
}
/*!
remove the object at the begin of the list (head).
\note
- The object itself is not deleted, only removed from the list.
The user is responsible for memory management.
- The iterator level must be zero to be able to use this function,
else an error will be generated
- The list must contain objects, else an error will be generated.
- Use this function if an iterator is not needed to do more complex things.
This will save time, since the iterator does not have to be created.
\par Example:
too insert integer a at end of list and remove it directly.
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
_intlist.insend(a)
_intlist.removetail();
\endcode
*/
template <class Dtype>
void DL_List<Dtype>::removetail()
{
if (_iterlevel > 0)
Error("removetail()",ITER_GT_0);
if (_nbitems==0)
Error("removehead()",EMPTY);
DL_Node<Dtype>* node=_root->_prev;
node->_prev->_next = node->_next; // update forward link
node->_next->_prev = node->_prev; // update backward link
_nbitems--;
delete node; // delete list node
}
/*!
insert the object given at the end of the list, after tail
\note
The iterator level must be zero to be able to use this function,
else an error will be generated
\note
Use this function if an iterator is not needed to do more complex things.
This will save time, since the iterator does not have to be created.
\par Example:
too insert integer a at end of list
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
_intlist.insend(a)
\endcode
\param newitem an object for which the template list was generated
*/
template <class Dtype>
DL_Node<Dtype>* DL_List<Dtype>::insend(Dtype newitem)
{
if (_iterlevel > 0)
Error("insend()",ITER_GT_0);
DL_Node<Dtype>* newnode = new DL_Node<Dtype>(newitem);
newnode ->_next = _root;
newnode ->_prev = _root->_prev;
_root->_prev->_next = newnode;
_root->_prev = newnode;
_nbitems++;
return newnode;
}
/*!
insert the object given at the begin of the list, before head
\note
The iterator level must be zero to be able to use this function,
else an error will be generated
\note
Use this function if an iterator is not needed to do more complex things.
This will save time, since the iterator does not have to be created.
\par Example:
too insert integer a at begin of list
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
_intlist.insbegin(a)
\endcode
\param newitem an object for which the template list was generated
*/
template <class Dtype>
DL_Node<Dtype>* DL_List<Dtype>::insbegin(Dtype newitem)
{
if (_iterlevel > 0)
Error("insbegin()",ITER_GT_0);
DL_Node<Dtype>* newnode = new DL_Node<Dtype>(newitem);
newnode ->_prev = _root;
newnode ->_next = _root->_next;
_root->_next->_prev = newnode;
_root->_next = newnode;
_nbitems++;
return newnode;
}
/*!
get head item
\return returns the object at the head of the list.
\par Example:
too insert integer a and b into list and make c be the value of b
which is at head of list|
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
int b=345;
int c;
_intlist.insbegin(a)
_intlist.insbegin(b)
c=_intlist.headitem()
\endcode
*/
template <class Dtype>
Dtype DL_List<Dtype>::headitem()
{
return _root->_next->_item;
}
/*!
get tail item
\return returns the object at the tail/end of the list.
\par Example:
too insert integer a and b into list and make c be the value of b which
is at the tail of list
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
int b=345;
int c;
_intlist.insbegin(a)
_intlist.insbegin(b)
c=_intlist.headitem()
\endcode
*/
template <class Dtype>
Dtype DL_List<Dtype>::tailitem()
{
return _root->_prev->_item;
}
/*!
* \note
The iterator level must be zero to be able to use this function, else an error will be generated
* \note The list may not be the same list as this list
* \param otherlist the list to take the items from
*/
template <class Dtype>
void DL_List<Dtype>::takeover(DL_List<Dtype>* otherlist)
{
if (otherlist==0)
Error("takeover(DL_List*)",NO_LIST);
// no iterators allowed on otherlist
if (otherlist->_iterlevel > 0)
Error("takeover(DL_List*)",AC_ITER_LIST_OTHER);
// otherlist not this list
else if (otherlist == this)
Error("takeover(DL_List*)",SAME_LIST);
if (otherlist->_nbitems == 0)
return;
//link other list into this list at the end
_root->_prev->_next=otherlist->_root->_next;
otherlist->_root->_next->_prev=_root->_prev;
otherlist->_root->_prev->_next=_root;
_root->_prev=otherlist->_root->_prev;
//empty other list
_nbitems+=otherlist->_nbitems;
otherlist->_nbitems=0;
otherlist->_root->_next=otherlist->_root;
otherlist->_root->_prev=otherlist->_root;
}
//=======================================================================
// implementation class DL_Iter
//=======================================================================
/*! \class DL_Iter
template iterator for any list/node type\n
This class is the base class to attach/instantiate an iterator on a double linked list. \n
DL_List The iterator is used to traverse and perform functions on the nodes of a list. \n
More then 1 iterator can be attached to a list. The list keeps track of the
number of iterators that are attached to it. \n
Depending on this certain operations are allowed are not. For instance a node can
only be deleted if there is only one iterator attached to the list. \n
class | Dtype | Object for traversing a DL_List of the same Dtype
// \par Example
to insert integer a and b into list and remove_all directly using an iterator
\code
DL_List<int>* a_list = new DL_List<int>(); // declaration and allocation
int a=123;
int b=345;
{
DL_Iter<int>* a_listiter=new DL_Iter<int>(a_list);
a_listiter->insbegin(a)
a_listiter->insbegin(b)
a_listiter->remove_all()
} //to destruct the iterator before the list is deleted
delete a_list; #delete it (must have no iterators attached to it)
\endcode
*/
/*!
Error report for list error inside DL_Iter class
the error function is used internally in the iterator class to report errors,
the function will generate a message based on the error code.
Then an exception will be generated using the global booleng class instance.|
\par Example
to call error from inside an DL_List class|
\code
Error("remove_all",ITER_GT_O);
\endcode
\param function: function string that generated this error
\param a_error: error code to generate a message for
*/
template <class Dtype>
void DL_Iter<Dtype>::Error(const char* function,Lerror a_error)
{
char buf[100];
strcpy(buf,"DL_Iter<Dtype>::");
strcat(buf,function);
switch (a_error)
{
case NO_MES: strcat(buf,""); break;
case NO_LIST: strcat(buf,"no list attached"); break;
case NO_LIST_OTHER: strcat(buf,"no list on other iter"); break;
case AC_ITER_LIST_OTHER: strcat(buf,"iter not allowed on other list"); break;
case SAME_LIST: strcat(buf,"same list not allowed"); break;
case NOT_SAME_LIST: strcat(buf,"must be same list"); break;
case ITER_GT_1: strcat(buf,"more then one iter"); break;
case ITER_HITROOT: strcat(buf,"iter at root"); break;
case NO_ITEM: strcat(buf,"no item at current"); break;
case NO_NEXT: strcat(buf,"no next after current"); break;
case NO_PREV: strcat(buf,"no prev before current"); break;
case EMPTY: strcat(buf,"list is empty"); break;
case NOT_ALLOW: strcat(buf,"not allowed"); break;
case ITER_NEG: strcat(buf,"to much iters deleted"); break;
default: strcat(buf,"unhandled error"); break;
}
throw Bool_Engine_Error(buf,"list error", 0, 1);
}
/*!
Construct an iterator object for a given list of type Dtype \n
tcarg: class | Dtype | list item object
\par Example
How to construct a list of type integer and an iterator for it:
\code
DL_List<int>* IntegerList;
IntegerList = new DL_List<int>();
DL_Iter<int>* a_listiter=new DL_Iter<int>(IntegerList);
\endcode
\param newlist: list for the iterator
*/
template <class Dtype>
DL_Iter<Dtype>:: DL_Iter(DL_List<Dtype>* newlist)
:_list(newlist), _current(RT)
{
_list->_iterlevel++; // add 1 to DL_Iters on list
}
/*!
This constructs an iterator for a list using an other iterator on the same list,
The new iterator will be pointing to the same list item as the other iterator.\n
tcarg: class | Dtype | list item object
\par Example
How to construct a list of type integer and a second iterator for it:|
\code
DL_List<int>* IntegerList;
IntegerList = new DL_List<int>();
DL_Iter<int>* a_listiter=new DL_Iter<int>(IntegerList);
DL_Iter<int>* a_secondlistiter=new DL_Iter<int>(a_listiter);
\endcode
\param otheriter other iterator on same list
*/
template <class Dtype>
DL_Iter<Dtype>:: DL_Iter(DL_Iter* otheriter)
{
if (otheriter->_current==0)
Error("DL_Iter(otheriter)",NO_LIST_OTHER);
_list=otheriter->_list;
_list->_iterlevel++; // add 1 to DL_Iters on List
_current=otheriter->_current;
}
/*!
This constructs an iterator for a list of a given type, the list does not have to exist.
Later on when a list is constructed,the iterator can be attached to it.
This way an iterator to a specific list can be made static to a class, and can be used
for several lists at the same time. \n
tcarg: class | Dtype | list item object
\par Example
How to construct an iterator, without having a list first.
This constructs an iterator for a list of the given type, but the list thus not yet exist.
\code
DL_Iter<int>* a_iter=new DL_Iter<int>();
DL_List<int>* IntegerList;
IntegerList = new DL_List<int>();
a_iter.Attach(IntegerList);
a_iter.insend(123);
a_iter.Detach();
\endcode
*/
template <class Dtype>
DL_Iter<Dtype>:: DL_Iter()
:_list(0), _current(0)
{
}
/*!
destruct an iterator for a list of a given type.
*/
template <class Dtype>
DL_Iter<Dtype>::~DL_Iter()
{
if (_current==0)
return;
_list->_iterlevel--; // decrease iterators
if (_list->_iterlevel < 0)
Error("~DL_Iter()",ITER_NEG);
}
/*!
This attaches an iterator to a list of a given type, the list must exist.
This way an iterator to a specific list can be made
static to a class, and can be used for several lists at the same time.\n
!tcarg: class | Dtype | list item object
\par Example
How to construct an iterator, without having a list first, and attach an iterator later:|
\code
DL_Iter<int>* a_iter=new DL_Iter<int>();
DL_List<int>* IntegerList;
IntegerList = new DL_List<int>();
a_iter.Attach(IntegerList);
a_iter.insend(123);
a_iter.Detach();
\endcode
\param newlist the list to attached the iterator to
*/
template <class Dtype>
void DL_Iter<Dtype>::Attach(DL_List<Dtype>* newlist)
{
if (_current!=0)
Error("Attach(list)",NOT_ALLOW);
_list=newlist;
_current=HD;
_list->_iterlevel++; // add 1 to DL_Iters on list
}
/*!
This detaches an iterator from a list of a given type, the list must exist.
This way an iterator to a specific list can be made static to a class,
and can be used for several lists at the same time. \n
!tcarg: class | Dtype | list item object
\par Example:
How to construct an iterator, without having a list first, and attach an iterator later:
\code
DL_Iter<int>* a_iter=new DL_Iter<int>();
DL_List<int>* IntegerList;
IntegerList = new DL_List<int>();
a_iter.Attach(IntegerList);
a_iter.insend(123);
a_iter.Detach();
\endcode
\param newlist: the list to attached the iterator to
*/
template <class Dtype>
void DL_Iter<Dtype>::Detach()
{
if (_current==0)
Error("Attach()",NO_LIST);
_list->_iterlevel--; // subtract 1 from DL_Iters on list
_list=0;
_current=0;
}
/*
// copy pointers to items from other list
template <class Dtype> void DL_Iter<Dtype>::merge(DL_List<Dtype>* otherlist)
{
DL_Node* node=otherlist->HD; //can be 0 if empty
for(int i=0; i<otherlist->NB; i++)
{
insend(node->new_item); // insert item at end
node=node->_next; // next item of otherlist
}
}
*/
/*
//call Dtype::mfp for each item
template <class Dtype>
void DL_Iter<Dtype>::foreach_mf(void (Dtype::*mfp)())
{
DL_Node<Dtype>* node=HD; //can be 0 if empty
for(int i=0; i< NB; i++)
{
((node->_item).*mfp)();
node=node->_next;
}
}
*/
/*! call given function for each item*/
template <class Dtype>
void DL_Iter<Dtype>::foreach_f(void (*fp) (Dtype n) )
{
DL_Node<Dtype>* node=HD; //can be 0 if empty
for(int i=0; i< NB; i++)
{
fp (node->_item);
node=node->_next;
}
}
/*!
to move all objects in a list to the list of the iterator.
\note
The iterator level must be one to be able to use this function,
else an error will be generated
\note
The list may not be the same list as the iterator list
\par Example
to take over all items in _intlist|
\code
DL_List<int> _intlist; #create a list of integers
DL_List<int> _intlist2; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter2=new DL_Iter<int>(&_intlist2);
_intlist->insend(a) // insert at end
a_listiter2->takeover(_intlist)
\endcode
\param otherlist the list to take the items from
*/
template <class Dtype>
void DL_Iter<Dtype>::takeover(DL_List<Dtype>* otherlist)
{
if (_current==0)
Error("takeover(DL_List*)",NO_LIST);
// no iterators allowed on otherlist
if (otherlist->_iterlevel > 0)
Error("takeover(DL_List*)",AC_ITER_LIST_OTHER);
// otherlist not this list
else if (otherlist == _list)
Error("takeover(DL_List*)",SAME_LIST);
if (otherlist->_nbitems == 0)
return;
//link other list into this list at the end
TL->_next=otherlist->_root->_next;
otherlist->_root->_next->_prev=TL;
otherlist->_root->_prev->_next=RT;
TL=otherlist->_root->_prev;
//empty other list
NB+=otherlist->_nbitems;
otherlist->_nbitems=0;
otherlist->_root->_next=otherlist->_root;
otherlist->_root->_prev=otherlist->_root;
}
/*!
to move all objects in a list (using iterator of that list) to the list of the iterator.
\note
The iterator level for both iterators must be one to be able to use this function,
\note
else an error will be generated
\note
The list may not be the same list as the iterator list
\par Example
to take over all items in a_listiter1 it's list|
\code
DL_List<int> _intlist; #create a list of integers
DL_List<int> _intlist2; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter1=new DL_Iter<int>(&_intlist);
DL_Iter<int>* a_listiter2=new DL_Iter<int>(&_intlist2);
a_listiter1->insend(a) // insert at end
a_listiter2->takeover(a_listiter1)
\\!to move all objects in a list (using iterator of that list) to the list of the iterator
\endcode
\param otheriter: the iterator to take the items from
*/
template <class Dtype>
void DL_Iter<Dtype>::takeover(DL_Iter* otheriter)
{
if (otheriter->_current==0)
Error(" DL_Iter",NO_LIST_OTHER);
if (_current==0)
Error(" DL_Iter",NO_LIST);
// only one iterator allowed on other list?
if (otheriter->_list->_iterlevel > 1)
Error("takeover(DL_Iter*)",AC_ITER_LIST_OTHER);
// otherlist not this list?
else if (otheriter->_list == _list)
Error("takeover(DL_Iter*)",SAME_LIST);
if (otheriter->NB == 0)
return;
//link other list into this list at the end
TL->_next=otheriter->HD;
otheriter->HD->_prev=TL;
otheriter->TL->_next=RT;
TL=otheriter->TL;
//empty other iter & list
NB+=otheriter->NB;
otheriter->NB=0;
otheriter->HD=otheriter->RT;
otheriter->TL=otheriter->RT;
otheriter->_current=otheriter->RT;
}
/*!
to move maxcount objects in a list (using iterator of that list)
to the list of the iterator.
\note The iterator level for both iterators must be one to be able to use this function,
else an error will be generated
\note The list may not be the same list as the iterator list
\note If less then maxcount objects are available in the source iterator,
all of them are taken and no error will accur
\par Example
to take over 1 item from a_listiter1 it's list
\code
DL_List<int> _intlist; #create a list of integers
DL_List<int> _intlist2; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter1=new DL_Iter<int>(&_intlist);
DL_Iter<int>* a_listiter2=new DL_Iter<int>(&_intlist2);
a_listiter1->insend(a) // insert at end
a_listiter2->takeover(a_listiter1,1);
//! to move maxcount objects in a list (using iterator of that list) to the list of the iterator
\endcode
\param otheriter the iterator to take the items from
\param maxcount maximum number of objects to take over
*/
template <class Dtype>
void DL_Iter<Dtype>::takeover(DL_Iter* otheriter, int maxcount)
{
if (otheriter->_current==0)
Error("takeover(DL_Iter*,int)",NO_LIST_OTHER);
if (_current==0)
Error("takeover(DL_Iter*,int)",NO_LIST);
if (otheriter->_list->_iterlevel > 1)
Error("takeover(DL_Iter*,int)",AC_ITER_LIST_OTHER);
else if (otheriter->_list == _list)
Error("takeover(DL_Iter*,int)",SAME_LIST);
if (maxcount<0)
Error("takeover(DL_Iter*,int), maxcount < 0",NO_MES);
if (otheriter->NB == 0)
return;
if (otheriter->NB <= maxcount)
{ //take it all
//link other list into this list at the end
TL->_next=otheriter->HD;
otheriter->HD->_prev=TL;
otheriter->TL->_next=RT;
TL=otheriter->TL;
//empty other iter & list
NB+=otheriter->NB;
otheriter->NB=0;
otheriter->HD=otheriter->RT;
otheriter->TL=otheriter->RT;
otheriter->_current=otheriter->RT;
}
else
{ //take maxcount elements from otheriter
//set cursor in otherlist to element maxcount
DL_Node<Dtype>* node;
if (NB/2 < maxcount)
{ // this is faster (1st half)
node=otheriter->HD;
for(int i=1; i<maxcount; i++)
node=node->_next;
}
else
{ // no, this is faster (2nd half)
node=otheriter->TL;
for(int i=NB; i>maxcount+1; i--)
node=node->_prev;
}
// link this->tail to other->head
if (NB>0)
{
TL->_next=otheriter->HD;
otheriter->HD->_prev=TL;
}
else // target is empty
{
HD=otheriter->HD;
otheriter->HD->_prev=RT;
}
// set other root to node-> next (after last to copy)
otheriter->HD=node->_next;
otheriter->HD->_prev=otheriter->RT;
// set this->tail to other->item()->prev (last element to be copied)
TL=node;
node->_next=RT;
// still need to update element counter
NB+=maxcount;
// update other list
otheriter->NB-=maxcount;
otheriter->_current=otheriter->HD; // other->current is moved to this!
}
}
/*!
put the iterator root object before the current iterator position in the list.
The current object will become the new head of the list.
\note The iterator level must be one to be able to use this function,
else an error will be generated
\par Example
move the root object to make the new head the old tail object|
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->insend(2345);
a_listiter->insend(3456);
a_listiter->totail();
a_listiter->reset_head();
a_listiter->tohead(); //the new head will be at object 3456
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::reset_head()
{
if (_current==0)
Error("reset_head()",NO_LIST);
if (_list->_iterlevel > 1 )
Error("reset_head()",ITER_GT_1);
if(_current==RT)
Error("reset head()",ITER_HITROOT);
//link out RT
HD->_prev=TL;
TL->_next=HD;
//link in RT before current
HD=_current;
TL=_current->_prev;
TL->_next=RT;
HD->_prev=RT;
}
/*!
put the iterator root object after the current iterator position in the list.
The current object will become the new tail of the list.
\note
The iterator level must be one to be able to use this function,
else an error will be generated
\par Example
move the root object to make the new tail the old head object
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->insend(2345);
a_listiter->insend(3456);
a_listiter->tohead();
a_listiter->reset_tail();
a_listiter->totail(); //the new tail will be at object 1234
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::reset_tail()
{
if (_current==0)
Error("reset_tail()",NO_LIST);
if (_list->_iterlevel > 1 )
Error("reset_tail()",ITER_GT_1);
if(_current==RT)
Error("reset head()",ITER_HITROOT);
//link out RT
HD->_prev=TL;
TL->_next=HD;
//link in RT after current
TL=_current;
HD=_current->_next;
HD->_prev=RT;
TL->_next=RT;
}
/*!
is list empty (contains items or not)?
\return returns true is list is empty else false
\par exmaple:
too see if list is empty
\code
DL_List<int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
if (a_listiter->Empty())
cout << "empty"
\endcode
*/
template <class Dtype>
bool DL_Iter<Dtype>::empty()
{
if (_current==0)
Error("empty()",NO_LIST);
return(bool)(NB==0);
}
/*!
is the iterator at the root of the list.
\note Traversing the list in a certain direction using a while loop,
the end can be tested with this function.
\return returns true if the iterator is at the root of the list (after the last/tail/head object), else false.
\par example:
to traverse in both directions|
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->tohead();
//traverse forwards
while ( ! a_listiter->hitroot())
{
cout << "The item =" << a_listiter->item();
a_listiter++; //goto next object
}
a_listiter->totail();
//traverse backwards
while ( ! a_listiter->hitroot())
{
cout << "The item =" << a_listiter->item();
a_listiter--; //goto next object
}
\endcode
*/
template <class Dtype>
bool DL_Iter<Dtype>::hitroot()
{
if (_current==0)
Error("hitroot()",NO_LIST);
return(bool)(_current == RT);
}
/*!
is the iterator at the head of the list.
\return returns true if the iterator is at the head object of the list, else false.
\par exmaple:
too see the object at the head
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->tohead();
if (a_listiter->athead())
cout << "at the head The item =" << a_listiter->item();
\endcode
*/
template <class Dtype>
bool DL_Iter<Dtype>::athead()
{
if (_current==0)
Error("athead()",NO_LIST);
return(bool)(_current == HD);
}
/*!
is the iterator at the tail of the list.
\return returns true if the iterator is at the tail object of the list,
else false.
\par Example
too see the object at the tail|
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->totail();
if (a_listiter->attail())
cout << "at the tail The item =" << a_listiter->item();
\endcode
*/
template <class Dtype>
bool DL_Iter<Dtype>::attail()
{
if (_current==0)
Error("attail()",NO_LIST);
return(bool)(_current == TL);
}
/*!
does the iterator/list contain the given object
\return returns true if the iterator/list contains the given object in the list, else false.
\par Example
too see if the object is already in the list
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
if (a_listiter->has(1234))
cout << "yes it does";
\endcode
\param otheritem item to search for
*/
template <class Dtype>
bool DL_Iter<Dtype>::has(Dtype otheritem)
{
if (_current==0)
Error("has()",NO_LIST);
DL_Node<Dtype>* node=HD; //can be 0 if empty
for(int i=0; i<NB; i++)
{ if (node->_item == otheritem)
return true;
node=node->_next;
}
return false;
}
/*!
number of items in list
\return number of items in the list
\par Example:
to see if a list contains only one object
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
if (a_listiter->count() == 1)
cout << "one object in list";
\endcode
*/
template <class Dtype>
int DL_Iter<Dtype>::count()
{
if (_current==0)
Error("count()",NO_LIST);
return NB;
}
/*!
go to first item, if list is empty goto hite
\par Example
set iterator to head of list
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->tohead();
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::tohead()
{
if (_current==0)
Error("tohead()",NO_LIST);
_current=HD;
}
/*!
go to last item, if list is empty goto hite
\par Example
set iterator to tail of list
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->totail();
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::totail()
{
if (_current==0)
Error("totail()",NO_LIST);
_current=TL;
}
/*!
set the iterator position to the root (empty dummy) object in the list.
\par Example
set iterator to root of list and iterate
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->toroot();
while (a_listiter->iterate())
cout << a_listiter->item();
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::toroot()
{
if (_current==0)
Error("toroot()",NO_LIST);
_current=RT;
}
/*!
set the iterator position to next object in the list ( can be the root also)(prefix).
\par Example
how to iterate backwards
\code
DL_List <int> _intlist; //create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->tohead();
while (!a_listiter->hitroot())
{
cout << a_listiter->item();
_listiter++;
}
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::operator++(void)
{
if (_current==0)
Error("operator++()",NO_LIST);
_current=_current->_next;
}
/*!
set the iterator position to next object in the list ( can be the root also)(prefix).
\par Example
how to iterate backwards
\code
DL_List <int> _intlist; //create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->tohead();
while (!a_listiter->hitroot())
{
cout << a_listiter->item();
++_listiter;
}
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::operator++(int)
{
if (_current==0)
Error("operator++(int)",NO_LIST);
_current=_current->_next;
}
/*!
set the iterator position to previous object in the list ( can be the root also)(prefix).
\par Example
how to iterate backwards
\code
DL_List <int> _intlist; //create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->totail();
while (!a_listiter->hitroot())
{
cout << a_listiter->item();
_listiter--;
}
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::operator--(void)
{
if (_current==0)
Error("operator++()",NO_LIST);
_current=_current->_prev;
}
/*!
set the iterator position to previous object in the list ( can be the root also)(prefix).
\par Example
how to iterate backwards
\code
DL_List <int> _intlist; //create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->totail();
while (!a_listiter->hitroot())
{
cout << a_listiter->item();
--_listiter;
}
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::operator--(int)
{
if (_current==0)
Error("operator++(int)",NO_LIST);
_current=_current->_prev;
}
/*!
set the iterator position n objects in the next direction ( can be the root also).
\par Example:
how to set iterator 2 items forward
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->tohead();
a_listiter>>2;//at root now
\endcode
\param n go n places forward
*/
template <class Dtype>
void DL_Iter<Dtype>::operator>>(int n)
{
if (_current==0)
Error("operator>>()",NO_LIST);
for(int i=0; i<n; i++)
_current=_current->_next;
}
/*!
set the iterator position n objects in the previous direction ( can be the root also).
\par Example:
how to set iterator 2 items backwards
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->totail();
a_listiter<<2;//at root now
\endcode
\param n go n places back
*/
template <class Dtype>
void DL_Iter<Dtype>::operator<<(int n)
{
if (_current==0)
Error("operator<<()",NO_LIST);
for(int i=0; i<n; i++)
_current=_current->_prev;
}
/*!
put the iterator at the position of the given object in the list.
\return returns true if the object was in the list, else false
\par Example:
goto element 2345
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->insend(2345);
a_listiter->insend(3456);
a_listiter->toitem(2345); template <class Dtype>
\endcode
*/
template <class Dtype>
bool DL_Iter<Dtype>::toitem(Dtype item)
{
if (_current==0)
Error("toitem(item)",NO_LIST);
DL_Node<Dtype>* node=HD; //can be 0 if empty
for(int i=0; i<NB; i++)
{ if (node->_item == item)
{
_current = node;
return true;
}
node=node->_next;
}
return false;
}
/*!
put the iterator at the same position as the given iterator in the list.
\par Example:
goto element 2345 and let a_listiter2 point to the same position
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
DL_Iter<int>* a_listiter2=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->insend(2345);
a_listiter->insend(3456);
a_listiter->toitem(2345);
a_listiter2->toiter(a_listiter2);
\endcode
\param otheriter other iterator to let this iterator point to.
*/
template <class Dtype>
void DL_Iter<Dtype>::toiter(DL_Iter *otheriter)
{
if (otheriter->_current==0)
Error("toiter(otheriter)",NO_LIST);
// both iters must have the same list
if (_list != otheriter->_list)
Error("toiter(otheriter)",NOT_SAME_LIST);
_current = otheriter->_current;
}
/*!
put the iterator at the position of the given object in the list.
\note DO NOT use this function. Normally you will not be able to address the nodes in a list.
\return returns true if the node was in the list, else false
\param othernode a node to let this iterator point to.
*/
template <class Dtype>
bool DL_Iter<Dtype>::tonode(DL_Node<Dtype> *othernode)
{
DL_Node<Dtype>* node=HD; //can be 0 if empty //node is a temporary cursor
for(int i=0; i<NB; i++)
{ if (node == othernode)
{
_current = othernode;
return true;
}
node=node->_next;
}
return false;
}
/*!
advance the iterator one position in the next direction in the list.
\return returns true if not at the end/root of the list else false.
\note This function combines iteration and testing for the end of
the list in one.
\note Therefore we do not have to advance the iterator ourselves.
\note
The iterator is first put to the next object, before testing for the end of the list. |
This is why we need to start at the root element in general usage.
\par Example
iterate through all the items in a list
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->insend(2345);
a_listiter->insend(3456);
a_listiter->tobegin(2345);
while (a_listiter->iterate())
{ cout << a_listiter->item(); }
\endcode
*/
template <class Dtype>
bool DL_Iter<Dtype>::iterate(void)
{
if (_current==0)
Error("iterate()",NO_LIST);
_current=_current->_next;
if (_current==RT)
return false;
return true;
}
/*!
To get the item at the current iterator position
\return returns the object where the iterator is pointing to at the moment.
\note
If the iterator is at the root of the list an error will be generated,
since there is no item there.
\par Example:
get the element at the head of the list|
\code
DL_List <int> _intlist; //create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->tohead();
int theitem=a_listiter->item();
\endcode
*/
template <class Dtype>
Dtype DL_Iter<Dtype>::item()
{
if (_current==0)
Error("item()",NO_LIST);
if (_current==RT)
Error("item()",NO_ITEM);
return _current->_item;
}
//! get the node at iterater position
template <class Dtype>
DL_Node<Dtype>* DL_Iter<Dtype>::node()
{
if (_current==0)
Error("item()",NO_LIST);
if (_current==RT)
Error("item()",NO_ITEM);
return _current;
}
/*!
set the iterator position to next object in the list ( can be the root also).
\note Use this function inside a new class derived from DL_Iter.
*/
template <class Dtype>
void DL_Iter<Dtype>::next()
{
if (_current==0)
Error("item()",NO_LIST);
_current=_current->_next;
}
/*!
set the iterator position to next object in the list, if this would be the root object,
then set the iterator at the head object
\par Example
cycle the list twice
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->insend(2345);
a_listiter->tohead();
int count=2*a_listiter->count();
while (count)
{
cout << a_listiter->item();
next_wrap();
count--;
}
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::next_wrap()
{
if (_current==0)
Error("item()",NO_LIST);
_current=_current->_next;
if (_current==RT)
_current=_current->_next;
}
/*!
set the iterator position to previous object in the list ( can be the root also).
\note Use this function inside a new class derived from DL_Iter.
*/
template <class Dtype>
void DL_Iter<Dtype>::prev()
{
if (_current==0)
Error("item()",NO_LIST);
_current=_current->_prev;
}
/*!
set the iterator position to previous object in the list, if this would be the root object,
then set the iterator at the tail object
\par Example
cycle the list twice
\code
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(1234);
a_listiter->insend(2345);
a_listiter->totail();
int count=2*a_listiter->count();
while (count)
{
cout << a_listiter->item();
prev_wrap();
count--;
}
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::prev_wrap()
{
if (_current==0)
Error("item()",NO_LIST);
_current=_current->_prev;
if (_current==RT)
_current=_current->_prev;
}
template <class Dtype>
void DL_Iter<Dtype>::remove_all()
{
if (_current==0)
Error("remove_all()",NO_LIST);
if (_list->_iterlevel > 1 )
Error("remove_all()",ITER_GT_1);
_list->_iterlevel--;
_list->remove_all();
_list->_iterlevel++;
_current=RT;
}
/*!
remove object at current iterator position from the list.
\note The object itself is not deleted, only removed from the list. The user is responsible for memory management.
\note The iterator level must be one to be able to use this function, else an error will be generated
\note The list must contain an object at the current iterator position, else an error will be generated.
\par Example:
to insert integer a at begin of list and remove it directly
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insbegin(a);
a_listiter->tohead();
a_listiter->remove();
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::remove()
{
if (_current==0)
Error("remove()",NO_LIST);
if (_list->_iterlevel > 1 )
Error("remove()",ITER_GT_1);
if (_current==RT)
Error("remove()",ITER_HITROOT);
DL_Node<Dtype>* node=_current;
_current=_current->_next;
node->_prev->_next = node->_next; // update forward link
node->_next->_prev = node->_prev; // update backward link
NB--;
delete node; // delete list node
}
/*!
remove the object at the begin of the list using an iterator
\note The object itself is not deleted, only removed from the list. The user is responsible for memory management.
\note The iterator level must be one to be able to use this function, else an error will be generated
\note The list must contain objects, else an error will be generated.
\note Use this function if an iterator is needed to do more complex things. Else use the list member functions directly.
\par Example:
to insert integer a at begin of list and remove it directly|
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insbegin(a);
a_listiter->removehead();
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::removehead()
{
if (_current==0)
Error("removehead()",NO_LIST);
if (_list->_iterlevel > 1 )
Error("removehead()",ITER_GT_1);
if(NB==0)
Error("removehead()",EMPTY);
if (_current==HD)
_current=_current->_next;
_list->_iterlevel--;
_list->removehead();
_list->_iterlevel++;
}
/*!
//remove the object at the end of the list using an iterator
\note The object itself is not deleted, only removed from the list. The user is responsible for memory management.
\note The iterator level must be one to be able to use this function, else an error will be generated
\note The list must contain objects, else an error will be generated.
\note Use this function if an iterator is needed to do more complex things. Else use the list member functions directly.
\par Example:
to insert integer a at end of list and remove it directly
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(a);
a_listiter->removetail();
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::removetail()
{
if (_current==0)
Error("removetail()",NO_LIST);
if (_list->_iterlevel > 1 )
Error("removetail()",ITER_GT_1);
if (NB==0)
Error("removehead()",EMPTY);
if (_current==TL)
_current=_current->_prev;
_list->_iterlevel--;
_list->removetail();
_list->_iterlevel++;
}
/*!
insert the object given at the end of the list
\note The iterator level must be one to be able to use this function, else an error will be generated
\note Use this function if an iterator is needed to do more complex things. Else use the list member functions directly.
\par Example:
to insert integer a at end of list|
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(a);
\endcode
*/
template <class Dtype>
DL_Node<Dtype>* DL_Iter<Dtype>::insend(Dtype newitem)
{
if (_current==0)
Error("insend()",NO_LIST);
if (_list->_iterlevel > 1)
Error("insend()",ITER_GT_1);
_list->_iterlevel--;
DL_Node<Dtype>* ret = _list->insend(newitem);
_list->_iterlevel++;
return ret;
}
/*!
insert the object given at the begin of the list
\note The iterator level must be one to be able to use this function, else an error will be generated
\note Use this function if an iterator is needed to do more complex things. Else use the list member functions directly.
\par Example:
to insert integer a at begin of list|
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insbegin(a);
\endcode
\param newitem an object for which the template list/iterator was generated
*/
template <class Dtype>
DL_Node<Dtype>* DL_Iter<Dtype>::insbegin(Dtype newitem)
{
if (_current==0)
Error("insbegin()",NO_LIST);
if (_list->_iterlevel > 1)
Error("insbegin()",ITER_GT_1);
_list->_iterlevel--;
DL_Node<Dtype>* ret = _list->insbegin(newitem);
_list->_iterlevel++;
return ret;
}
/*!
//insert the object given before the current position of the iterator in list
\note The iterator level must be one to be able to use this function, else an error will be generated
\par Example:
to insert integer before the iterator position in the list|
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->totail();
a_listiter->insbefore(a); // insert before tail
\endcode
\param newitem an object for which the template list/iterator was generated
*/
template <class Dtype>
DL_Node<Dtype>* DL_Iter<Dtype>::insbefore(Dtype newitem)
{
if (_current==0)
Error("insbefore()",NO_LIST);
if (_list->_iterlevel > 1)
Error("insbefore()",ITER_GT_1);
DL_Node<Dtype>* newnode = new DL_Node<Dtype>(newitem);
newnode ->_next = _current;
_current->_prev->_next = newnode;
newnode ->_prev = _current->_prev;
_current->_prev = newnode;
NB++;
return newnode;
}
/*!
insert the object given after the current position of the iterator in list
\note The iterator level must be one to be able to use this function, else an error will be generated
\par Example: to insert integer after the iterator position in the list|
\code
DL_List<int> _intlist; #create a list of integers
int a=123;
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->tohead();
a_listiter->insafter(a); // insert after head
\endcode
\param newitem an object for which the template list/iterator was generated
*/
template <class Dtype>
DL_Node<Dtype>* DL_Iter<Dtype>::insafter(Dtype newitem)
{
if (_current==0)
Error("insafter()",NO_LIST);
if (_list->_iterlevel > 1)
Error("insafter()",ITER_GT_1);
DL_Node<Dtype>* newnode = new DL_Node<Dtype>(newitem);
newnode ->_next = _current->_next;
newnode ->_prev = _current;
_current->_next->_prev = newnode;
_current->_next = newnode;
NB++;
return newnode;
}
/*!
sort all items in the list according to the compare function.
when items need to be swapped to reach the right order the swap function will be called also.
\note There are no restrictions on the internal decision in the compare function when to return -1,0,1.
\note The swap function can be used to change items when they are swapped.
fcmp (function, fcmp)
\verbatim
Declaration: int (*fcmp) (Dtype,Dtype)
compare function pointer, the function takes two objects in the list. It must return -1, 0, 1, to sort the list in upgoing
order the function should return:
-1 is returned if the first object is bigger then the second.
0 is returned if the objects are equal.
1 is returned if the first object is smaller then the second.
To sort the list in downgoing order:
1 is returned if the first object is bigger then the second.
0 is returned if the objects are equal.
-1 is returned if the first object is smaller then the second.
fswap (function, fswap)
Declaration: void (*fswap) (Dtype,Dtype)
swap function pointer, the function takes two objects in the list. It will be called when the objects are swapped to
reach the right order. If it is NULL, it will not be called.
\endverbatim
\par Example: sort the list in upgoing order using cocktailsort and the function numbersorter|
\code
int numbersorter(int a,int b)
{
if(a < b) return(1);
else
if(a == b) return(0);
return(-1);
}
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(2345);
a_listiter->insend(3456);
a_listiter->insend(1234);
a_listiter->cocktailsort(numbersorter,NULL);
\endcode
\param fcmp sortfunction
\param fswap swapfunction
*/
template <class Dtype>
int DL_Iter<Dtype>::cocktailsort(int (*fcmp) (Dtype, Dtype), bool (*fswap)(Dtype, Dtype))
{
if (_current==0)
Error("cocktailsort()",NO_LIST);
if (NB <= 1)
return 0;
DL_Node<Dtype>* cursor;
Dtype swap;
int swapResult = 0;
// boven/ondergrens setten
DL_Node<Dtype> *bg = TL, *bgold = TL;
DL_Node<Dtype> *og = HD, *ogold = HD;
bool swapped = true;
// while swaping is done & lowerborder upperborder don't touch
while (swapped && (og!=bg))
{
swapped = false;
// BUBBELSLAG lowerborder--->> upperborder
cursor=og;
while(!(cursor == bgold))
{
// (current.next < current)?
if( fcmp(cursor->_next->_item, cursor->_item)==1)
{
// user function
if ( fswap != NULL )
if ( fswap(cursor->_item, cursor->_next->_item) )
swapResult++;
// update swap-flag en upperborder
swapped = true;
bg = cursor;
// swap the items of the nodes
swap = cursor->_item;
cursor->_item = cursor->_next->_item;
cursor->_next->_item = swap;
}
cursor=cursor->_next;
}// end bubbelslag
bgold = bg;
// BRICKSLAG lowerborder <<---upperborder
cursor=bg;
while(!(cursor == ogold))
{
// (current < current.next)?
if( fcmp(cursor->_item, cursor->_prev->_item)==1)
{
// user function
if ( fswap != NULL )
if ( fswap(cursor->_item, cursor->_prev->_item) )
swapResult++;
// update swap-flag and lowerborder
swapped = true;
og = cursor;
// swap de items van de nodes
swap = cursor->_item;
cursor->_item = cursor->_prev->_item;
cursor->_prev->_item = swap;
}
cursor=cursor->_prev;
}// end brickslag
ogold = og;
}// end while(ongesorteerd)
return swapResult;
}
/*!
sort all items in the list according to the compare function.
\note
There are no restrictions on the internal decision in the compare function when to return -1,0,1.
\note
For the mergesort function the objects will be swapped when the return value is -1.
\note
\verbatim
fcmp (function, fcmp)
Declaration: int (*fcmp) (Dtype,Dtype)
compare function pointer, the function takes two objects in the list. It must return -1, 0, 1, to sort the list in upgoing
order the function should return:
-1 is returned if the first object is bigger then the second.
0 is returned if the objects are equal.
1 is returned if the first object is smaller then the second.
To sort the list in downgoing order:
1 is returned if the first object is bigger then the second.
0 is returned if the objects are equal.
-1 is returned if the first object is smaller then the second.
\endverbatim
!tcarg: class | Dtype | list item object
\par example
sort the list in upgoing order using mergesort and the function numbersorter|
\code
int numbersorter(int a,int b)
{
if(a < b) return(1);
else
if(a == b) return(0);
return(-1);
}
DL_List <int> _intlist; #create a list of integers
DL_Iter<int>* a_listiter=new DL_Iter<int>(&_intlist);
a_listiter->insend(2345);
a_listiter->insend(3456);
a_listiter->insend(1234);
a_listiter->mergesort(numbersorter);
\endcode
*/
template <class Dtype>
void DL_Iter<Dtype>::mergesort(int (*fcmp) (Dtype, Dtype))
{
if (_current==0)
Error("mergesort()",NO_LIST);
mergesort_rec(fcmp, RT, NB);
}
template <class Dtype>
void DL_Iter<Dtype>::mergesort_rec(int (*fcmp)(Dtype,Dtype), DL_Node<Dtype> *RT1, int n1)
{
if (n1 > 1) //one element left then stop
{
DL_Node<Dtype> RT2;
int n2;
RT2._prev=RT1->_prev;
RT2._next=RT1->_next;
// goto middle
n2=n1;n1>>=1;n2-=n1;
for (int i=0; i <n1;i++)
RT2._next=RT2._next->_next;
//RT2 is at half
RT1->_prev->_next=&RT2;
RT2._prev=RT1->_prev;
RT1->_prev=RT2._next->_prev;
RT2._next->_prev->_next=RT1;
mergesort_rec(fcmp,RT1,n1);
mergesort_rec(fcmp,&RT2,n2);
mergetwo(fcmp,RT1,&RT2);
}
}
template <class Dtype>
void DL_Iter<Dtype>::mergetwo(int (*fcmp)(Dtype,Dtype), DL_Node<Dtype> *RT1,DL_Node<Dtype> *RT2)
{
DL_Node<Dtype> *c,*a,*b;
a=RT1->_next;b=RT2->_next;
c=RT1;
do
{
if (fcmp(a->_item , b->_item) > -1)
{ c->_next=a;a->_prev=c;c=a;a=a->_next;}
else
{ c->_next=b;b->_prev=c;c=b;b=b->_next;}
if (a == RT1)
{ c->_next=
b;b->_prev=c; //connect list b to the list made sofar
RT1->_prev=RT2->_prev;
RT1->_prev->_next=RT1;
break;
}
if (b == RT2)
{ c->_next=a;a->_prev=c; //connect list a to the list made sofar
break;
}
}
while (true);
}
//=======================================================================
// implementation class DL_StackIter
//=======================================================================
/*! \class DL_StackIter
* template class DL_StackIter class for stack iterator on DL_List
* template stack iterator for any list/node type \n
* This class is the base class to attach/instantiate a stack iterator on a double linked list
* DL_List. The stack iterator is used to push and pop objects
* to and from the beginning of a list.
* class | Dtype | Object for traversing a DL_List of the same Dtype
*\par Example
How to work with a stack iterator for a list of type integer \n
to push a and b, pop a into list and remove_all directly using a stack iterator
*
*\code DL_List<int>* a_list = new DL_List<int>();# declaration and allocation
*
* int a=123;
*
* int b=345;
*
* {
*
* DL_StackIter<int>* a_listiter=new DL_StackIter<int>(a_list);
*
* a_listiter->push(a)
*
* a_listiter->push(b)
*
* a_listiter->pop()
*
* a_listiter->remove_all()
*
* } //to destruct the iterator before the list is deleted
*
* delete a_list; #delete it (must have no iterators attached to it)
*\endcode
*/
// constructor
template <class Dtype>
DL_StackIter<Dtype>::DL_StackIter(DL_List<Dtype> *newlist)
:DL_Iter<Dtype>(newlist) // initialiseer BaseIter
{}
// destructor
template <class Dtype>
DL_StackIter<Dtype>::~DL_StackIter()
{
}
// plaats nieuw item op stack
template <class Dtype>
void DL_StackIter<Dtype>::push(Dtype newitem)
{
DL_Iter<Dtype>::insbegin(newitem);
}
// remove current item
template <class Dtype>
void DL_StackIter<Dtype>::remove_all()
{
DL_Iter<Dtype>::remove_all();
}
// is stack leeg?
template <class Dtype>
bool DL_StackIter<Dtype>::empty()
{
return DL_Iter<Dtype>::empty();
}
// aantal items op stack
template <class Dtype>
int DL_StackIter<Dtype>::count()
{
return DL_Iter<Dtype>::count();
}
// haal bovenste item van stack
template <class Dtype>
Dtype DL_StackIter<Dtype>::pop()
{
if(DL_Iter<Dtype>::empty())
this->Error("pop()",EMPTY);
DL_Iter<Dtype>::tohead();
Dtype temp = DL_Iter<Dtype>::item();
DL_Iter<Dtype>::removehead();
return temp;
}
//=======================================================================
// implementation class DL_SortIter
//=======================================================================
/*! \class DL_SortIter
* template class DL_SortIter
* class for sort iterator on DL_List
* template sort iterator for any list/node type
* This class is a derived class to attach/instantiate a sorted iterator on a double linked list
* DL_List. The iterator is used to insert items in sorted order into a list.
//!tcarg: class | Dtype | Object for traversing a DL_List of the same Dtype
*/
// constructor
template <class DType>
DL_SortIter<DType>::DL_SortIter(DL_List<DType>* nw_list, int (*new_func)(DType ,DType ))
:DL_Iter<DType>(nw_list), comparef(new_func)
{}
// destructor
template <class DType>
DL_SortIter<DType>::~DL_SortIter()
{}
// general function to insert item
template <class DType>
void DL_SortIter<DType>::insert(DType new_item)
{
DL_Node<DType>* cursor=this->_current; //can be 0 if empty //node is a temporary cursor
// if list is empty directly insert
if (DL_Iter<DType>::empty())
{
DL_Iter<DType>::insend(new_item);
}
else
{
// put new item left of item
DL_Iter<DType>::tohead();
while(!DL_Iter<DType>::hitroot())
{
if (!(*comparef)(DL_Iter<DType>::item(), new_item))
break;
DL_Iter<DType>::next();
}
//if at root
DL_Iter<DType>::insbefore(new_item);
}
this->_current=cursor; //set to old cursor position
}
template <class DType>
void DL_SortIter<DType>::sortitererror()
{
this->Error("sortiter()",NOT_ALLOW);
}