昨天写了vector之后写了链表,但是没有时间更新,今天补上。
链表是基本的数据结构之一,刚学过语言,没有学过数据结构的同学看上去可能有点吃力,因为又牵扯指针,来回指向,比较容易乱,只要记住一点 指针指向的是一个节点,自己理解了,你就觉得很容易了。
先说一下优缺点吧:
1、在我看来链表就是为了弥补数组插入删除的繁琐操作,而出现的,链表的最大优点就是插入删除节点时的方便。直接删除而不用像数组那样来反复移动元素。
2、链表的缺点就是它开辟了额外的空间来来存数前后节点的指针。
我的作图技术不是很好凑合着看吧,这个图我想说的就是一点(下面介绍)。
我们一般把节点定义成struct;
struct Node
{
Object data;//如图的数据
Node *prev;//这个如图前指针区
Node *next;//这个如图后指针区
Node (const Object &d = Object(),Node *p=NULL,Node *q=NULL):data(d),prev(p),next(q){}//这个是构造函数(或者是初试话函数)具体可以查查结构体,没用过也没关系
};
大家不用担心看不懂,我给大家解释:object是指某个数据类型(如int char等) Node * 是指指向Node的指针 (这个就像 int * 一样)
我想说明的一点是指针指向的红圆圈里面所有东西的地址。这样就应该好理解了吧。这样看到链表自己画一下就明白了。
下面我们来说实现了。
书中的实现有点费劲,他建立了内部类。这使我们看上去好像很难,其实也就那样,不咸不淡。
跟我一起走。
我尽量每个地方都来加上注释。我们在实现链表时一般加上头结点和为节点来方便操作。
设置私有变量
private:
struct Node
{
Object data;
Node *prev;
Node *next;
Node (const Object &d = Object(),Node *p=NULL,Node *q=NULL):data(d),prev(p),next(q){}
};
int thesize;
Node *head;
Node *tail;
然后我们来考虑iterator 让我们来实现它 用一个内部类(这些内部类什么的没接触过得听上去搞不懂但是一看就明白了) 迭代器(主要为了遍历元素)
class iterator
{
public :
iterator(){}//构造函数
Object & operator*()//重载*运算符
{
return retrieve();
}
const Object & operator *() const//重载*运算符
{
return retrieve();
}
const iterator &operator++()//重载++
{
current = current->next;
return *this;
}
const iterator &operator--()//重载--
{
current = current->prev;
return *this;
}
const iterator operator ++(int )//重载++
iterator old = *this;
++(*this);
return old;
}
bool operator==(const iterator &rhs)const//重载==
{
return current == rhs.current;
}
bool operator!=(const iterator &rhs)const//重载!=
{
return !(*this==rhs);
}
private:
Node *current;//node的节点指针
Object & retrieve()const//返回该节点下的数据值
{
return current->data;
}
protected:
iterator (Node *p):current(p) {}//这也是构造函数
friend class List<Object>;//声明为友元,为了后面再list类中调用;
};
书中还定义了const_iterator类 ,iterator继承了const_iterator。这里我省略了,直接定义了iterator。
接下来就是我们的LIst类的东西了,类不用说上来肯定是构造函数。
List ()
{
init();
}
List(const List &rhs)
{
init();
*this = rhs;
}
void init()
{
thesize = 0;
head = new Node();
tail = new Node();
head->next = tail;
tail->prev = head;
}
~List()
{
clear();
delete head;
delete tail;
}
上面就不用说了吧!init()函数下面有实现。
这里重载了= 主要是为了给list赋值。
const List & operator = (const List &rhs)
{
if(this==&rhs)
return *this;
clear();
for(iterator it = rhs.begin();it!=rhs.end();it++)
{
push_back(*it);
}
return *this;
}
下面是插入删除的操作:
iterator insert(iterator it , const Object &x)//在it的后面插入一个值为x的节点
{
Node *p = it.current;
thesize++;
return iterator(p->prev = p->prev->next = new Node(x,p->prev,p));
}
iterator erase(iterator it)//删除迭代器位置的节点(iterator 就是迭代器 主要为了遍历元素)
{
Node *p = it.current;
iterator retVal=(p->next);
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
thesize--;
return retVal;
}
iterator erase(iterator start ,iterator end)//删除迭代器start-end的所有元素
{
for(iterator it = start ;it!=end;)
{
it=erase(it);
}
return end;
}
下面是基本的方法了 ;
iterator begin()//返回开始第一个节点位置(除头结点)
{
return iterator(head->next);
}
iterator end()//返回为节点位置
{
return iterator(tail);
}
int size()const//链表的大小
{
return thesize;
}
bool empty()const//是否为空
{
return size()==0;
}
void clear()//清空链表
{
while(!empty())
{
pop_front();
}
}
Object front()//返回第一个元素的值
{
return *begin();
}
Object back()//返回最后一个元素的值
{
return *(--end());
}
void push_front(Object &x)//插入前面一个元素
{
insert(begin(),x);
}
void push_back(Object & x)//插入后面一个元素
{
insert(end(),x);
}
void pop_front()//删除前面元素
{
erase(begin());
}
void pop_back()//删除后面元素
{
erase(--end());
}
到这已经基本结束了。
函数实现倒是不复杂。主要是了解这些操作,熟悉链表的用法。
下面是整个代码
#include<iostream>
using namespace std;
template<typename Object>
class List
{
private:
struct Node
{
Object data;
Node *prev;
Node *next;
Node (const Object &d = Object(),Node *p=NULL,Node *q=NULL):data(d),prev(p),next(q){}
};
int thesize;
Node *head;
Node *tail;
public:
class iterator
{
public :
iterator(){}
Object & operator*()
{
return retrieve();
}
const Object & operator *() const
{
return retrieve();
}
const iterator &operator++()
{
current = current->next;
return *this;
}
const iterator &operator--()
{
current = current->prev;
return *this;
}
const iterator operator ++(int )
{
iterator old = *this;
++(*this);
return old;
}
bool operator==(const iterator &rhs)const
{
return current == rhs.current;
}
bool operator!=(const iterator &rhs)const
{
return !(*this==rhs);
}
private:
Node *current;
Object & retrieve()const
{
return current->data;
}
protected:
iterator (Node *p):current(p) {}
friend class List<Object>;
};
List ()
{
init();
}
List(const List &rhs)
{
init();
*this = rhs;
}
void init()
{
thesize = 0;
head = new Node();
tail = new Node();
head->next = tail;
tail->prev = head;
}
~List()
{
clear();
delete head;
delete tail;
}
const List & operator = (const List &rhs)
{
if(this==&rhs)
return *this;
clear();
for(iterator it = rhs.begin();it!=rhs.end();it++)
{
push_back(*it);
}
return *this;
}
iterator insert(iterator it , const Object &x)
{
Node *p = it.current;
thesize++;
return iterator(p->prev = p->prev->next = new Node(x,p->prev,p));
}
iterator erase(iterator it)
{
Node *p = it.current;
iterator retVal=(p->next);
p->prev->next = p->next;
p->next->prev = p->prev;
delete p;
thesize--;
return retVal;
}
iterator erase(iterator start ,iterator end)
{
for(iterator it = start ;it!=end;)
{
it=erase(it);
}
return end;
}
iterator begin()
{
return iterator(head->next);
}
iterator end()
{
return iterator(tail);
}
int size()const
{
return thesize;
}
bool empty()const
{
return size()==0;
}
void clear()
{
while(!empty())
{
pop_front();
}
}
Object front()
{
return *begin();
}
Object back()
{
return *(--end());
}
void push_front(Object &x)
{
insert(begin(),x);
}
void push_back(Object & x)
{
insert(end(),x);
}
void pop_front()
{
erase(begin());
}
void pop_back()
{
erase(--end());
}
};
int main()
{
}
c++语言的地方看不懂没关系我们主要是为了熟悉数据结构,具体语言没有要求。
好了!感谢自己坚持。