双向链表实际上是单向链表的扩展。
当我们对单向链表进行操作的时候,有时你要对某个结点的前驱进行操作的时,又必须从表头开始查找。这是单向链表
结构特点的局限性。因为单链表每个结点只有一个存储直接后继的结点地址的链域,那么能不能定义一个既有存储前驱,
又能存储后继的这样一个链表结构呢?答案是可以的。这就是双向链表。
在双向链表中,结点除了含有数据域外,还有两个链域,“前驱后继”,有的人称之为左右链域,差不多,知道这么个意
思就可以了。其定义如下所示:
struct RoleStruct
{
int ID;
string Name;
RoleStruct *lpLink,*rpLink; //注意:有的人经常犯错写成:RoleStruct *lpLink,rpLink;后一指针标示错误
};
还有一个问题是,我们还能不能使双向链表变成双向循环链表呢?答案同样是可以的。
双向链表同单向链表一样,也有3种最基本的操作:查找、插入、删除。
下边介绍双向链表的这3个最为基本的操作:
#include <iostream>
using namespace std;
struct RoleStruct
{
int ID;
RoleStruct *lpLink,*rpLink;
};
typedef struct RoleStruct MyRoleStruct;
typedef MyRoleStruct* lpMyRoleStruct;
//0、生成双向链表
lpMyRoleStruct CreateRoleLink(void)
{
lpMyRoleStruct pHead,pMiddle,pTail;
int _Volue;
pHead = new(MyRoleStruct);
if (pHead == NULL)
{
cout << "分配头结点存储空间失败." << endl;
}
cout << "请任意输入自然值:" << endl;
cin >> _Volue;
pHead->ID = _Volue;
pHead->lpLink = NULL;
pHead->rpLink = NULL;
pTail = pHead;
cout << "请继续输入数值,以0结束录入:" << endl;
cin >> _Volue;
while (_Volue != 0)
{
pMiddle = new (MyRoleStruct);
if (pMiddle == NULL)
{
cout << "中间存储空间申请失败." << endl;
}
//*生成双向链表的关键步骤
pMiddle->ID = _Volue;
pTail->rpLink = pMiddle;//将尾结点的右结点设置成中间结点
pMiddle->lpLink = pTail;//将中间结点的前驱设置成尾结点
pMiddle->rpLink = NULL; //将中间结点的后继设置成空结点
pTail = pMiddle;
cout << "请继续输入数值:" << endl;
cin >> _Volue;
}
return pHead;
};
//1、输出链表
void printRoleLink_R(lpMyRoleStruct pHead)
{
lpMyRoleStruct pTail;
while (pHead != NULL)
{
pTail = pHead;
pHead = pHead->rpLink;
cout << "输出:" << pTail->ID << endl;
}
cout << "----------------------------------------------------------" << endl;
}
//2、测试双向链表前驱是否工作正常
void printRoleLink_L(lpMyRoleStruct pHead)
{
lpMyRoleStruct pTail;
while (1)
{
pTail = pHead;
pHead = pHead->rpLink;
if (pTail->lpLink != NULL)
{
cout << pTail->lpLink->ID << endl;
break;
}
}
cout << "上边没做错的话,应该输出头结点起初的录入值" << endl;
}
//3、双向链表的释放
void DelRoleLink(lpMyRoleStruct pHead)
{
lpMyRoleStruct pTail;
while (pHead != NULL)
{
pTail = pHead;
pHead = pHead->rpLink;
free(pTail);
}
cout << "释放链表成功." << endl;
getchar();
}
//4、双向链表的查找(很简单,请参阅单向链表的查找方法,再此不再累述)
//注:其他方法也很简单,参看我实现的单向链表
int main()
{
lpMyRoleStruct pHead;
pHead = CreateRoleLink();
printRoleLink_R(pHead);
printRoleLink_L(pHead);
DelRoleLink(pHead);
getchar();
return 0;
}