This commit is contained in:
邹晓航
2015-01-12 14:14:16 +08:00
parent 077d5c6a19
commit 4d84582df9
2 changed files with 425 additions and 374 deletions

401
TinySTL/Detail/List.impl.h Normal file
View File

@@ -0,0 +1,401 @@
#ifndef _LIST_IMPL_H_
#define _LIST_IMPL_H_
namespace TinySTL{
namespace Detail{
template<class T>
listIterator<T>& listIterator<T>::operator++(){
p = p->next;
return *this;
}
template<class T>
listIterator<T> listIterator<T>::operator++(int){
auto res = *this;
++*this;
return res;
}
template<class T>
listIterator<T>& listIterator<T>::operator --(){
p = p->prev;
return *this;
}
template<class T>
listIterator<T> listIterator<T>::operator --(int){
auto res = *this;
--*this;
return res;
}
template<class T>
bool operator ==(const listIterator<T>& lhs, const listIterator<T>& rhs){
return lhs.p == rhs.p;
}
template<class T>
bool operator !=(const listIterator<T>& lhs, const listIterator<T>& rhs){
return !(lhs == rhs);
}
}//end of Detail namespace
template<class T>
void list<T>::insert_aux(iterator position, size_type n, const T& val, std::true_type){
for (auto i = n; i != 0; --i){
position = insert(position, val);
}
}
template<class T>
template<class InputIterator>
void list<T>::insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type){
for (; first != last; ++first){
insert(position, *first);
}
}
template<class T>
typename list<T>::nodePtr list<T>::newNode(const T& val = T()){
nodePtr res = nodeAllocator::allocate();
res->container = this;
//res->data = val; //-> bug
//nodeAllocator::construct(&(res->data), val);
TinySTL::construct(&(res->data), val);//fix
res->prev = nullptr;
res->next = nullptr;
return res;
}
template<class T>
void list<T>::deleteNode(nodePtr p){
p->prev = nullptr;
p->next = nullptr;
nodeAllocator::deallocate(p);
}
template<class T>
void list<T>::ctorAux(size_type n, const value_type& val, std::true_type){
head.p = newNode();//add a dummy node
tail.p = head.p;
while (n--)
push_back(val);
}
template<class T>
template <class InputIterator>
void list<T>::ctorAux(InputIterator first, InputIterator last, std::false_type){
head.p = newNode();//add a dummy node
tail.p = head.p;
for (; first != last; ++first)
push_back(*first);
}
template<class T>
typename list<T>::size_type list<T>::size()const{
size_type length = 0;
for (auto h = head; h != tail; ++h)
++length;
return length;
}
template<class T>
list<T>::list(){
head.p = newNode();//add a dummy node
tail.p = head.p;
}
template<class T>
list<T>::list(size_type n, const value_type& val = value_type()){
ctorAux(n, val, std::is_integral<value_type>());
}
template<class T>
template <class InputIterator>
list<T>::list(InputIterator first, InputIterator last){
ctorAux(first, last, std::is_integral<InputIterator>());
}
template<class T>
list<T>::list(const list& l){
head.p = newNode();//add a dummy node
tail.p = head.p;
for (auto node = l.head.p; node != l.tail.p; node = node->next)
push_back(node->data);
}
template<class T>
list<T>& list<T>::operator = (const list& l){
if (this != &l){
list(l).swap(*this);
}
return *this;
}
template<class T>
list<T>::~list(){
for (; head != tail;){
auto temp = head++;
//bug fix
nodeAllocator::destroy(temp.p);
nodeAllocator::deallocate(temp.p);
}
nodeAllocator::deallocate(tail.p);
}
template<class T>
void list<T>::push_front(const value_type& val){
auto node = newNode(val);
head.p->prev = node;
node->next = head.p;
head.p = node;
}
template<class T>
void list<T>::pop_front(){
auto oldNode = head.p;
head.p = oldNode->next;
head.p->prev = nullptr;
deleteNode(oldNode);
}
template<class T>
void list<T>::push_back(const value_type& val){
auto node = newNode();
(tail.p)->data = val;
(tail.p)->next = node;
node->prev = tail.p;
tail.p = node;
}
template<class T>
void list<T>::pop_back(){
auto newTail = tail.p->prev;
newTail->next = nullptr;
deleteNode(tail.p);
tail.p = newTail;
}
template<class T>
typename list<T>::iterator list<T>::insert(iterator position, const value_type& val){
auto node = newNode(val);
auto prev = position.p->prev;
node->next = position.p;
node->prev = prev;
prev->next = node;
position.p->prev = node;
return iterator(node);
}
template<class T>
void list<T>::insert(iterator position, size_type n, const value_type& val){
insert_aux(position, n, val, typename std::is_integral<InputIterator>::type());
}
template<class T>
template <class InputIterator>
void list<T>::insert(iterator position, InputIterator first, InputIterator last){
insert_aux(position, first, last, typename std::is_integral<InputIterator>::type());
}
template<class T>
typename list<T>::iterator list<T>::erase(iterator position){
if (position == head){
pop_front();
return head;
}
else{
auto prev = position.p->prev;
prev->next = position.p->next;
position.p->next->prev = prev;
deleteNode(position.p);
return iterator(prev->next);
}
}
template<class T>
typename list<T>::iterator list<T>::erase(iterator first, iterator last){
typename list<T>::iterator res;
for (; first != last;){
auto temp = first++;
res = erase(temp);
}
return res;
}
template<class T>
void list<T>::clear(){
erase(begin(), end());
}
template<class T>
void list<T>::reverse(){//<2F><><EFBFBD><EFBFBD>β<EFBFBD>
if (empty() || head.p->next == tail.p) return;
auto curNode = head.p;
head.p = tail.p->prev;
head.p->prev = nullptr;
do{
auto nextNode = curNode->next;
curNode->next = head.p->next;
head.p->next->prev = curNode;
head.p->next = curNode;
curNode->prev = head.p;
curNode = nextNode;
} while (curNode != head.p);
}
template<class T>
void list<T>::remove(const value_type& val){
for (auto it = begin(); it != end();){
if (*it == val)
it = erase(it);
else
++it;
}
}
template<class T>
template <class Predicate>
void list<T>::remove_if(Predicate pred){
for (auto it = begin(); it != end();){
if (pred(*it))
it = erase(it);
else
++it;
}
}
template<class T>
void list<T>::swap(list& x){
TinySTL::swap(head.p, x.head.p);
TinySTL::swap(tail.p, x.tail.p);
}
template<class T>
void swap(list<T>& x, list<T>& y){
x.swap(y);
}
template<class T>
void list<T>::unique(){
nodePtr curNode = head.p;
while (curNode != tail.p){
nodePtr nextNode = curNode->next;
if (curNode->data == nextNode->data){
if (nextNode == tail.p){
curNode->next = nullptr;
tail.p = curNode;
}
else{
curNode->next = nextNode->next;
nextNode->next->prev = curNode;
}
deleteNode(nextNode);
}
else{
curNode = nextNode;
}
}
}
template<class T>
template <class BinaryPredicate>
void list<T>::unique(BinaryPredicate binary_pred){
nodePtr curNode = head.p;
while (curNode != tail.p){
nodePtr nextNode = curNode->next;
if (binary_pred(curNode->data, nextNode->data)){
if (nextNode == tail.p){
curNode->next = nullptr;
tail.p = curNode;
}
else{
curNode->next = nextNode->next;
nextNode->next->prev = curNode;
}
deleteNode(nextNode);
}
else{
curNode = nextNode;
}
}
}
template<class T>
void list<T>::splice(iterator position, list& x){
this->insert(position, x.begin(), x.end());
x.head.p = x.tail.p;
}
template<class T>
void list<T>::splice(iterator position, list& x, iterator first, iterator last){
if (first.p == last.p) return;
auto tailNode = last.p->prev;
if (x.head.p == first.p){
x.head.p = last.p;
x.head.p->prev = nullptr;
}
else{
first.p->prev->next = last.p;
last.p->prev = first.p->prev;
}
if (position.p == head.p){
first.p->prev = nullptr;
tailNode->next = head.p;
head.p->prev = tailNode;
head.p = first.p;
}
else{
position.p->prev->next = first.p;
first.p->prev = position.p->prev;
tailNode->next = position.p;
position.p->prev = tailNode;
}
}
template<class T>
void list<T>::splice(iterator position, list& x, iterator i){
auto next = i;
this->splice(position, x, i, ++next);
}
template<class T>
void list<T>::merge(list& x){
auto it1 = begin(), it2 = x.begin();
while (it1 != end() && it2 != x.end()){
if (*it1 <= *it2)
++it1;
else{
auto temp = it2++;
this->splice(it1, x, temp);
}
}
if (it1 == end()){
this->splice(it1, x, it2, x.end());
}
}
template<class T>
template <class Compare>
void list<T>::merge(list& x, Compare comp){
auto it1 = begin(), it2 = x.begin();
while (it1 != end() && it2 != x.end()){
if (comp(*it2, *it1)){
auto temp = it2++;
this->splice(it1, x, temp);
}
else
++it1;
}
if (it1 == end()){
this->splice(it1, x, it2, x.end());
}
}
template <class T>
bool operator== (const list<T>& lhs, const list<T>& rhs){
auto node1 = lhs.head.p, node2 = rhs.head.p;
for (; node1 != lhs.tail.p && node2 != rhs.tail.p; node1 = node1->next, node2 = node2->next){
if (node1->data != node2->data)
break;
}
if (node1 == lhs.tail.p && node2 == rhs.tail.p)
return true;
return false;
}
template <class T>
bool operator!= (const list<T>& lhs, const list<T>& rhs){
return !(lhs == rhs);
}
template<class T>
void list<T>::sort(){
sort(TinySTL::less<T>());
}
template<class T>
template <class Compare>
void list<T>::sort(Compare comp){
if (empty() || head.p->next == tail.p)
return;
list carry;
list counter[64];
int fill = 0;
while (!empty()){
carry.splice(carry.begin(), *this, begin());
int i = 0;
while (i < fill && !counter[i].empty()){
counter[i].merge(carry, comp);
carry.swap(counter[i++]);
}
carry.swap(counter[i]);
if (i == fill)
++fill;
}
for (int i = 0; i != fill; ++i){
counter[i].merge(counter[i - 1], comp);
}
swap(counter[fill - 1]);
}
}
#endif

View File

@@ -11,7 +11,7 @@
namespace TinySTL{
template<class T>
class list;
namespace{
namespace Detail{
//the class of node
template<class T>
struct node{
@@ -36,24 +36,10 @@ namespace TinySTL{
public:
explicit listIterator(nodePtr ptr = nullptr) :p(ptr){}
listIterator& operator++(){
p = p->next;
return *this;
}
listIterator operator++(int){
auto res = *this;
++*this;
return res;
}
listIterator& operator --(){
p = p->prev;
return *this;
}
listIterator operator --(int){
auto res = *this;
--*this;
return res;
}
listIterator& operator++();
listIterator operator++(int);
listIterator& operator --();
listIterator operator --(int);
T& operator *(){ return p->data; }
T* operator &(){ return &(operator*()); }
@@ -62,27 +48,20 @@ namespace TinySTL{
template<class T>
friend bool operator !=(const listIterator<T>& lhs, const listIterator<T>& rhs);
};
template<class T>
bool operator ==(const listIterator<T>& lhs, const listIterator<T>& rhs){
return lhs.p == rhs.p;
}
template<class T>
bool operator !=(const listIterator<T>& lhs, const listIterator<T>& rhs){
return !(lhs == rhs);
}
}//end of namespace
//the class of list
template<class T>
class list{
template<class T>
friend struct listIterator;
private:
typedef allocator<node<T>> nodeAllocator;
typedef node<T> *nodePtr;
typedef allocator<Detail::node<T>> nodeAllocator;
typedef Detail::node<T> *nodePtr;
public:
typedef T value_type;
typedef listIterator<T> iterator;
typedef Detail::listIterator<T> iterator;
typedef reverse_iterator_t<iterator> reverse_iterator;
typedef T& reference;
typedef size_t size_type;
@@ -90,48 +69,16 @@ namespace TinySTL{
iterator head;
iterator tail;
public:
list(){
head.p = newNode();//add a dummy node
tail.p = head.p;
}
explicit list(size_type n, const value_type& val = value_type()){
ctorAux(n, val, std::is_integral<value_type>());
}
list();
explicit list(size_type n, const value_type& val = value_type());
template <class InputIterator>
list(InputIterator first, InputIterator last){
ctorAux(first, last, std::is_integral<InputIterator>());
}
list(const list& l){
head.p = newNode();//add a dummy node
tail.p = head.p;
for (auto node = l.head.p; node != l.tail.p; node = node->next)
push_back(node->data);
}
list& operator = (const list& l){
if (this != &l){
list(l).swap(*this);
}
return *this;
}
~list(){
for (; head != tail;){
auto temp = head++;
//bug fix
nodeAllocator::destroy(temp.p);
nodeAllocator::deallocate(temp.p);
}
nodeAllocator::deallocate(tail.p);
}
list(InputIterator first, InputIterator last);
list(const list& l);
list& operator = (const list& l);
~list();
bool empty()const{
return head == tail;
}
size_type size()const{
size_type length = 0;
for (auto h = head; h != tail; ++h)
++length;
return length;
}
bool empty()const{ return head == tail; }
size_type size()const;
reference front(){ return (head.p->data); }
reference back(){ return (tail.p->prev->data); }
@@ -170,45 +117,14 @@ namespace TinySTL{
void sort(Compare comp);
void reverse();
private:
void ctorAux(size_type n, const value_type& val, std::true_type){
head.p = newNode();//add a dummy node
tail.p = head.p;
while (n--)
push_back(val);
}
void ctorAux(size_type n, const value_type& val, std::true_type);
template <class InputIterator>
void ctorAux(InputIterator first, InputIterator last, std::false_type){
head.p = newNode();//add a dummy node
tail.p = head.p;
for (; first != last; ++first)
push_back(*first);
}
nodePtr newNode(const T& val = T()){
nodePtr res = nodeAllocator::allocate();
res->container = this;
//res->data = val; //-> bug
//nodeAllocator::construct(&(res->data), val);
TinySTL::construct(&(res->data), val);//fix
res->prev = nullptr;
res->next = nullptr;
return res;
}
void deleteNode(nodePtr p){
p->prev = nullptr;
p->next = nullptr;
nodeAllocator::deallocate(p);
}
void insert_aux(iterator position, size_type n, const T& val, std::true_type){
for (auto i = n; i != 0; --i){
position = insert(position, val);
}
}
void ctorAux(InputIterator first, InputIterator last, std::false_type);
nodePtr newNode(const T& val = T());
void deleteNode(nodePtr p);
void insert_aux(iterator position, size_type n, const T& val, std::true_type);
template<class InputIterator>
void insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type){
for (; first != last; ++first){
insert(position, *first);
}
}
void insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type);
public:
template<class T>
friend void swap(list<T>& x, list<T>& y);
@@ -217,273 +133,7 @@ namespace TinySTL{
template <class T>
friend bool operator!= (const list<T>& lhs, const list<T>& rhs);
};//end of List
template<class T>
void list<T>::push_front(const value_type& val){
auto node = newNode(val);
head.p->prev = node;
node->next = head.p;
head.p = node;
}
template<class T>
void list<T>::pop_front(){
auto oldNode = head.p;
head.p = oldNode->next;
head.p->prev = nullptr;
deleteNode(oldNode);
}
template<class T>
void list<T>::push_back(const value_type& val){
auto node = newNode();
(tail.p)->data = val;
(tail.p)->next = node;
node->prev = tail.p;
tail.p = node;
}
template<class T>
void list<T>::pop_back(){
auto newTail = tail.p->prev;
newTail->next = nullptr;
deleteNode(tail.p);
tail.p = newTail;
}
template<class T>
typename list<T>::iterator list<T>::insert(iterator position, const value_type& val){
auto node = newNode(val);
auto prev = position.p->prev;
node->next = position.p;
node->prev = prev;
prev->next = node;
position.p->prev = node;
return iterator(node);
}
template<class T>
void list<T>::insert(iterator position, size_type n, const value_type& val){
insert_aux(position, n, val, typename std::is_integral<InputIterator>::type());
}
template<class T>
template <class InputIterator>
void list<T>::insert(iterator position, InputIterator first, InputIterator last){
insert_aux(position, first, last, typename std::is_integral<InputIterator>::type());
}
template<class T>
typename list<T>::iterator list<T>::erase(iterator position){
if (position == head){
pop_front();
return head;
}else{
auto prev = position.p->prev;
prev->next = position.p->next;
position.p->next->prev = prev;
deleteNode(position.p);
return iterator(prev->next);
}
}
template<class T>
typename list<T>::iterator list<T>::erase(iterator first, iterator last){
typename list<T>::iterator res;
for (; first != last; ){
auto temp = first++;
res = erase(temp);
}
return res;
}
template<class T>
void list<T>::clear(){
erase(begin(), end());
}
template<class T>
void list<T>::reverse(){//<2F><><EFBFBD><EFBFBD>β<EFBFBD>
if (empty() || head.p->next == tail.p) return;
auto curNode = head.p;
head.p = tail.p->prev;
head.p->prev = nullptr;
do{
auto nextNode = curNode->next;
curNode->next = head.p->next;
head.p->next->prev = curNode;
head.p->next = curNode;
curNode->prev = head.p;
curNode = nextNode;
} while (curNode != head.p);
}
template<class T>
void list<T>::remove(const value_type& val){
for (auto it = begin(); it != end();){
if (*it == val)
it = erase(it);
else
++it;
}
}
template<class T>
template <class Predicate>
void list<T>::remove_if(Predicate pred){
for (auto it = begin(); it != end();){
if (pred(*it))
it = erase(it);
else
++it;
}
}
template<class T>
void list<T>::swap(list& x){
TinySTL::swap(head.p, x.head.p);
TinySTL::swap(tail.p, x.tail.p);
}
template<class T>
void swap(list<T>& x, list<T>& y){
x.swap(y);
}
template<class T>
void list<T>::unique(){
nodePtr curNode = head.p;
while (curNode != tail.p){
nodePtr nextNode = curNode->next;
if (curNode->data == nextNode->data){
if (nextNode == tail.p){
curNode->next = nullptr;
tail.p = curNode;
}else{
curNode->next = nextNode->next;
nextNode->next->prev = curNode;
}
deleteNode(nextNode);
}else{
curNode = nextNode;
}
}
}
template<class T>
template <class BinaryPredicate>
void list<T>::unique(BinaryPredicate binary_pred){
nodePtr curNode = head.p;
while (curNode != tail.p){
nodePtr nextNode = curNode->next;
if (binary_pred(curNode->data, nextNode->data)){
if (nextNode == tail.p){
curNode->next = nullptr;
tail.p = curNode;
}
else{
curNode->next = nextNode->next;
nextNode->next->prev = curNode;
}
deleteNode(nextNode);
}
else{
curNode = nextNode;
}
}
}
template<class T>
void list<T>::splice(iterator position, list& x){
this->insert(position, x.begin(), x.end());
x.head.p = x.tail.p;
}
template<class T>
void list<T>::splice(iterator position, list& x, iterator first, iterator last){
if (first.p == last.p) return;
auto tailNode = last.p->prev;
if (x.head.p == first.p){
x.head.p = last.p;
x.head.p->prev = nullptr;
}else{
first.p->prev->next = last.p;
last.p->prev = first.p->prev;
}
if (position.p == head.p){
first.p->prev = nullptr;
tailNode->next = head.p;
head.p->prev = tailNode;
head.p = first.p;
}else{
position.p->prev->next = first.p;
first.p->prev = position.p->prev;
tailNode->next = position.p;
position.p->prev = tailNode;
}
}
template<class T>
void list<T>::splice(iterator position, list& x, iterator i){
auto next = i;
this->splice(position, x, i, ++next);
}
template<class T>
void list<T>::merge(list& x){
auto it1 = begin(), it2 = x.begin();
while (it1 != end() && it2 != x.end()){
if (*it1 <= *it2)
++it1;
else{
auto temp = it2++;
this->splice(it1, x, temp);
}
}
if (it1 == end()){
this->splice(it1, x, it2, x.end());
}
}
template<class T>
template <class Compare>
void list<T>::merge(list& x, Compare comp){
auto it1 = begin(), it2 = x.begin();
while (it1 != end() && it2 != x.end()){
if (comp(*it2, *it1)){
auto temp = it2++;
this->splice(it1, x, temp);
}
else
++it1;
}
if (it1 == end()){
this->splice(it1, x, it2, x.end());
}
}
template <class T>
bool operator== (const list<T>& lhs, const list<T>& rhs){
auto node1 = lhs.head.p, node2 = rhs.head.p;
for (; node1 != lhs.tail.p && node2 != rhs.tail.p; node1 = node1->next, node2 = node2->next){
if (node1->data != node2->data)
break;
}
if (node1 == lhs.tail.p && node2 == rhs.tail.p)
return true;
return false;
}
template <class T>
bool operator!= (const list<T>& lhs, const list<T>& rhs){
return !(lhs == rhs);
}
template<class T>
void list<T>::sort(){
sort(TinySTL::less<T>());
}
template<class T>
template <class Compare>
void list<T>::sort(Compare comp){
if (empty() || head.p->next == tail.p)
return;
list carry;
list counter[64];
int fill = 0;
while (!empty()){
carry.splice(carry.begin(), *this, begin());
int i = 0;
while (i < fill && !counter[i].empty()){
counter[i].merge(carry, comp);
carry.swap(counter[i++]);
}
carry.swap(counter[i]);
if (i == fill)
++fill;
}
for (int i = 0; i != fill; ++i){
counter[i].merge(counter[i - 1], comp);
}
swap(counter[fill - 1]);
}
}
#include "Detail\List.impl.h"
#endif