#ifndef unrolled_h_ #define unrolled_h_ #ifndef iostream_h_ #define iostream_h_ #include #endif const int NUM_ELEMENTS_PER_NODE=6; template class Node { public: Node() : next_(NULL), prev_(NULL), num_elements(0) {}; Node(const T& v); // REPRESENTATION T value_[NUM_ELEMENTS_PER_NODE]; Node* next_; Node* prev_; unsigned int num_elements; }; template Node::Node(const T& v) { next_=NULL; prev_=NULL; num_elements=1; value_[0]=v; } //Definition of list_iterator, so UnrolledLL can use it template class list_iterator; template class UnrolledLL { public: UnrolledLL() : head_(NULL), tail_(NULL), size_(0) {} UnrolledLL(const UnrolledLL& old) { this->copy_list(old); } ~UnrolledLL() { this->destroy_list(); } UnrolledLL& operator= (const UnrolledLL& old); //Some basic functions unsigned int size() const { return size_; } bool empty() const { return head_ == NULL; } void clear() { this->destroy_list(); } //Front, back const T& front() const { return head_->value_[0]; } T& front() { return head_->value_[0]; } const T& back() const { return tail_->value_[tail_->num_elements]; } T& back() { return tail_->value_[tail_->num_elements]; } //Entering new data void push_front(const T& v); void pop_front(); void push_back(const T& v); void pop_back(); //Iterator functions typedef list_iterator iterator; iterator begin() { return iterator(head_); } iterator end() { return iterator(end_); } list_iterator erase(iterator itr); list_iterator insert(iterator itr, T const& v); private: void copy_list(const UnrolledLL& old); void destroy_list(); Node* end_; Node* head_; Node* tail_; unsigned int size_; }; template list_iterator UnrolledLL::insert(iterator itr, T const& v) { //Push front, if itr is at begin() if(itr==this->begin()) { this->push_front(v); itr++; return itr; } //Push back, if itr is at end() if(itr==this->end()) { this->push_back(v); return itr; } //If itr is at the beginning of a full node, create a new node if(itr.offset==0 && itr.ptr_->num_elements==NUM_ELEMENTS_PER_NODE) { Node* temp=new Node(v); temp->next_=itr.ptr_; temp->prev_=itr.ptr_->prev_; temp->prev_->next_=temp; itr.ptr_->prev_=temp; return itr; } //If itr is somewhere else in a full node, create a new node if(itr.ptr_->num_elements==NUM_ELEMENTS_PER_NODE) { Node* temp=new Node(itr.ptr_->value_[NUM_ELEMENTS_PER_NODE-1]); int x; for(x=NUM_ELEMENTS_PER_NODE-1 ; x>=itr.offset ; x--) itr.ptr_->value_[x]=itr.ptr_->value_[x-1]; itr.ptr_->value_[itr.offset-1]=v; return itr; } //If itr is in a node with room for the new element { int x; for(x=itr.ptr_->num_elements-1;x>=itr.offset ; x--) itr.ptr_->value_[x]=itr.ptr_->value_[x-1]; itr.ptr_->value_[itr.offset-1]=v; itr.ptr_->num_elements=itr.ptr_->num_elements+1; return itr; } } template list_iterator UnrolledLL::erase(iterator itr) { //Size=1 if(size_==1) { destroy_list(); itr=NULL; return itr; } //Number of elements in node=1, head node if((itr.ptr_)->num_elements==1 && (itr.ptr_)==(this->head_)) { head_=head_->next_; itr++; delete head_->prev_; head_->prev_=NULL; return itr; } //Number of elements in node=1, tail node if((itr.ptr_)->num_elements==1 && (itr.ptr_)==(this->tail_)) { tail_=tail_->prev_; delete tail_->next_; tail_->next_=end_; end_->prev_=tail_; itr=NULL; return itr; } //First element if(itr.ptr_==(this->head_) && itr.offset==0) { this->pop_front(); return itr; } //Last element if(itr.ptr_==(this->tail_) && itr.offset==(itr.ptr_)->num_elements-1) { this->pop_back(); return itr; } //Only one element in node if(itr.ptr_->num_elements==1) { itr++; itr.ptr_->prev_=itr.ptr_->prev_->prev_; delete itr.ptr_->prev_->next_; itr.ptr_->prev_->next_=itr.ptr_; return itr; } //Last element in node if(itr.offset==itr.ptr_->num_elements-1) { itr.ptr_->num_elements=itr.ptr_->num_elements-1; itr++; return itr; } //Normal case... More than one element in the node, not the last element in the node, and not the very first element in the list int x; for(x=itr.offset; x < itr.ptr_->num_elements;x++) itr.ptr_->value_[x]=itr.ptr_->value_[x+1]; itr.ptr_->num_elements=itr.ptr_->num_elements-1; return itr; } template UnrolledLL& UnrolledLL::operator= (const UnrolledLL& old) { if (&old != this) { this->destroy_list(); this->copy_list(old); } return *this; } template void UnrolledLL::copy_list(const UnrolledLL& old) { size_=old.size_; //empty list if(size_==0) { head_=tail_=end_=0; return; } //Create an appropritate number of nodes Node* temp=new Node; head_=tail_=temp; for(int x=0;x<((size_-1)/6);x++) { temp=new Node; tail_->next_=temp; temp->prev_=tail_; tail_=temp; } end_=new Node; end_->prev_=tail_; tail_->next_=end_; //The minimum number of nodes has been created; head_, tail_, and end_ point to the correct spots, now fill in values list_iterator p=old.head_; list_iterator q=this->begin(); for(p;p != old.end_;p++) { *q=*p; q++; } } template void UnrolledLL::destroy_list() { if(head_==tail_) delete head_; if(head_!=tail_) { list_iterator p=head_; p++; for(p;p!=end_;p++) { delete (p.ptr_)->prev_; } delete p.ptr_; } delete end_; head_=NULL; tail_=NULL; end_=NULL; } template std::ostream& operator<<(std::ostream& os, UnrolledLL a) { list_iterator itr=a.begin(); for(itr ; itr != a.end() ; itr++) os << *itr << " "; return os; } template void UnrolledLL::push_front(const T& v) { //If there is no Node in existence if(!tail_) { Node* temp=new Node(v); head_=tail_=temp; end_=new Node; end_ -> prev_ = tail_; tail_ -> next_ = end_; size_++; return; } //If the current head Node is full if(head_ -> num_elements==NUM_ELEMENTS_PER_NODE) { Node*temp=new Node(v); head_ -> next_ = temp; temp -> prev_ = head_; head_=temp; } //If the current head Node has more room if(head_ -> num_elementsnum_elements-1;x==0;x++) { head_ -> value_[x+1] = head_ -> value_[x]; } head_ -> value_[0]=v; head_ -> num_elements = head_ -> num_elements + 1; } } template void UnrolledLL::pop_front() { //This is assuming there's a node in existence //Normal case, if head has more than one value if(head_ -> num_elements > 1) { for(int x=0;x< head_ -> num_elements; x++) { head_->value_[x]=head_->value_[x+1]; } head_->num_elements=head_->num_elements-1; } //If head has only one value, but there are other nodes if(head_-> num_elements==1 && size_>1) { head_=head_->next_; delete head_->prev_; head_->prev_=NULL; } //If there's only one value total, everything goes to null if(size_==1) { delete head_; delete end_; head_=NULL; tail_=NULL; end_=NULL; } size_--; } template void UnrolledLL::pop_back() { //This is assuming there's a node in existance //Normal case, if tail has more than one value if(tail_ -> num_elements > 1) { tail_-> num_elements = tail_-> num_elements -1; } //If tail has only one value, but there are other nodes if(tail_-> num_elements==1 && size_>1) { tail_=tail_->prev_; delete tail_->next_; tail_->next_=end_; end_->prev_=tail_; } //If there's only one value total, everything goes to null if(size_==1) { delete head_; delete end_; head_=NULL; tail_=NULL; end_=NULL; } size_--; } template void UnrolledLL::push_back(const T& v) { //If there is no Node in existence if(!tail_) { Node* temp=new Node(v); head_=tail_=temp; end_=new Node; end_ -> prev_ = tail_; tail_ -> next_ = end_; } //If the current tail Node is full if(tail_ -> num_elements==NUM_ELEMENTS_PER_NODE) { Node* temp=new Node(v); tail_ -> next_ = temp; temp -> prev_ = tail_; tail_=temp; tail_ -> next_ = end_; end_ -> prev_ = tail_; } //If the current tail Node has more room if(tail_ -> num_elements value_[tail_ -> num_elements]=v; tail_ -> num_elements = tail_ -> num_elements++; } size_++; } template class list_iterator { public: list_iterator() : ptr_(NULL), offset(0) {}; list_iterator(Node* p) : ptr_(p), offset(0) {}; list_iterator(Node* p, int q): ptr_(p), offset(q) {}; list_iterator(list_iterator const& old) : ptr_(old.ptr_) {} ~list_iterator() {}; list_iterator & operator=(const list_iterator & old) { ptr_ = old.ptr_; return *this; } // dereferencing operator gives access to the value at the pointer T& operator*() { return ptr_->value_[offset]; } // increment operator list_iterator & operator++() { if(offset==ptr_->num_elements-1) { ptr_ = ptr_->next_; offset=0; } if(offsetnum_elements-1) { offset++; } return *this; } list_iterator operator++(int) { list_iterator temp(*this); if(offset==ptr_->num_elements-1) { ptr_ = ptr_->next_; offset=0; } if(offsetnum_elements-1) { offset++; } return temp; } // decrement operator list_iterator & operator--() { if(offset==0) { ptr_ = ptr_->prev_; offset=ptr_->num_elements-1; } if(offset>0) { offset--; } return *this; } list_iterator operator--(int) { list_iterator temp(*this); if(offset==0) { ptr_=ptr_->prev_; offset=ptr_->num_elements-1; } if(offset>0) { offset--; } return *this; } friend class UnrolledLL; // comparison friend bool operator==(const list_iterator& l, const list_iterator& r) { return l.ptr_ == r.ptr_; } friend bool operator!=(const list_iterator& l, const list_iterator& r) { return l.ptr_ != r.ptr_; } private: Node* ptr_; unsigned int offset; }; #endif