概述
List是STL中常用的容器之一,List将元素按顺序储存到链表中,在快速删除和快速插入方面比vector高出许多。STL中的list是一双向链表,具有指向前一节点和后一节点的指针。那么我们开始写一个属于自己的List吧。
list的节点
list的节点应由指向前一节点的指针,指向后一节点的指针一节储存的元素构成。那么我给出节点的定义
template <typename Object> struct Node {
Object object;
Node<Object> *previous;//指向前一节点
Node<Object> *next;//指向后一节点
Node(const Object&obj) :object(obj), next(NULL),previous(NULL) {}
Node():next(NULL),previous(NULL){}
};
迭代器的实现
迭代器类似于指针类型,它也提供了对对象的间接访问。我们可以通过迭代器的遍历来遍历整个链表,也可通过操作迭代器来删除或插入元素。
STL中迭代器有两种:iterator和const_iterator。前一种允许通过迭代器来改变元素的值,后一种则不允许通过迭代器来改变元素值。
我们可以将const_iterator作为父类,iterator作为基类。
template <typename Object> class const_iterator {
protected:
Node<Object>* current;
Object& retrieve()const { return current->data; }
public:
const_iterator() :current(NULL) {}
const Object&operator*()const;
const_iterator &operator++(int);
const_iterator&operator++();
bool operator==(const const_iterator&);
bool operator!=(const const_iterator&);
friend class List<Object>;
};
template <typename Object> const Object& const_iterator<Object>::operator*() const {
return current->object;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++(int) {
const_iterator old = *this;
++(*this);
return old;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++() {
current = current->next;
return *this;
}
template <typename Object>bool const_iterator<Object>::operator==(const const_iterator &rhs) {
return current == rhs.current ? true : false;
}
template <typename Object>bool const_iterator<Object>::operator!=(const const_iterator &rhs) {
return !(this->current == rhs.current);
}
通过重载++,==等运算符,使我们的迭代器实现自增以及比较是否相等的功能。
下面是iterator的代码:
template <typename Object> class iterator :public const_iterator<Object> {
public:
iterator() {}
Object&operator*() { return const_iterator<Object>::current->object; }
const Object&operator*()const { return const_iterator<Object>::operator*(); }
iterator&operator++() {
const_iterator<Object>::current = const_iterator<Object>::current->next;
return *this;
}
iterator&operator++(int) {
iterator old = *this;
++(*this);
return old;
}
friend class List<Object>;
};
List的实现
前面说到list用双向链表实现,我们可以在list中设置一个没有储存元素的头结点和尾节点,这样可以使插入删除等操作变得相同,即无论头结点是否为空,都执行相投操作。以及在向后插入元素时,由于记住了尾节点,只需要O(1)的复杂度。我们仅仅只用了两个空的节点,就极大的提高了效率。
在编写代码的时候值得注意的是,防止野指针的出现,以及别搞错了指针的指向。
template <typename Object> class List {
private:
Node<Object> *head;
Node<Object> *tail;
int theSize;
public:
typedef iterator<Object> iterator;
typedef const_iterator<Object> const_iterator;
List();
~List();
List(const List<Object>&);
List(unsigned initSize);
void push_back(const Object&);
void push_front(const Object&);
void pop_front();
void pop_back();
bool empty();
void clear();
void resize(unsigned);
const Object& front();
const Object& back();
int size()const;
void insert(iterator, const Object&);
void remove(const Object&);
const List<Object>&operator=(const List<Object>&);
iterator begin() {
iterator it;
it.current = head->next;
return it;
}
iterator end() {
iterator it;
it.current = tail;
return it;
}
const_iterator begin()const{
const_iterator it;
it.current=head->next;
return it;
}
const_iterator end()const{
const_iterator it;
it.current=tail;
return it;
}
iterator erase(iterator it){
if(it!=end()&&!empty()){
Node<Object>*tmp=it.current;
Node<Object>*p=tmp;
tmp->previous->next=tmp->next;
tmp=tmp->next;
delete p;
iterator to;
to.current=tmp;
--theSize;
return to;
}
}
};
template <typename Object> List<Object>::~List() {
clear();
delete head;
delete tail;
}
template <typename Object> List<Object>::List() :head(new Node<Object>()), theSize(0),tail(new Node<Object>()) {
tail->previous=head;
head->next=tail;
}
template <typename Object> List<Object>::List(unsigned initSize) : head(new Node<Object>()),theSize(initSize),tail(new Node<Object>()) {
tail->previous=head;
head->next=tail;
for (int i = 0; i < theSize; i++) {
Node<Object>*tmp = new Node<Object>();
tail->previous->next=tmp;
tmp->previous=tail->previous;
tail->previous=tmp;
tmp->next=tail;
}
}
template <typename Object> List<Object>::List(const List<Object> &rhs):head(new Node<Object>()),tail(new Node<Object>()),theSize(0) {
tail->previous=head;
head->next=tail;
for(const_iterator it=rhs.begin();it!=rhs.end();++it)
push_back(*it);
}
template <typename Object> const List<Object>& List<Object>::operator=(const List<Object> &rhs) {
if(this==&rhs)return *this;
clear();
for(const_iterator it=rhs.begin();it!=rhs.end();++it)
push_back(*it);
return *this;
}
template <typename Object> void List<Object>::push_back(const Object &rhs) {
Node<Object>*tmp=new Node<Object>(rhs);
tail->previous->next=tmp;
tmp->previous=tail->previous;
tail->previous=tmp;
tmp->next=tail;
++theSize;
}
template <typename Object> void List<Object>::pop_back() {
if(empty())return;
else{
Node<Object>*tmp=tail->previous;
tmp->previous->next=tail;
tail->previous=tmp->previous;
delete tmp;
--theSize;
}
}
template <typename Object> void List<Object>::push_front(const Object &obj) {
Node<Object>*tmp = new Node<Object>(obj);
tmp->previous=head;
head->next->previous=tmp;
tmp->next = head->next;
head->next = tmp;
++theSize;
}
template <typename Object> void List<Object>::pop_front() {
if (empty()) return;
else {
Node<Object>*tmp = head->next;
head->next = tmp->next;
delete tmp;
--theSize;
}
}
template <typename Object> int List<Object>::size() const {
return theSize;
}
template <typename Object> bool List<Object>::empty() {
return theSize == 0 ? true : false;
}
template <typename Object> void List<Object>::clear() {
while (!empty()){
pop_back();
}
}
template <typename Object> const Object& List<Object>::front() {
if (!empty())
return head->next->object;
}
template <typename Object> const Object& List<Object>::back() {
if(!empty()){
return tail->previous->object;
}
}
template <typename Object> void List<Object>::remove(const Object &obj) {
if(empty())return;
else{
Node<Object>*tmp=head->next;
while(tmp!=tail){
if(tmp->object==obj){
Node<Object>*p=tmp;
tmp->previous->next=tmp->next;
tmp->next->previous=p->previous;
tmp=tmp->next;
std::cout<<"remove()"<<p->object<<std::endl;
delete p;
p=NULL;
--theSize;
}
else
tmp=tmp->next;
}
}
}
template <typename Object> void List<Object>::resize(unsigned newSize) {
if(newSize==theSize)return;
else if(newSize<theSize){
int num=theSize-newSize;
for(int i=0;i<num;i++) {
std::cout<<"pop"<<back()<<" ";
pop_back();
}
}
else{
int num=newSize-theSize;
for(int i=0;i<num;i++)
push_back(Object());
}
}
template <typename Object> const Object& const_iterator<Object>::operator*() const {
return current->object;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++(int) {
const_iterator old = *this;
++(*this);
return old;
}
template <typename Object> const_iterator<Object>& const_iterator<Object>::operator++() {
current = current->next;
return *this;
}
template <typename Object>bool const_iterator<Object>::operator==(const const_iterator &rhs) {
return current == rhs.current ? true : false;
}
template <typename Object>bool const_iterator<Object>::operator!=(const const_iterator &rhs) {
return !(this->current == rhs.current);
}
template <typename Object>void List<Object>::insert(iterator it, const Object &obj) {
Node<Object> *tmp = it.current;
Node<Object>* p = new Node<Object>(obj);
tmp->previous->next=p;
p->next = tmp;
p->previous=tmp->previous;
tmp->previous=p;
++theSize;
}
最后
如有错误,欢迎大家批评交流!