2015-04-30 20:36:39 +00:00
|
|
|
//
|
|
|
|
// Typical template dynamic array container class.
|
|
|
|
// By S Melax 1998
|
2018-09-23 21:17:31 +00:00
|
|
|
//
|
2015-04-30 20:36:39 +00:00
|
|
|
// anyone is free to use, inspect, learn from, or ignore
|
2018-09-23 21:17:31 +00:00
|
|
|
// the code here as they see fit.
|
2015-04-30 20:36:39 +00:00
|
|
|
//
|
|
|
|
// A very simple template array class.
|
|
|
|
// Its easiest to understand this array
|
|
|
|
// class by seeing how it is used in code.
|
|
|
|
//
|
|
|
|
// For example:
|
2018-09-23 21:17:31 +00:00
|
|
|
// for(i=0;i<myarray.count;i++)
|
2015-04-30 20:36:39 +00:00
|
|
|
// myarray[i] = somefunction(i);
|
2018-09-23 21:17:31 +00:00
|
|
|
//
|
|
|
|
// When the array runs out of room, it
|
2015-04-30 20:36:39 +00:00
|
|
|
// reallocates memory and doubles the size of its
|
|
|
|
// storage buffer. The reason for *doubleing* the amount of
|
|
|
|
// memory is so the order of any algorithm using this class
|
|
|
|
// is the same as it would be had you used a regular C array.
|
2018-09-23 21:17:31 +00:00
|
|
|
// The penalty for reallocating and copying
|
2015-04-30 20:36:39 +00:00
|
|
|
// For example consider adding n elements to a list.
|
|
|
|
// Lets sum the number of times elements are "copied".
|
|
|
|
// The worst case occurs when n=2^k+1 where k is integer.
|
2018-09-23 21:17:31 +00:00
|
|
|
// In this case we do a big reallocation when we add the last element.
|
2015-04-30 20:36:39 +00:00
|
|
|
// n elements are copied once, n/2 elements are copied twice,
|
|
|
|
// n/4 elements are copied 3 times, and so on ...
|
|
|
|
// total == n* (1+1/2 + 1/4 + 1/8 + ...) == n * 2
|
2018-09-23 21:17:31 +00:00
|
|
|
// So we do n*2 copies. Therefore adding n
|
2015-04-30 20:36:39 +00:00
|
|
|
// elements to an Array is still O(n).
|
|
|
|
// The memory usage is also of the same order as if a C array was used.
|
2018-09-23 21:17:31 +00:00
|
|
|
// An Array uses less than double the minimum needed space. Again, we
|
2015-04-30 20:36:39 +00:00
|
|
|
// see that we are within a small constant multiple.
|
2018-09-23 21:17:31 +00:00
|
|
|
//
|
|
|
|
// Why no "realloc" to avoid the copy when reallocating memory?
|
|
|
|
// You have a choice to either use malloc/free and friends
|
2015-04-30 20:36:39 +00:00
|
|
|
// or to use new/delete. Its bad mojo to mix these. new/delete was
|
2018-09-23 21:17:31 +00:00
|
|
|
// chosen to be C++ish and have the array elements constructors/destructors
|
2015-04-30 20:36:39 +00:00
|
|
|
// invoked as expected.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef SM_ARRAY_H
|
|
|
|
#define SM_ARRAY_H
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
class Array
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Array(int s = 0);
|
|
|
|
Array(Array<Type> &array);
|
|
|
|
~Array();
|
|
|
|
void allocate(int s);
|
|
|
|
void SetSize(int s);
|
|
|
|
void Pack();
|
|
|
|
Type &Add(Type);
|
|
|
|
void AddUnique(Type);
|
|
|
|
int Contains(Type);
|
|
|
|
void Insert(Type, int);
|
|
|
|
int IndexOf(Type);
|
|
|
|
void Remove(Type);
|
|
|
|
void DelIndex(int i);
|
|
|
|
Type &DelIndexWithLast(int i);
|
|
|
|
Type *element;
|
|
|
|
int count;
|
|
|
|
int array_size;
|
|
|
|
const Type &operator[](int i) const
|
|
|
|
{
|
|
|
|
assert(i >= 0 && i < count);
|
|
|
|
return element[i];
|
|
|
|
}
|
|
|
|
Type &operator[](int i)
|
|
|
|
{
|
|
|
|
assert(i >= 0 && i < count);
|
|
|
|
return element[i];
|
|
|
|
}
|
|
|
|
Type &Pop()
|
|
|
|
{
|
|
|
|
assert(count);
|
|
|
|
count--;
|
|
|
|
return element[count];
|
|
|
|
}
|
2015-04-30 20:36:39 +00:00
|
|
|
Array<Type> ©(const Array<Type> &array);
|
|
|
|
Array<Type> &operator=(Array<Type> &array);
|
|
|
|
};
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
Array<Type>::Array(int s)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
if (s == -1) return;
|
|
|
|
count = 0;
|
2015-04-30 20:36:39 +00:00
|
|
|
array_size = 0;
|
|
|
|
element = NULL;
|
2018-09-23 21:17:31 +00:00
|
|
|
if (s)
|
|
|
|
{
|
2015-04-30 20:36:39 +00:00
|
|
|
allocate(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
Array<Type>::Array(Array<Type> &array)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
count = 0;
|
2015-04-30 20:36:39 +00:00
|
|
|
array_size = 0;
|
|
|
|
element = NULL;
|
|
|
|
*this = array;
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
Array<Type> &Array<Type>::copy(const Array<Type> &array)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
assert(array.array_size >= 0);
|
|
|
|
count = 0;
|
|
|
|
for (int i = 0; i < array.count; i++)
|
|
|
|
{
|
2015-04-30 20:36:39 +00:00
|
|
|
Add(array[i]);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
Array<Type> &Array<Type>::operator=(Array<Type> &array)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
if (array.array_size < 0) // negative number means steal the data buffer instead of copying
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
delete[] element;
|
2015-04-30 20:36:39 +00:00
|
|
|
element = array.element;
|
|
|
|
array_size = -array.array_size;
|
|
|
|
count = array.count;
|
2018-09-23 21:17:31 +00:00
|
|
|
array.count = array.array_size = 0;
|
2015-04-30 20:36:39 +00:00
|
|
|
array.element = NULL;
|
|
|
|
return *this;
|
|
|
|
}
|
2018-09-23 21:17:31 +00:00
|
|
|
count = 0;
|
|
|
|
for (int i = 0; i < array.count; i++)
|
|
|
|
{
|
2015-04-30 20:36:39 +00:00
|
|
|
Add(array[i]);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
Array<Type>::~Array()
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
if (element != NULL && array_size != 0)
|
|
|
|
{
|
|
|
|
delete[] element;
|
|
|
|
}
|
|
|
|
count = 0;
|
|
|
|
array_size = 0;
|
|
|
|
element = NULL;
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
void Array<Type>::allocate(int s)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
assert(s > 0);
|
|
|
|
assert(s >= count);
|
|
|
|
if (s == array_size) return;
|
2015-04-30 20:36:39 +00:00
|
|
|
Type *old = element;
|
2018-09-23 21:17:31 +00:00
|
|
|
array_size = s;
|
2015-04-30 20:36:39 +00:00
|
|
|
element = new Type[array_size];
|
|
|
|
assert(element);
|
2018-09-23 21:17:31 +00:00
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
element[i] = old[i];
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
2018-09-23 21:17:31 +00:00
|
|
|
if (old) delete[] old;
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
void Array<Type>::SetSize(int s)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
if (s == 0)
|
|
|
|
{
|
|
|
|
if (element)
|
|
|
|
{
|
|
|
|
delete[] element;
|
|
|
|
element = NULL;
|
|
|
|
}
|
2015-04-30 20:36:39 +00:00
|
|
|
array_size = s;
|
2018-09-23 21:17:31 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
allocate(s);
|
|
|
|
}
|
|
|
|
count = s;
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
void Array<Type>::Pack()
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
|
|
|
allocate(count);
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
Type &Array<Type>::Add(Type t)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
assert(count <= array_size);
|
|
|
|
if (count == array_size)
|
|
|
|
{
|
|
|
|
allocate((array_size) ? array_size * 2 : 16);
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
//int i;
|
|
|
|
//for(i=0;i<count;i++) {
|
2018-09-23 21:17:31 +00:00
|
|
|
// dissallow duplicates
|
2015-04-30 20:36:39 +00:00
|
|
|
// assert(element[i] != t);
|
|
|
|
//}
|
|
|
|
element[count++] = t;
|
2018-09-23 21:17:31 +00:00
|
|
|
return element[count - 1];
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
int Array<Type>::Contains(Type t)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
|
|
|
int i;
|
2018-09-23 21:17:31 +00:00
|
|
|
int found = 0;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (element[i] == t) found++;
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
void Array<Type>::AddUnique(Type t)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
if (!Contains(t)) Add(t);
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
void Array<Type>::DelIndex(int i)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
assert(i < count);
|
2015-04-30 20:36:39 +00:00
|
|
|
count--;
|
2018-09-23 21:17:31 +00:00
|
|
|
while (i < count)
|
|
|
|
{
|
|
|
|
element[i] = element[i + 1];
|
2015-04-30 20:36:39 +00:00
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
Type &Array<Type>::DelIndexWithLast(int i)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
assert(i < count);
|
2015-04-30 20:36:39 +00:00
|
|
|
count--;
|
2018-09-23 21:17:31 +00:00
|
|
|
if (i < count)
|
|
|
|
{
|
|
|
|
Type r = element[i];
|
2015-04-30 20:36:39 +00:00
|
|
|
element[i] = element[count];
|
2018-09-23 21:17:31 +00:00
|
|
|
element[count] = r;
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
return element[count];
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
void Array<Type>::Remove(Type t)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
|
|
|
int i;
|
2018-09-23 21:17:31 +00:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (element[i] == t)
|
|
|
|
{
|
2015-04-30 20:36:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-09-23 21:17:31 +00:00
|
|
|
assert(i < count); // assert object t is in the array.
|
2015-04-30 20:36:39 +00:00
|
|
|
DelIndex(i);
|
2018-09-23 21:17:31 +00:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
2015-04-30 20:36:39 +00:00
|
|
|
assert(element[i] != t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
void Array<Type>::Insert(Type t, int k)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
2018-09-23 21:17:31 +00:00
|
|
|
int i = count;
|
|
|
|
Add(t); // to allocate space
|
|
|
|
while (i > k)
|
|
|
|
{
|
|
|
|
element[i] = element[i - 1];
|
2015-04-30 20:36:39 +00:00
|
|
|
i--;
|
|
|
|
}
|
2018-09-23 21:17:31 +00:00
|
|
|
assert(i == k);
|
|
|
|
element[k] = t;
|
2015-04-30 20:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-09-23 21:17:31 +00:00
|
|
|
template <class Type>
|
|
|
|
int Array<Type>::IndexOf(Type t)
|
2015-04-30 20:36:39 +00:00
|
|
|
{
|
|
|
|
int i;
|
2018-09-23 21:17:31 +00:00
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
if (element[i] == t)
|
|
|
|
{
|
2015-04-30 20:36:39 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(0);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|