array.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. //
  2. // Typical template dynamic array container class.
  3. // By S Melax 1998
  4. //
  5. // anyone is free to use, inspect, learn from, or ignore
  6. // the code here as they see fit.
  7. //
  8. // A very simple template array class.
  9. // Its easiest to understand this array
  10. // class by seeing how it is used in code.
  11. //
  12. // For example:
  13. // for(i=0;i<myarray.count;i++)
  14. // myarray[i] = somefunction(i);
  15. //
  16. // When the array runs out of room, it
  17. // reallocates memory and doubles the size of its
  18. // storage buffer. The reason for *doubleing* the amount of
  19. // memory is so the order of any algorithm using this class
  20. // is the same as it would be had you used a regular C array.
  21. // The penalty for reallocating and copying
  22. // For example consider adding n elements to a list.
  23. // Lets sum the number of times elements are "copied".
  24. // The worst case occurs when n=2^k+1 where k is integer.
  25. // In this case we do a big reallocation when we add the last element.
  26. // n elements are copied once, n/2 elements are copied twice,
  27. // n/4 elements are copied 3 times, and so on ...
  28. // total == n* (1+1/2 + 1/4 + 1/8 + ...) == n * 2
  29. // So we do n*2 copies. Therefore adding n
  30. // elements to an Array is still O(n).
  31. // The memory usage is also of the same order as if a C array was used.
  32. // An Array uses less than double the minimum needed space. Again, we
  33. // see that we are within a small constant multiple.
  34. //
  35. // Why no "realloc" to avoid the copy when reallocating memory?
  36. // You have a choice to either use malloc/free and friends
  37. // or to use new/delete. Its bad mojo to mix these. new/delete was
  38. // chosen to be C++ish and have the array elements constructors/destructors
  39. // invoked as expected.
  40. //
  41. //
  42. #ifndef SM_ARRAY_H
  43. #define SM_ARRAY_H
  44. #include <assert.h>
  45. #include <stdio.h>
  46. template <class Type> class Array {
  47. public:
  48. Array(int s=0);
  49. Array(Array<Type> &array);
  50. ~Array();
  51. void allocate(int s);
  52. void SetSize(int s);
  53. void Pack();
  54. Type& Add(Type);
  55. void AddUnique(Type);
  56. int Contains(Type);
  57. void Insert(Type,int);
  58. int IndexOf(Type);
  59. void Remove(Type);
  60. void DelIndex(int i);
  61. Type& DelIndexWithLast(int i);
  62. Type * element;
  63. int count;
  64. int array_size;
  65. const Type &operator[](int i) const { assert(i>=0 && i<count); return element[i]; }
  66. Type &operator[](int i) { assert(i>=0 && i<count); return element[i]; }
  67. Type &Pop() { assert(count); count--; return element[count]; }
  68. Array<Type> &copy(const Array<Type> &array);
  69. Array<Type> &operator=(Array<Type> &array);
  70. };
  71. template <class Type> Array<Type>::Array(int s)
  72. {
  73. if(s==-1) return;
  74. count=0;
  75. array_size = 0;
  76. element = NULL;
  77. if(s)
  78. {
  79. allocate(s);
  80. }
  81. }
  82. template <class Type> Array<Type>::Array(Array<Type> &array)
  83. {
  84. count=0;
  85. array_size = 0;
  86. element = NULL;
  87. *this = array;
  88. }
  89. template <class Type> Array<Type> &Array<Type>::copy(const Array<Type> &array)
  90. {
  91. assert(array.array_size>=0);
  92. count=0;
  93. for(int i=0;i<array.count;i++)
  94. {
  95. Add(array[i]);
  96. }
  97. return *this;
  98. }
  99. template <class Type> Array<Type> &Array<Type>::operator=( Array<Type> &array)
  100. {
  101. if(array.array_size<0) // negative number means steal the data buffer instead of copying
  102. {
  103. delete[] element;
  104. element = array.element;
  105. array_size = -array.array_size;
  106. count = array.count;
  107. array.count =array.array_size = 0;
  108. array.element = NULL;
  109. return *this;
  110. }
  111. count=0;
  112. for(int i=0;i<array.count;i++)
  113. {
  114. Add(array[i]);
  115. }
  116. return *this;
  117. }
  118. template <class Type> Array<Type>::~Array()
  119. {
  120. if (element != NULL && array_size!=0)
  121. {
  122. delete[] element;
  123. }
  124. count=0;array_size=0;element=NULL;
  125. }
  126. template <class Type> void Array<Type>::allocate(int s)
  127. {
  128. assert(s>0);
  129. assert(s>=count);
  130. if(s==array_size) return;
  131. Type *old = element;
  132. array_size =s;
  133. element = new Type[array_size];
  134. assert(element);
  135. for(int i=0;i<count;i++)
  136. {
  137. element[i]=old[i];
  138. }
  139. if(old) delete[] old;
  140. }
  141. template <class Type> void Array<Type>::SetSize(int s)
  142. {
  143. if(s==0)
  144. {
  145. if(element)
  146. {
  147. delete[] element;
  148. element = NULL;
  149. }
  150. array_size = s;
  151. }
  152. else
  153. {
  154. allocate(s);
  155. }
  156. count=s;
  157. }
  158. template <class Type> void Array<Type>::Pack()
  159. {
  160. allocate(count);
  161. }
  162. template <class Type> Type& Array<Type>::Add(Type t)
  163. {
  164. assert(count<=array_size);
  165. if(count==array_size)
  166. {
  167. allocate((array_size)?array_size *2:16);
  168. }
  169. //int i;
  170. //for(i=0;i<count;i++) {
  171. // dissallow duplicates
  172. // assert(element[i] != t);
  173. //}
  174. element[count++] = t;
  175. return element[count-1];
  176. }
  177. template <class Type> int Array<Type>::Contains(Type t)
  178. {
  179. int i;
  180. int found=0;
  181. for(i=0;i<count;i++)
  182. {
  183. if(element[i] == t) found++;
  184. }
  185. return found;
  186. }
  187. template <class Type> void Array<Type>::AddUnique(Type t)
  188. {
  189. if(!Contains(t)) Add(t);
  190. }
  191. template <class Type> void Array<Type>::DelIndex(int i)
  192. {
  193. assert(i<count);
  194. count--;
  195. while(i<count)
  196. {
  197. element[i] = element[i+1];
  198. i++;
  199. }
  200. }
  201. template <class Type> Type& Array<Type>::DelIndexWithLast(int i)
  202. {
  203. assert(i<count);
  204. count--;
  205. if(i<count)
  206. {
  207. Type r=element[i];
  208. element[i] = element[count];
  209. element[count]=r;
  210. }
  211. return element[count];
  212. }
  213. template <class Type> void Array<Type>::Remove(Type t)
  214. {
  215. int i;
  216. for(i=0;i<count;i++)
  217. {
  218. if(element[i] == t)
  219. {
  220. break;
  221. }
  222. }
  223. assert(i<count); // assert object t is in the array.
  224. DelIndex(i);
  225. for(i=0;i<count;i++)
  226. {
  227. assert(element[i] != t);
  228. }
  229. }
  230. template <class Type> void Array<Type>::Insert(Type t,int k)
  231. {
  232. int i=count;
  233. Add(t); // to allocate space
  234. while(i>k)
  235. {
  236. element[i]=element[i-1];
  237. i--;
  238. }
  239. assert(i==k);
  240. element[k]=t;
  241. }
  242. template <class Type> int Array<Type>::IndexOf(Type t)
  243. {
  244. int i;
  245. for(i=0;i<count;i++)
  246. {
  247. if(element[i] == t)
  248. {
  249. return i;
  250. }
  251. }
  252. assert(0);
  253. return -1;
  254. }
  255. #endif