一、双链表
1、定义
双链表:上一篇提到单链表,其实有一个弊端,就是只能单向读取,很笨重并且只能从头指针开始读取,而双链表是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。
2、建立
(1)初始化一个双链表的结点
typedef int ElemType;
typedef struct DNode
{
ElemType data;
struct DNode *prior,*next;
}DNode,*DLinkList;//用法和上一篇的单链表一致
(2)初始化一个空链表
//初始化双链表
bool InitDLinkList(DLinkList& L)
{
L = (DNode*)malloc(sizeof(DNode));//分配一个头结点
if (L == NULL)//内存不够,分配失败
return false;
L->prior = NULL;//头结点的prior永远指向NULL
L->next = NULL;//头结点之后在暂时没有结点
return true;
}
(3)判断双链表是否为空
//判断双链表是否为空(带头结点)
bool Empty(DLinkList L)
{
if (L->next == NULL)
return true;
else
return false;
}
(4)在p结点后插入s结点
//在p结点之后插入s结点
bool InsertNextDNode(DNode* p, DNode* s)
{
if (p == NULL || s == NULL)//非法参数
return false;
s->next = p->next;
if(p->next!=NULL)//如果p有后续结点
p->next->prior = s;
s->prior = p;
p->next = s;
}
(5)删除p结点的后续结点q
//删除p的后继结点q
bool DeleteNextDNode(DNode* p)
{
if (p == NULL)
return false;
DNode* q = p->next;//找到p的后继结点q
if (q == NULL)//p没有后续
return false;
p->next = q->next;
if (q->next != NULL)//q结点不是最后一个结点
q->next->prior = p;
free(q);//释放结点空间
return true;
}
(6)删除整个双链表
//删除整个双链表
void DestoryList(DLinkList& L)
{//循环释放各个数据结点
while (L->next != NULL)
DeleteNextDNode(L);
free(L);//释放头结点
L = NULL;//头结点指向NULL
}
二、静态链表
静态链表是由数组的方式实现的链表。由于比较少用就不谈及这么多。
优点:增删不需大量移动元素
缺点:不能随机存储,容量大小固定,与单链表缺点类似。