diff --git a/TinySTL/Detail/List.impl.h b/TinySTL/Detail/List.impl.h new file mode 100644 index 0000000..57241f6 --- /dev/null +++ b/TinySTL/Detail/List.impl.h @@ -0,0 +1,401 @@ +#ifndef _LIST_IMPL_H_ +#define _LIST_IMPL_H_ + +namespace TinySTL{ + namespace Detail{ + template + listIterator& listIterator::operator++(){ + p = p->next; + return *this; + } + template + listIterator listIterator::operator++(int){ + auto res = *this; + ++*this; + return res; + } + template + listIterator& listIterator::operator --(){ + p = p->prev; + return *this; + } + template + listIterator listIterator::operator --(int){ + auto res = *this; + --*this; + return res; + } + template + bool operator ==(const listIterator& lhs, const listIterator& rhs){ + return lhs.p == rhs.p; + } + template + bool operator !=(const listIterator& lhs, const listIterator& rhs){ + return !(lhs == rhs); + } + }//end of Detail namespace + + template + void list::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 + template + void list::insert_aux(iterator position, InputIterator first, InputIterator last, std::false_type){ + for (; first != last; ++first){ + insert(position, *first); + } + } + template + typename list::nodePtr list::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 + void list::deleteNode(nodePtr p){ + p->prev = nullptr; + p->next = nullptr; + nodeAllocator::deallocate(p); + } + template + void list::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 + template + void list::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 + typename list::size_type list::size()const{ + size_type length = 0; + for (auto h = head; h != tail; ++h) + ++length; + return length; + } + template + list::list(){ + head.p = newNode();//add a dummy node + tail.p = head.p; + } + template + list::list(size_type n, const value_type& val = value_type()){ + ctorAux(n, val, std::is_integral()); + } + template + template + list::list(InputIterator first, InputIterator last){ + ctorAux(first, last, std::is_integral()); + } + template + list::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 + list& list::operator = (const list& l){ + if (this != &l){ + list(l).swap(*this); + } + return *this; + } + template + list::~list(){ + for (; head != tail;){ + auto temp = head++; + //bug fix + nodeAllocator::destroy(temp.p); + nodeAllocator::deallocate(temp.p); + } + nodeAllocator::deallocate(tail.p); + } + template + void list::push_front(const value_type& val){ + auto node = newNode(val); + head.p->prev = node; + node->next = head.p; + head.p = node; + } + template + void list::pop_front(){ + auto oldNode = head.p; + head.p = oldNode->next; + head.p->prev = nullptr; + deleteNode(oldNode); + } + template + void list::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 + void list::pop_back(){ + auto newTail = tail.p->prev; + newTail->next = nullptr; + deleteNode(tail.p); + tail.p = newTail; + } + template + typename list::iterator list::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 + void list::insert(iterator position, size_type n, const value_type& val){ + insert_aux(position, n, val, typename std::is_integral::type()); + } + template + template + void list::insert(iterator position, InputIterator first, InputIterator last){ + insert_aux(position, first, last, typename std::is_integral::type()); + } + template + typename list::iterator list::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 + typename list::iterator list::erase(iterator first, iterator last){ + typename list::iterator res; + for (; first != last;){ + auto temp = first++; + res = erase(temp); + } + return res; + } + template + void list::clear(){ + erase(begin(), end()); + } + template + void list::reverse(){//采用尾插法 + 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 + void list::remove(const value_type& val){ + for (auto it = begin(); it != end();){ + if (*it == val) + it = erase(it); + else + ++it; + } + } + template + template + void list::remove_if(Predicate pred){ + for (auto it = begin(); it != end();){ + if (pred(*it)) + it = erase(it); + else + ++it; + } + } + template + void list::swap(list& x){ + TinySTL::swap(head.p, x.head.p); + TinySTL::swap(tail.p, x.tail.p); + } + template + void swap(list& x, list& y){ + x.swap(y); + } + template + void list::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 + template + void list::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 + void list::splice(iterator position, list& x){ + this->insert(position, x.begin(), x.end()); + x.head.p = x.tail.p; + } + template + void list::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 + void list::splice(iterator position, list& x, iterator i){ + auto next = i; + this->splice(position, x, i, ++next); + } + template + void list::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 + template + void list::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 + bool operator== (const list& lhs, const list& 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 + bool operator!= (const list& lhs, const list& rhs){ + return !(lhs == rhs); + } + template + void list::sort(){ + sort(TinySTL::less()); + } + template + template + void list::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 \ No newline at end of file diff --git a/TinySTL/List.h b/TinySTL/List.h index 21a773c..465f362 100644 --- a/TinySTL/List.h +++ b/TinySTL/List.h @@ -11,7 +11,7 @@ namespace TinySTL{ template class list; - namespace{ + namespace Detail{ //the class of node template 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 friend bool operator !=(const listIterator& lhs, const listIterator& rhs); }; - template - bool operator ==(const listIterator& lhs, const listIterator& rhs){ - return lhs.p == rhs.p; - } - template - bool operator !=(const listIterator& lhs, const listIterator& rhs){ - return !(lhs == rhs); - } }//end of namespace + //the class of list template class list{ template friend struct listIterator; private: - typedef allocator> nodeAllocator; - typedef node *nodePtr; + typedef allocator> nodeAllocator; + typedef Detail::node *nodePtr; public: typedef T value_type; - typedef listIterator iterator; + typedef Detail::listIterator iterator; typedef reverse_iterator_t 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()); - } + list(); + explicit list(size_type n, const value_type& val = value_type()); template - list(InputIterator first, InputIterator last){ - ctorAux(first, last, std::is_integral()); - } - 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 - 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 - 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 friend void swap(list& x, list& y); @@ -217,273 +133,7 @@ namespace TinySTL{ template friend bool operator!= (const list& lhs, const list& rhs); };//end of List - - template - void list::push_front(const value_type& val){ - auto node = newNode(val); - head.p->prev = node; - node->next = head.p; - head.p = node; - } - template - void list::pop_front(){ - auto oldNode = head.p; - head.p = oldNode->next; - head.p->prev = nullptr; - deleteNode(oldNode); - } - template - void list::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 - void list::pop_back(){ - auto newTail = tail.p->prev; - newTail->next = nullptr; - deleteNode(tail.p); - tail.p = newTail; - } - template - typename list::iterator list::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 - void list::insert(iterator position, size_type n, const value_type& val){ - insert_aux(position, n, val, typename std::is_integral::type()); - } - template - template - void list::insert(iterator position, InputIterator first, InputIterator last){ - insert_aux(position, first, last, typename std::is_integral::type()); - } - template - typename list::iterator list::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 - typename list::iterator list::erase(iterator first, iterator last){ - typename list::iterator res; - for (; first != last; ){ - auto temp = first++; - res = erase(temp); - } - return res; - } - template - void list::clear(){ - erase(begin(), end()); - } - template - void list::reverse(){//采用尾插法 - 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 - void list::remove(const value_type& val){ - for (auto it = begin(); it != end();){ - if (*it == val) - it = erase(it); - else - ++it; - } - } - template - template - void list::remove_if(Predicate pred){ - for (auto it = begin(); it != end();){ - if (pred(*it)) - it = erase(it); - else - ++it; - } - } - template - void list::swap(list& x){ - TinySTL::swap(head.p, x.head.p); - TinySTL::swap(tail.p, x.tail.p); - } - template - void swap(list& x, list& y){ - x.swap(y); - } - template - void list::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 - template - void list::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 - void list::splice(iterator position, list& x){ - this->insert(position, x.begin(), x.end()); - x.head.p = x.tail.p; - } - template - void list::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 - void list::splice(iterator position, list& x, iterator i){ - auto next = i; - this->splice(position, x, i, ++next); - } - template - void list::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 - template - void list::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 - bool operator== (const list& lhs, const list& 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 - bool operator!= (const list& lhs, const list& rhs){ - return !(lhs == rhs); - } - template - void list::sort(){ - sort(TinySTL::less()); - } - template - template - void list::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 \ No newline at end of file