C++自己实现list
C++自己实现list
前两个博客发表了自己写的stack(栈)和queue(队列),感觉比较简单,今天想试着实现list,结果发现,不是那么容易,感觉自己对STL的底层不是很了解,
真要自己实现还真的很难,看STL的源代码,那个晕啊...那代码也写得太难理解了,当然跟我不了解有关,但我相信,在将来的某一天我会懂的,你看我的代码也会懂的。
话说:STL中的list的内部结构就是一个双向链表,这个东东以前还真没有玩过,就凭他用的是双向链表我就不想用他,指针太多,耗资源,当然存在就有他的价值,
他能快速访问其中的元素。 废话总该少说,代码就该多些。
有那么一点高兴的是实现双向链表的翻转,其他的没什么了,list还没有实现,由于现在能力有限,新的版本一定会发布的,你就将就着看吧!
源码
#include <iostream>
usingnamespace std;
template<typename T>
class list
{
public :
list()
{
initialize();
}
list(int count)
{
initialize();
if(count>0)
{
for(int i=0;i<count;i++)
{
push_front(0);
}
}
}
list(int count,T data)
{
initialize();
if(count>0)
{
for(int i=0;i<count;i++)
{
push_front(data);
}
}
}
//显示最后一个节点
T& back()
{
checkEmpty();
return cur->data;
}
T& back() const
{
return back();
}
//显示第一个节点
T& front()
{
checkEmpty();
return head->next->data;
}
T& front() const
{
return front();
}
//弹出最后一个节点
void pop_back()
{
checkEmpty();
cur=cur->prev;
delete cur->next;
cur->next=NULL;
--len;
}
//弹出第一个节点
void pop_front()
{
checkEmpty();
node* tmp=head->next;
head->next=tmp->next;
tmp->prev=head;
delete tmp;
--len;
}
//前插节点
void push_front(const T& t)
{
node* newNode=new node(t);
head->next=newNode;
newNode->prev=head;
++len;
}
//后插节点
void push_back(const T& t)
{
node* newNode=new node(t);
newNode->prev=cur;
cur->next=newNode;
cur=newNode;
++len;
}
//删除所有值为t的节点
void remove(const T& t)
{
checkEmpty();
node* tmp=head->next;
for(int i=0;i<len;i++)
{
if(tmp->data!=t)
{
tmp=tmp->next;
continue;
}
if(tmp->next==NULL)//删除最后一个节点
{
cur=tmp->prev; //将当前节点指向最后一个节点的前一个节点
cur->next=NULL;//由于保持当前节点指向最后一个节点,他的下一个节点当然为空
}else//删除中间节点
{
tmp->prev->next=tmp->next; //要删除节点的前一个节点的next指针指向要删除节点的下一个节点
tmp->next->prev=tmp->prev; //要删除节点的下一个节点的prev指针指向要删除节点的前一个节点
}
--len;
node* t=tmp->next;
delete tmp;
tmp=t;
}
}
//反转链表
//每次都修改当前节点的前后节点指针
//最后一个节点的下一个指针指向前一个节点
void reverse()
{
checkEmpty();
node* prev = head;// 上一个节点
node* pcur = head->next;//当前节点
node* next;
while (pcur !=NULL)
{
if(!pcur->next)
{
pcur->next=prev;//最后一个节点的下一个节点指向前一个节点
break;
}
next = pcur->next; //下一个节点
pcur->next=prev; //修改当前节点的下一个节点
pcur->prev=next; //修改当前及诶单的上一个节点
prev=pcur; //将当前节点设为上一个节点
pcur=next; //将下一个节点设为当前节点
}
cur=head->next; //末节点指向头节点
head->next=pcur; //头指针指向当前节点,也就是指向翻转之前的末节点
}
//排序
//节点之间直接交换数据,而没有用修改指针指向
void sort()
{
if(empty())
{
return;
}
node *p,*t;
p=head->next;
T d;
while(p!=NULL)
{
t=p;
while(t!=NULL)
{
if(p->data>t->data)
{
d=p->data;
p->data=t->data;
t->data=d;
}
t=t->next;
}
p=p->next;
}
}
//链表元素个数
int size()
{
return len;
}
void resize(int count)
{
resize(count,0);
}
//重新设置元素
void resize(int count,T t)
{
if(count<0)
{
thrownew exception("元素的个数不能小于0!");
}
clear(); //内存是必须释放的
while(count--)
{
push_front(t);
}
}
//清空集合
void clear()
{
if(empty())
{
return;
}
node *tmp=head;
node *t=tmp->next;
while(t!=NULL)
{
tmp=t;
t=t->next;
delete tmp;
}
tmp=NULL;
t=NULL;
cur=head;//当前节点指向头指针
}
//链表是否为空
bool empty() const
{
return len==0;
}
//判断链表是否为空
void checkEmpty()
{
if(empty())
{
thrownew exception("集合中没有元素!");
}
}
private :
typedef struct node1
{
node1 *prev,*next;
T data;
node1(T t):data(t),prev(NULL),next(NULL){}
}node;
node* head;//头节点
node* cur; //当前节点,指向末节点
int len; //节点个数
void initialize()
{
cur=head=new node(-1);
len=0;
}
};
作者:陈太汉