home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
tlx501.zip
/
TEMPLATE
/
SEQ.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-02
|
19KB
|
613 lines
/****************************************************************************
$Id: seq.cpp 501.0 1995/03/07 12:27:00 RON Exp $
Copyright (c) 1991-95 Tarma Software Research. All rights reserved.
Project: Tarma Library for C++ V5.0
Author: Ron van der Wal
Implementation of class TLSeq<T>.
$Log: seq.cpp $
Revision 501.0 1995/03/07 12:27:00 RON
Updated for TLX 5.01
Revision 1.6 1995/01/31 16:30:48 RON
Update for release 012
Added partial support for SunPro C++ compiler
Revision 1.5 1994/09/28 14:41:59 ron
Removed Macintosh-style #include references
Revision 1.4 1994/09/27 20:27:33 ron
Changed path separator from / to \
Revision 1.3 1994/09/26 15:34:21 ron
Changed include file references
Revision 1.2 1994/09/06 14:15:36 ron
Adapted to changes in tlx.h
Revision 1.1 1994/08/16 18:15:31 ron
Initial revision
****************************************************************************/
#ifndef _TLX_SEQ_CPP
#define _TLX_SEQ_CPP
//----- Project headers
#ifndef _TLX_ARRAYS_H
#include <tlx\501\arrays.h>
#endif
#ifndef _TLX_DEBUG_H
#include <tlx\501\debug.h>
#endif
#ifndef _TLX_EXCEPT_H
#include <tlx\501\except.h>
#endif
#ifndef _TLX_SEQBASE_CPP
#include <tlx\501\template\seqbase.cpp>
#endif
/*---------------------------------------------------------------------------
Implementation note
-------------------
TLSeq<T> can be indexed using index base 1, i.e. valid indices range
from 1..mCount. The underlying TLVector<T> has index base 0, i.e. its
valid indices range from 0.._size-1. Several TLSeq<T> member functions
have these index bounds coded in for reasons of speed.
---------------------------------------------------------------------------*/
/*-------------------------------------------------------------------------*/
template<class T> TLSeq<T>::TLSeq(size_t size, size_t delta)
/* Normal constructor for TLSeq<T>. It calls the TLVector<T>(size_t)
constructor to create a vector of the desired size, then it sets
mCount to 0 to indicate an empty sequence, and mDelta to the
delta parameter.
---------------------------------------------------------------------------*/
: TLSeqBase<T>(size, delta)
{
}
/*-------------------------------------------------------------------------*/
template<class T> TLSeq<T>::TLSeq(const T &t)
/* Constructor creating a single element sequence that is initially not
expandable.
---------------------------------------------------------------------------*/
: TLSeqBase<T>(t)
{
}
/*-------------------------------------------------------------------------*/
template<class T> TLSeq<T>::TLSeq(const T *tp, size_t sz)
/* Constructor creating a sequence from a C-style vector of a given size.
---------------------------------------------------------------------------*/
: TLSeqBase<T>(tp, sz)
{
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::Append(const T &t, const T &pos)
/* Adds a new element after a given other one, or at the end of the
sequence if the positioning element does not appear in the sequence.
---------------------------------------------------------------------------*/
{
#ifndef NDEBUG
size_t csz = Count();
#endif
index_t ipos = IndexOf(pos);
InsertAt(IsValidIndex(ipos) ? ipos : mCount + 1, t);
TLX_ASSERT(Count() == csz + 1);
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::Append(const TLSeq<T> &s)
/* Adds another sequence at the end of the current sequence.
---------------------------------------------------------------------------*/
{
if (this == &s) return;
#ifndef NDEBUG
size_t csz = Count();
#endif
if (Available() < s.Count())
ExpandBy(s.Count() - Available());
TLX_ASSERT(Available() < s.Count());
const T *src = &s.PeekAt(1);
T *dst = &PeekAt(mCount + 1);
for (size_t cnt = s.mCount; cnt; --cnt)
*dst++ = *src++;
mCount += s.mCount;
TLX_ASSERT(Count() == csz + s.Count());
}
/*-------------------------------------------------------------------------*/
template<class T> T TLSeq<T>::Extract(const T &t)
/* Removes and returns a given value from the sequence.
---------------------------------------------------------------------------*/
{
index_t index = IndexOf(t);
if (!IsValidIndex(index))
THROW(TLXNotFound(LOCUS));
return ExtractAt(index);
}
/*-------------------------------------------------------------------------*/
template<class T> T TLSeq<T>::ExtractAt(index_t index)
/* Removes and returns a value at the given index from the sequence.
---------------------------------------------------------------------------*/
{
if (!IsValidIndex(index))
THROW(TLXIndex(LOCUS, index));
// Take 0/1 index base difference into account
index--;
T tmp = mVect[index];
for (index_t i = index; (tSize)i < (mCount-1); i++)
mVect[i] = mVect[i + 1];
TLX_ASSERT(Count() > 0);
mCount--;
return tmp;
}
/*-------------------------------------------------------------------------*/
template<class T> T TLSeq<T>::ExtractFirst()
/* Removes and returns the first value from the sequence.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return ExtractAt(Mini());
}
/*-------------------------------------------------------------------------*/
template<class T> T TLSeq<T>::ExtractLast()
/* Removes and returns the last value from the sequence.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return ExtractAt(Maxi());
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLSeq<T>::FindInsertPos
(
const T & t, // Value to find
index_t & pos // Will receive index position
) const
/* Performs a binary search in the sequence. Sets index of the item if
found, or best position if not. Returns true or false.
NOTE: we use 1-based indices to avoid problems with expressions like
'pos - 1' which might otherwise wrap around to +kMaxSize for the size_t
(i.e. unsigned) variables we use.
---------------------------------------------------------------------------*/
{
// Initialize invariant:
//
// low <= pos(t) <= up...
index_t low = 1, up = mCount;
pos = (low + up) / 2;
while (low <= up)
{
int result = mCompare(t, PeekAt(pos));
if (result == 0) // Found a match
return true;
else if (result < 0) // 't' less than mVect[i]
up = pos - 1;
else // 't' greater than mVect[i]
low = pos + 1;
pos = (low + up) / 2; // Adjust position
}
pos++; // TLSeq<T>::Insert() inserts BEFORE position 'i'
return false;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::Insert(const T &t)
/* Inserts a new element in its properly sorted position.
---------------------------------------------------------------------------*/
{
#ifndef NDEBUG
size_t csz = Count();
#endif
index_t pos;
FindInsertPos(t, pos);
InsertAt(pos, t);
TLX_ASSERT(Count() == csz + 1);
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::InsertAt(index_t index, const T &t)
/* Inserts a new element at the given position in the sequence.
---------------------------------------------------------------------------*/
{
if (IsFull())
Expand();
TLX_ASSERT(Available() >= 1);
#ifndef NDEBUG
size_t csz = Count();
#endif
if (index < 1) index = 1;
if ((tSize)index > (mCount + 1)) index = mCount + 1;
--index; // Adjust to 0-based indexing
for (size_t i = mCount; i > (tSize)index; i--)
mVect[i] = mVect[i - 1];
mVect[index] = t;
++mCount;
TLX_ASSERT(Count() == csz + 1);
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLSeq<T>::IterFirst(iter_t &i) const
/* Initializes the iterator to address the first element in the sequence.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return ((tSize)(i.ix = 0)) < mCount;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLSeq<T>::IterLast(iter_t &i) const
/* Initializes the iterator to address the last element in the sequence.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return (i.ix = mCount - 1) >= 0;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLSeq<T>::IterNext(iter_t &i) const
/* Initializes the iterator to address the next element in the sequence.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return ((tSize)(++i.ix)) < mCount;
}
/*-------------------------------------------------------------------------*/
template<class T> bool TLSeq<T>::IterPrev(iter_t &i) const
/* Initializes the iterator to address the previous element in the sequence.
Returns nonzero if the iterator is valid after the operation, else zero.
---------------------------------------------------------------------------*/
{
return --i.ix >= 0;
}
/*-------------------------------------------------------------------------*/
template<class T> TLSeq<T> &TLSeq<T>::operator =(const T &t)
/* Overloading of assignment operator that allows assignment of a single
element to a sequence. The previous contents of the sequence are lost.
---------------------------------------------------------------------------*/
{
RemoveAll();
Append(t);
return *this;
}
/*-------------------------------------------------------------------------*/
template<class T> TLSeq<T> &TLSeq<T>::operator =(const TLSeq<T> &s)
/* Overloading of the assignment operator.
---------------------------------------------------------------------------*/
{
if (this != &s)
{
TLSeqBase<T>::operator =(s);
mLower = s.mLower;
}
return *this;
}
/*-------------------------------------------------------------------------*/
template<class T> T &TLSeq<T>::PeekAt(index_t aIndex)
/* Returns a reference to the element at the given index.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(aIndex >= Mini());
TLX_ASSERT(aIndex <= Maxi());
return mVect[aIndex - 1];
}
/*-------------------------------------------------------------------------*/
template<class T> const T &TLSeq<T>::PeekAt(index_t aIndex) const
/* Returns a reference to the element at the given index.
---------------------------------------------------------------------------*/
{
TLX_ASSERT(aIndex >= Mini());
TLX_ASSERT(aIndex <= Maxi());
return mVect[aIndex - 1];
}
/*-------------------------------------------------------------------------*/
template<class T> T &TLSeq<T>::PeekFirst()
/* Returns a reference to the first element in the sequence. If the
sequence is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return PeekAt(Mini());
}
/*-------------------------------------------------------------------------*/
template<class T> const T &TLSeq<T>::PeekFirst() const
/* Returns a reference to the first element in the sequence. If the
sequence is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return PeekAt(Mini());
}
/*-------------------------------------------------------------------------*/
template<class T> T &TLSeq<T>::PeekLast()
/* Returns a reference to the last element in the sequence. If the
sequence is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return PeekAt(Maxi());
}
/*-------------------------------------------------------------------------*/
template<class T> const T &TLSeq<T>::PeekLast() const
/* Returns a reference to the last element in the sequence. If the
sequence is empty, a TLXEmpty exception is thrown.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
return PeekAt(Maxi());
}
/*-------------------------------------------------------------------------*/
template<class T> T &TLSeq<T>::PeekValue(const T &t)
/* Returns a reference to the first element with a given value. If the
value does not appear in the sequence, a TLXNotFound exception is
thrown.
---------------------------------------------------------------------------*/
{
index_t i = IndexOf(t);
if (!IsValidIndex(i))
THROW(TLXNotFound(LOCUS));
return PeekAt(i);
}
/*-------------------------------------------------------------------------*/
template<class T> const T &TLSeq<T>::PeekValue(const T &t) const
/* Returns a reference to the first element with a given value. If the
value does not appear in the sequence, a TLXNotFound exception is
thrown.
---------------------------------------------------------------------------*/
{
index_t i = IndexOf(t);
if (!IsValidIndex(i))
THROW(TLXNotFound(LOCUS));
return PeekAt(i);
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::Prepend(const T &t, const T &pos)
/* Inserts a new element before a given value. If the value does not
appear in the sequence, the new element is inserted at the start
of the sequence.
---------------------------------------------------------------------------*/
{
index_t ipos = IndexOf(pos);
InsertAt(IsValidIndex(ipos) ? ipos : 1, t);
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::Prepend(const TLSeq<T> &s)
/* Inserts another sequence at the start of the current sequence.
---------------------------------------------------------------------------*/
{
if (this == &s) return;
if (Available() < s.Count())
ExpandBy(s.Count() - Available());
TLX_ASSERT(Available() < s.Count());
const T *src = &PeekAt(mCount);
T *dst = &PeekAt(mCount + s.mCount);
for (size_t cnt = mCount; cnt; --cnt)
*dst-- = *src--;
src = &s.PeekAt(1);
dst = &PeekAt(1);
for (size_t cnt2 = s.mCount; cnt2; --cnt2)
*dst++ = *src++;
mCount += s.mCount;
}
/*-------------------------------------------------------------------------*/
template<class T> index_t TLSeq<T>::QPart(index_t low, index_t up)
/* Partitions a subarray of the sequence for quick-sort sorting.
---------------------------------------------------------------------------*/
{
T &pivot = PeekAt(low);
index_t i = low - 1; // Rover in lower part
index_t j = up + 1; // Rover in upper part
for (;;)
{
// Find subsequence in upper part
do j--; while (mCompare(PeekAt(j), pivot) > 0);
// Find subsequence in lower part
do i++; while (mCompare(PeekAt(i), pivot) < 0);
// Swap elements, or return partition position
if (i < j)
{
T tmp = PeekAt(i);
PeekAt(i) = PeekAt(j);
PeekAt(j) = tmp;
}
else
return j; // Done
}
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::QSort(index_t low, index_t up)
/* Performs quick sort on a partition of the sequence.
---------------------------------------------------------------------------*/
{
if (low >= up) return; // Empty or single-item partition
index_t mid = QPart(low, up); // Make partitions
QSort(low, mid); // Sort lower part
QSort(mid + 1, up); // Sort upper part
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::Remove(const T &t)
/* Removes a given value from the sequence.
---------------------------------------------------------------------------*/
{
index_t index = IndexOf(t);
if (!IsValidIndex(index))
THROW(TLXNotFound(LOCUS));
RemoveAt(index);
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::RemoveAt(index_t index)
/* Removes a value at the given index from the sequence.
---------------------------------------------------------------------------*/
{
if (!IsValidIndex(index))
THROW(TLXIndex(LOCUS, index));
// Take 0/1 index base difference into account
index--;
for (index_t i = index; (tSize)i < (mCount-1); i++)
mVect[i] = mVect[i + 1];
TLX_ASSERT(Count() > 0);
mCount--;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::RemoveFirst()
/* Removes the first value from the sequence.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
RemoveAt(Mini());
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::RemoveLast()
/* Removes the last value from the sequence.
---------------------------------------------------------------------------*/
{
if (IsEmpty())
THROW(TLXEmpty(LOCUS));
RemoveAt(Maxi());
}
/*-------------------------------------------------------------------------*/
template<class T> index_t TLSeq<T>::Search(const T &t) const
/* Performs a binary search in the sequence. Returns index, or 0
if not found.
---------------------------------------------------------------------------*/
{
index_t pos;
return FindInsertPos(t, pos) ? pos : 0;
}
/*-------------------------------------------------------------------------*/
template<class T> void TLSeq<T>::Sort()
/* Performs quick sort on the sequence.
---------------------------------------------------------------------------*/
{
QSort(1, Count());
}
#endif // _TLX_SEQ_CPP