C++ List 双向链表 实现 会用也要会写
2015-08-25 17:45
387 查看
转载自:http://blog.csdn.net/u011408355/article/details/47731021
这次的代码比较长,原因是比之前的Vector实现增加了许多的操作,而且毕竟指针操作嘛,处理起来稍微麻烦一点。
List实现中非常重要的一点,就是定义一个头指针和一个尾指针,这样可以避免对很多的特殊情况的处理,当链表为空时就是头指针指向尾指针,另外一个就是迭代器的实现,
list的迭代器的实现比vector要麻烦许多,因为内存不连续,所有采用了内部嵌套类的方式,重载了*(解引用),++EXP(前置++),++EXP(后置++),==和!=等操作符。
具体的大家可以看代码。
[cpp] view
plaincopy
<span style="font-size:14px;">//链表
template<typename T>
class List{
private:
//定义节点,并设置一个节点的初始化函数
struct Node{
T t;
Node* pre;
Node* next;
Node(T tVal=T(),Node* preVal=NULL,Node* nextVal=NULL):t(tVal),pre(preVal),next(nextVal){}
};
public:
/*const迭代器和非const迭代器的实现,因为const迭代器只是作为对数据的保护,很多操作都是相同的因此这里采用了继承*/
class const_iterator{
public:
const_iterator():current(NULL){}
const T& operator*() const{
return retrieve();
}
//重载相关的操作符
const_iterator& operator++(){
current=current->next;
return *this;
}
const_iterator operator++(int){
const_iterator old=*this;
++(*this);
return old;
}
bool operator==(const_iterator& rhs) const{
return current==rhs.current;
}
bool operator!=(const_iterator& rhs)const{
return current!=rhs.current;
}
protected:
Node* current;
T& retrieve() const{
return current->t;
}
const_iterator(Node* p):current(p){}
friend class List<T>;
};
class iterator:public const_iterator{
public:
iterator():current(NULL){}
T& operator*(){
return retrieve();
}
iterator& operator++(){
current=current->next;
return *this;
}
iterator operator++(int){
iterator old=*this;
current=current->next;
return old;
}
const T& operator*()const{
return const_iterator::operator*();
}
protected:
iterator(Node* p):const_iterator(p){}
friend class List<T>;
};
public:
/* 构造函数和析构函数,init函数属于private成员,因此放在下面*/
List(){
init();
}
List(const List& rhs){
init();
operator=(rhs);
}
~List(){
clear();
delete head;
delete tail;
}
//重载操作符
const List& operator=(const List& rhs){
for(const_iterator cite=rhs.begin();cite!=rhs.end();cite++){
push_back(*cite);
}
return *this;
}
T& operator[](int index){
iterator ite=begin();
for(int i=0;i<index;i++)
ite++;
return *ite;
}
//相关的操作函数
T& front(){
return *begin();
}
const T& front()const{
return *begin();
}
T& back(){
return *(--end());
}
const T& back()const{
return *(--end());
}
void push_front(T t){
Node* p=new Node(t);
p->next=head->next;
p->pre=head;
p->next->pre=p;
head->next=p;
theSize++;
}
void push_back(T t){
Node* p=new Node(t);
p->pre=tail->pre;
p->next=tail;
p->pre->next=p;
tail->pre=p;
theSize++;
}
void pop_front(){
Node* p=head->next;
head->next=p->next;
p->next->pre=head;
delete p;
theSize--;
}
void pop_back(){
Node* p=tail->pre;
tail->pre=p->pre;
p->pre->next=tail;
delete p;
theSize--;
}
void insert(iterator itr,T t){
Node* p=new Node(t);
p->next=itr.current;
p->pre=itr.current->pre;
itr.current->pre->next=p;
itr.current->pre=p;
theSize++;
}
iterator erase(iterator itr){
Node* p=itr.current->next;
p->pre=itr.current->pre;
p->pre->next=p;
delete itr.current;
return iterator(p);
theSize--;
}
void erase(iterator start,iterator end){
for(iterator ite=start;ite!=end){
ite=erase(ite);
theSize--;
}
}
iterator begin(){
return iterator(head->next);
}
const_iterator begin() const{
return const_iterator(head->next);
}
iterator end(){
return iterator(tail);
}
const_iterator end() const{
return const_iterator(tail);
}
int size()const{
return theSize;
}
bool empty()const{
return theSize==0;
}
void clear(){
while(theSize!=0){
pop_back();
}
}
private:
int theSize;
Node* head;
Node* tail;
void init(){
theSize=0;
head=new Node();
tail=new Node();
head->next=tail;
tail->pre=head;
}
};</span>
有疑问或是发现错误,欢迎留言。
这次的代码比较长,原因是比之前的Vector实现增加了许多的操作,而且毕竟指针操作嘛,处理起来稍微麻烦一点。
List实现中非常重要的一点,就是定义一个头指针和一个尾指针,这样可以避免对很多的特殊情况的处理,当链表为空时就是头指针指向尾指针,另外一个就是迭代器的实现,
list的迭代器的实现比vector要麻烦许多,因为内存不连续,所有采用了内部嵌套类的方式,重载了*(解引用),++EXP(前置++),++EXP(后置++),==和!=等操作符。
具体的大家可以看代码。
[cpp] view
plaincopy
<span style="font-size:14px;">//链表
template<typename T>
class List{
private:
//定义节点,并设置一个节点的初始化函数
struct Node{
T t;
Node* pre;
Node* next;
Node(T tVal=T(),Node* preVal=NULL,Node* nextVal=NULL):t(tVal),pre(preVal),next(nextVal){}
};
public:
/*const迭代器和非const迭代器的实现,因为const迭代器只是作为对数据的保护,很多操作都是相同的因此这里采用了继承*/
class const_iterator{
public:
const_iterator():current(NULL){}
const T& operator*() const{
return retrieve();
}
//重载相关的操作符
const_iterator& operator++(){
current=current->next;
return *this;
}
const_iterator operator++(int){
const_iterator old=*this;
++(*this);
return old;
}
bool operator==(const_iterator& rhs) const{
return current==rhs.current;
}
bool operator!=(const_iterator& rhs)const{
return current!=rhs.current;
}
protected:
Node* current;
T& retrieve() const{
return current->t;
}
const_iterator(Node* p):current(p){}
friend class List<T>;
};
class iterator:public const_iterator{
public:
iterator():current(NULL){}
T& operator*(){
return retrieve();
}
iterator& operator++(){
current=current->next;
return *this;
}
iterator operator++(int){
iterator old=*this;
current=current->next;
return old;
}
const T& operator*()const{
return const_iterator::operator*();
}
protected:
iterator(Node* p):const_iterator(p){}
friend class List<T>;
};
public:
/* 构造函数和析构函数,init函数属于private成员,因此放在下面*/
List(){
init();
}
List(const List& rhs){
init();
operator=(rhs);
}
~List(){
clear();
delete head;
delete tail;
}
//重载操作符
const List& operator=(const List& rhs){
for(const_iterator cite=rhs.begin();cite!=rhs.end();cite++){
push_back(*cite);
}
return *this;
}
T& operator[](int index){
iterator ite=begin();
for(int i=0;i<index;i++)
ite++;
return *ite;
}
//相关的操作函数
T& front(){
return *begin();
}
const T& front()const{
return *begin();
}
T& back(){
return *(--end());
}
const T& back()const{
return *(--end());
}
void push_front(T t){
Node* p=new Node(t);
p->next=head->next;
p->pre=head;
p->next->pre=p;
head->next=p;
theSize++;
}
void push_back(T t){
Node* p=new Node(t);
p->pre=tail->pre;
p->next=tail;
p->pre->next=p;
tail->pre=p;
theSize++;
}
void pop_front(){
Node* p=head->next;
head->next=p->next;
p->next->pre=head;
delete p;
theSize--;
}
void pop_back(){
Node* p=tail->pre;
tail->pre=p->pre;
p->pre->next=tail;
delete p;
theSize--;
}
void insert(iterator itr,T t){
Node* p=new Node(t);
p->next=itr.current;
p->pre=itr.current->pre;
itr.current->pre->next=p;
itr.current->pre=p;
theSize++;
}
iterator erase(iterator itr){
Node* p=itr.current->next;
p->pre=itr.current->pre;
p->pre->next=p;
delete itr.current;
return iterator(p);
theSize--;
}
void erase(iterator start,iterator end){
for(iterator ite=start;ite!=end){
ite=erase(ite);
theSize--;
}
}
iterator begin(){
return iterator(head->next);
}
const_iterator begin() const{
return const_iterator(head->next);
}
iterator end(){
return iterator(tail);
}
const_iterator end() const{
return const_iterator(tail);
}
int size()const{
return theSize;
}
bool empty()const{
return theSize==0;
}
void clear(){
while(theSize!=0){
pop_back();
}
}
private:
int theSize;
Node* head;
Node* tail;
void init(){
theSize=0;
head=new Node();
tail=new Node();
head->next=tail;
tail->pre=head;
}
};</span>
有疑问或是发现错误,欢迎留言。
相关文章推荐
- C语言动态内存分配函数解析
- const的常见用法
- 排序算法之希尔排序(C语言实现)
- MFC视频教程(孙鑫)学习笔记2-掌握C++
- 一个包含所有c++的头文件的头文件
- 程序崩溃时自动记录minidump的c++类
- C语言多文件编译
- 常见的字符串匹配算法对比实现C语言版本
- Effective C++ 条款22 将成员变量声明为private
- 黑马程序员——C语言中的标识符
- 常见的排序算法对比及实现C语言版本
- C++ 关键字typeid 运行时类型检查
- Effective C++ 条款21必须返回对象时,别妄想返回其reference
- C/C++的编译与运行
- C++中空类的大小
- C++中类对象所占空间的大小
- 常见的查找算法C语言版本
- 【深入理解C++】从初始化列表和构造函数谈C++的初始化机制
- c++常见面试题30道
- C++初始化列表