Last active
November 9, 2019 21:59
-
-
Save jaasonw/581a8599d5b5b7beca66e4c643a7ebca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Simple vector implementation | |
* Author: Jason Wong | |
*/ | |
#pragma once | |
#include <cassert> | |
#include <iostream> | |
#include <stdexcept> | |
template <typename T> | |
class vector { | |
private: | |
T* _array; | |
const unsigned int MIN_CAPACITY = 2; | |
unsigned int _size = 0; | |
unsigned int _capacity = MIN_CAPACITY; | |
void _copy_array(T* src, unsigned int src_size) { | |
assert(src_size <= _capacity); | |
for (unsigned int i = 0; i < src_size; ++i) { | |
_array[i] = src[i]; | |
} | |
_size = src_size; | |
} | |
void _reallocate(unsigned int new_capacity) { | |
T* temp = _array; | |
_capacity = new_capacity; | |
_array = new T[new_capacity](); | |
_copy_array(temp, _size); | |
delete[] temp; | |
} | |
public: | |
class iterator { | |
private: | |
T* _ptr = nullptr; | |
unsigned int _index = -1; | |
public: | |
iterator(T* data, unsigned int index): _ptr(data), _index(index) {}; | |
T& operator*() { return _ptr[_index]; } | |
iterator& operator++() { | |
_index++; | |
return *this; | |
} | |
iterator operator++(int) { | |
iterator hold = *this; | |
_index++; | |
return hold; | |
} | |
iterator& operator--() { | |
_index--; | |
return *this; | |
} | |
iterator operator--(int) { | |
iterator hold = *this; | |
_index--; | |
return hold; | |
} | |
friend bool operator!=(typename vector<T>::iterator& left, | |
typename vector<T>::iterator& right) { | |
return left._ptr != right._ptr || left._index != right._index; | |
} | |
friend bool operator==(typename vector<T>::iterator& left, | |
typename vector<T>::iterator& right) { | |
return !(left != right); | |
} | |
}; | |
// constructors | |
vector(); | |
vector(unsigned int capacity); | |
vector(const vector<T>& other); | |
vector<T>& operator=(const vector<T>& other); | |
~vector(); | |
// vector methods | |
void push_back(const T& item); | |
T pop_back(); | |
void clear(); | |
void shrink_to_fit() { _reallocate(_size); }; | |
void resize(unsigned int size); | |
// size/capacity | |
unsigned int size() const { return _size; }; | |
unsigned int capacity() const { return _capacity; }; | |
// accessors | |
T& operator[](unsigned int index) const; | |
T& at(unsigned int index) const; | |
// iterators (bidirectional) | |
// returns an iterator pointing to the beginning to the 1st element | |
iterator begin() const { return iterator(_array, 0); } | |
// returns an iterator pointing to after the last element | |
iterator end() const { return iterator(_array, _size); } | |
friend std::ostream& operator<<(std::ostream& outs, const vector<T>& vec) { | |
for (auto e : vec) { | |
outs << e << " "; | |
} | |
return outs; | |
} | |
}; | |
template <typename T> | |
vector<T>::vector() { | |
_array = new T[_capacity](); | |
} | |
template <typename T> | |
vector<T>::vector(unsigned int capacity) | |
: _capacity(capacity), _array(new T[_capacity]()) {} | |
template <typename T> | |
vector<T>::vector(const vector<T>& other) { | |
_capacity = other._capacity; | |
_array = new T[_capacity](); | |
_copy_array(other._array, other._size); | |
} | |
template <typename T> | |
vector<T>& vector<T>::operator=(const vector<T>& other) { | |
if (this == &other) | |
return *this; | |
delete[] _array; | |
_capacity = other._capacity; | |
_array = new T[other._capacity](); | |
_copy_array(other._array, other._size); | |
return *this; | |
} | |
template <typename T> | |
vector<T>::~vector() { | |
delete[] _array; | |
} | |
template <typename T> | |
void vector<T>::push_back(const T& item) { | |
if (_size + 1 >= _capacity) { | |
_reallocate(_capacity * 2); | |
} | |
_array[_size++] = item; | |
} | |
template <typename T> | |
T vector<T>::pop_back() { | |
T hold = _array[--_size]; | |
if (_size <= _capacity / 4 && _capacity > MIN_CAPACITY) { | |
_reallocate(_capacity / 2); | |
} | |
return hold; | |
} | |
template <typename T> | |
void vector<T>::clear() { | |
_size = 0; | |
_reallocate(MIN_CAPACITY); | |
} | |
template <typename T> | |
T& vector<T>::at(unsigned int index) const { | |
if (index >= _size) | |
throw std::out_of_range("Index out of range"); | |
return _array[index]; | |
} | |
template <typename T> | |
T& vector<T>::operator[](unsigned int index) const { return _array[index]; } | |
template <typename T> | |
void vector<T>::resize(unsigned int size) { | |
if (size >= _size) | |
_reallocate(size * 2); | |
_size = size; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment