上文已经介绍了链表中的单链表,这里我们再叙述一下双向链表
1.双向链表
对比单链表,双向链表能够直接找到节点的前驱,也就能从任意一个节点到达链表的头结点和尾节点。如下图所示:
下面我们还是从使用的角度出发来定义双向链表的接口。我想使用一个双向链表,那我就new一个来用。然后我就往里插入元素。之后我又想在某个索引处插入一个元素。于是我就可以写出下面的代码:
TwoDirectionsLinkList<int> * twoDirectionsLinkList = new TwoDirectionsLinkList<int>();//new一个双链表对象来用
twoDirectionsLinkList->insertElementToEnd(1);//在尾端插入
twoDirectionsLinkList->insertElementToEnd(3);
twoDirectionsLinkList->insertElementToEnd(4);
twoDirectionsLinkList->insertElementToEnd(5);//此时链表中为1345
twoDirectionsLinkList->printAllElement();
twoDirectionsLinkList->insertElementToIndex(2,2);//在索引2处插入,此时链表中为12345
twoDirectionsLinkList->printAllElement();
twoDirectionsLinkList->deleteElementAtIndex(3);//删除索引3处的节点,此时链表中为1245
twoDirectionsLinkList->printAllElement();
接下来就是来实现这些接口里的具体内容。
我们要使用双向链表,就要定义一个双向链表的类,姑且叫做TwoDirectionsLinkList
,为了扩展性我们使用模板。类TwoDirectionsLinkList
中应该有成员变量
TwoDirectionsLinkNode<DataType>* _head;
int _length;
其中TwoDirectionsLinkNode<DataType>* _head;
为头结点,int _length;
记录链表的长度。节点类TwoDirectionsLinkNode
我们也需要定义,节点类中应该有三个成员变量:
DataType _data;//存储数据
TwoDirectionsLinkNode<DataType>* _next;//指向后继节点
TwoDirectionsLinkNode<DataType>* _prior;//指向前驱节点
new一个双向链表时,调用TwoDirectionsLinkList
的构造函数,这样就有了头节点了,我们就可以在头节点的基础上进行操作了。
TwoDirectionsLinkList()
{
//头结点我随便放个数据0
_head = new TwoDirectionsLinkNode<DataType>(0);
_length = 0;
}
插入新节点的操作,如下图所示,首先我们把指针p移动到要插入索引的前一个索引处,然后让新节点的_next指针指向p的_next(也就是索引处的节点),然后让p的_next指向新节点,然后让新节点的_prior指向p,再让索引处节点的_prior指向新节点。
bool insertElementToIndex(int index,DataType data)//插入到链表的指定位置处
{
if (_length == 0)
{//在长度为0的情况下,可以插入到索引1处
if (index == 1)
{
//链表长度为0,即只有头节点时,把新节点插入
TwoDirectionsLinkNode<DataType>* newNode
= new TwoDirectionsLinkNode<DataType>(data);
_head->_next = newNode;
newNode->_prior = _head;
_length++;
return true;
}else
{
return false;
}
}
//长度不为0的情况下,只能在1~_length范围内插入
if (index <=0 || index > _length)return false;
TwoDirectionsLinkNode<DataType>* p = _head;
//把指针p指向指定索引前的那个节点
for (int i = 0;i<index -1 ;i++)
{
p=p->_next;
}
TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
if (newNode == NULL)return false;
newNode->_next = p->_next;
p->_next = newNode;
newNode->_prior = p;
newNode->_next->_prior = newNode;
_length++;
return true;
}
这样我们就解决双向链表的插入与删除问题,下面是双向链表的.h文件,
template<typename DataType>class TwoDirectionsLinkList;
template<typename DataType>class TwoDirectionsLinkNode
{
public:
TwoDirectionsLinkNode(DataType data):_next(NULL),_prior(NULL),_data(data)
{
}
private:
DataType _data;//存储数据
TwoDirectionsLinkNode<DataType>* _next;//指向后继节点
TwoDirectionsLinkNode<DataType>* _prior;//指向前驱节点
friend class TwoDirectionsLinkList<DataType>;
};
template<typename DataType>class TwoDirectionsLinkList
{
public:
TwoDirectionsLinkList()
{
//头结点我随便放个数据0
_head = new TwoDirectionsLinkNode<DataType>(0);
_length = 0;
}
//双向链表的操作
bool insertElementToEnd(DataType data)//插入到链表的尾部,如果成功,返回true
{
TwoDirectionsLinkNode<DataType>* p = _head;
while(p->_next){//把p指针指向链表的尾部
p=p->_next;
}
//在尾部插入新节点
TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
p->_next = newNode;
newNode->_prior = p;
_length++;
return true;
}
bool insertElementToIndex(int index,DataType data)//插入到链表的指定位置处
{
if (_length == 0)
{//在长度为0的情况下,可以插入到索引1处
if (index == 1)
{
//链表长度为0,即只有头节点时,把新节点插入
TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
_head->_next = newNode;
newNode->_prior = _head;
_length++;
return true;
}else
{
return false;
}
}
//长度不为0的情况下,只能在1~_length范围内插入
if (index <=0 || index > _length)return false;
TwoDirectionsLinkNode<DataType>* p = _head;
//把指针p指向指定索引前的那个节点
for (int i = 0;i<index -1 ;i++)
{
p=p->_next;
}
TwoDirectionsLinkNode<DataType>* newNode = new TwoDirectionsLinkNode<DataType>(data);
if (newNode == NULL)return false;
newNode->_next = p->_next;
p->_next = newNode;
newNode->_prior = p;
newNode->_next->_prior = newNode;
_length++;
return true;
}
bool deleteElementAtIndex(int index)//删除指定位置的元素,如果成功,返回true
{
if (_length == 0)return false;
if (index <= 0 || index>_length)return false;
TwoDirectionsLinkNode<DataType>* p = _head;
//把指针p指向指定索引前的那个节点
for (int i = 0;i<index -1 ;i++)
{
p=p->_next;
}
TwoDirectionsLinkNode<DataType>* temp = p->_next;
p->_next = p->_next->_next;
p->_next->_prior = p;
delete temp;
return true;
}
int getLength()//获取链表的长度
{
return _length;
}
void printAllElement()//打印表中的元素
{
cout<<"打印元素"<<endl;
TwoDirectionsLinkNode<DataType>* p = _head;
while(p->_next)
{
p=p->_next;
cout<<p->_data<<endl;
}
}
private:
TwoDirectionsLinkNode<DataType>* _head;
int _length;
};