Static vectors operations:
Dynamic vectors, additional operations:
Below is an approximation of the definition of vector in c++
template<typename T>
class vector {
vector();
~vector();
vector(vector const& src);
vector& operator=(vector const& src);
bool empty() const;
size_t size() const;
void clear();
iterator begin();
const_iterator begin() const;
iterator end();
const_iterator end();
T& operator[](size_t index);
T const& operator[](size_t index) const;
iterator insert(iterator pos, T const& val);
void erase(iterator pos);
};
Main functions in java arrays are:
class ArrayList{ ArrayList(); ArrayList(Collection extends E> src); Object clone(); boolean isEmpty(); int size(); void clear(); Iterator iterator(); ListIterator listIterator(); ListIterator listIterator(int index); E get(int index); E set(int index, E element); void add(int index, E element); }
Some functions are performed directly through iterators
class ListIterator{ boolean hasNext(); boolean hasPrevious(); E next(); E previous(); int nextIndex(); int previousIndex(); void set(E element); // changes the last element returned by next() or previous() void add(E element); // adds at current position void remove(); // removes the last element returned by next() or previous() }
For dynamic vectors, the actual array of elements is allocated separately from the vector variable. The vector is defined as:
template<typename T>
class vector {
T* m_data; // pointer to the array
size_t m_size; // number of actually used elements in the array
size_t m_allocated; // number of allocated elements in the array
};
or
template<typename T>
class vector {
T* m_data; // pointer to the array
T* m_end_data; // pointer after the last used element
T* m_end_allocated; // pointer after the last allocated element
};
The constructors, destructor and assignment operators must take care of the actual array of elements.
vector::~vector()
{
delete[] m_data;
}
vector& vector::vector(vector const& src)
:m_data(new T[src.size()],
m_size(src.size()),
m_allocated(src.size())
{
for(size_t i=0 ; i<m_size ; ++i) {
m_data[i] = src[i];
}
}
When adding an element exceeds the allocated capacity, the data array must be reallocated and the existing elements must be copied.
Question: what should be the new allocated size?
It is tempting to allocate the current size plus a fixed number. However, a better strategy is to allocate the current size times a fixed coefficient. The first strategy requires a number of element copies of O(n2), while the second one requires O(n).
Below we give the cumulated number of element copies after adding n elements to an initially empty vector. Strategy 1 starts with a capacity of 0 and reallocates at a capacity 16 plus the old capacity each time the capacity is exceeded. Strategy 2 starts with a capacity of 1 and doubles the capacity each time it is exceeded.
| n | copies for adding 16 | copies for doubling |
|---|---|---|
| 16 | 0 | 15 |
| 32 | 16 | 31 |
| 256 | 1920 | 255 |
| 1024 | 32256 | 1023 |
| 1M | 34359214080 | 1048575 |
| 32M | 35184355311616 | 33554431 |
There are several ways to represent an iterator: