123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- //
- // Typical template dynamic array container class.
- // By S Melax 1998
- //
- // anyone is free to use, inspect, learn from, or ignore
- // the code here as they see fit.
- //
- // A very simple template array class.
- // Its easiest to understand this array
- // class by seeing how it is used in code.
- //
- // For example:
- // for(i=0;i<myarray.count;i++)
- // myarray[i] = somefunction(i);
- //
- // When the array runs out of room, it
- // 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.
- // The penalty for reallocating and copying
- // 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.
- // In this case we do a big reallocation when we add the last element.
- // 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
- // So we do n*2 copies. Therefore adding n
- // elements to an Array is still O(n).
- // The memory usage is also of the same order as if a C array was used.
- // An Array uses less than double the minimum needed space. Again, we
- // see that we are within a small constant multiple.
- //
- // Why no "realloc" to avoid the copy when reallocating memory?
- // You have a choice to either use malloc/free and friends
- // or to use new/delete. Its bad mojo to mix these. new/delete was
- // chosen to be C++ish and have the array elements constructors/destructors
- // invoked as expected.
- //
- //
- #ifndef SM_ARRAY_H
- #define SM_ARRAY_H
- #include <assert.h>
- #include <stdio.h>
- 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]; }
- Array<Type> ©(const Array<Type> &array);
- Array<Type> &operator=(Array<Type> &array);
- };
- template <class Type> Array<Type>::Array(int s)
- {
- if(s==-1) return;
- count=0;
- array_size = 0;
- element = NULL;
- if(s)
- {
- allocate(s);
- }
- }
- template <class Type> Array<Type>::Array(Array<Type> &array)
- {
- count=0;
- array_size = 0;
- element = NULL;
- *this = array;
- }
- template <class Type> Array<Type> &Array<Type>::copy(const Array<Type> &array)
- {
- assert(array.array_size>=0);
- count=0;
- for(int i=0;i<array.count;i++)
- {
- Add(array[i]);
- }
- return *this;
- }
- template <class Type> Array<Type> &Array<Type>::operator=( Array<Type> &array)
- {
- if(array.array_size<0) // negative number means steal the data buffer instead of copying
- {
- delete[] element;
- element = array.element;
- array_size = -array.array_size;
- count = array.count;
- array.count =array.array_size = 0;
- array.element = NULL;
- return *this;
- }
- count=0;
- for(int i=0;i<array.count;i++)
- {
- Add(array[i]);
- }
- return *this;
- }
- template <class Type> Array<Type>::~Array()
- {
- if (element != NULL && array_size!=0)
- {
- delete[] element;
- }
- count=0;array_size=0;element=NULL;
- }
- template <class Type> void Array<Type>::allocate(int s)
- {
- assert(s>0);
- assert(s>=count);
- if(s==array_size) return;
- Type *old = element;
- array_size =s;
- element = new Type[array_size];
- assert(element);
- for(int i=0;i<count;i++)
- {
- element[i]=old[i];
- }
- if(old) delete[] old;
- }
- template <class Type> void Array<Type>::SetSize(int s)
- {
- if(s==0)
- {
- if(element)
- {
- delete[] element;
- element = NULL;
- }
- array_size = s;
- }
- else
- {
- allocate(s);
- }
- count=s;
- }
- template <class Type> void Array<Type>::Pack()
- {
- allocate(count);
- }
- template <class Type> Type& Array<Type>::Add(Type t)
- {
- assert(count<=array_size);
- if(count==array_size)
- {
- allocate((array_size)?array_size *2:16);
- }
- //int i;
- //for(i=0;i<count;i++) {
- // dissallow duplicates
- // assert(element[i] != t);
- //}
- element[count++] = t;
- return element[count-1];
- }
- template <class Type> int Array<Type>::Contains(Type t)
- {
- int i;
- int found=0;
- for(i=0;i<count;i++)
- {
- if(element[i] == t) found++;
- }
- return found;
- }
- template <class Type> void Array<Type>::AddUnique(Type t)
- {
- if(!Contains(t)) Add(t);
- }
- template <class Type> void Array<Type>::DelIndex(int i)
- {
- assert(i<count);
- count--;
- while(i<count)
- {
- element[i] = element[i+1];
- i++;
- }
- }
- template <class Type> Type& Array<Type>::DelIndexWithLast(int i)
- {
- assert(i<count);
- count--;
- if(i<count)
- {
- Type r=element[i];
- element[i] = element[count];
- element[count]=r;
- }
- return element[count];
- }
- template <class Type> void Array<Type>::Remove(Type t)
- {
- int i;
- for(i=0;i<count;i++)
- {
- if(element[i] == t)
- {
- break;
- }
- }
- assert(i<count); // assert object t is in the array.
- DelIndex(i);
- for(i=0;i<count;i++)
- {
- assert(element[i] != t);
- }
- }
- template <class Type> void Array<Type>::Insert(Type t,int k)
- {
- int i=count;
- Add(t); // to allocate space
- while(i>k)
- {
- element[i]=element[i-1];
- i--;
- }
- assert(i==k);
- element[k]=t;
- }
- template <class Type> int Array<Type>::IndexOf(Type t)
- {
- int i;
- for(i=0;i<count;i++)
- {
- if(element[i] == t)
- {
- return i;
- }
- }
- assert(0);
- return -1;
- }
- #endif
|