在线性表的链式存储结构中,每个物理结点增加一个指向后继结点的指针域和一个指向前驱结点的指针域
⇒
\Rightarrow
⇒双链表

1.单链表是在元素的结点中只能包含一个后继结点指针,不能包含多个指针,双链表则是包含前驱结点和后继结点两个指针。
2.单链表要求建好后返回一个结点的指针,只能朝后运行,双链表建好后可以给任意一个结点的指针,前后两个方向都可以走。


定义如下:
typedef struct DNode //双链表结点类型
{
ElemType data;
struct DNode *prior; //指向前驱结点
struct DNode *next; //指向后继结点
}DLinkNode;


在p结点之后插入结点s。
代码如下:
s->next=p->next;
p->next->prior=s;
s->prior=p;
p->next=s;
删除p结点之后的一个节点

p->next->next-prior=p;
p->next=p->next-next;
整体建立双链表:
1.头插法
2,尾插法
void CreateListF(DLinkNode *&L,ElemType a[],int n)//由·含n个元素的数组a创建带头结点的双链表L
{
DLinkNode *s;
L=(DLinkNode *)malloc(sizeof(DLinkNode));//创建头结点
L->prior=L->next=NULL;//前后指针域置为NULL
for(int i=0;i<n;i++)
{
s=(DLinkNode *)malloc(sizeof(DLinkNode);
s->data=a[i]; //创建数据结点s
s-next=L->next; //将s结点插入到头结点之后
if(L->next=NULL) //如果L非空,修改L->next的前驱指针
L-next-prior=s;
L->next=s;
s->prior=L;
}
}
void CreatListR(DLinkNode *&L,ElemType a[],int n)
{
DLinkNode *s,*r;
L=(DLinkNode *)malloc(sizeof(DLinkNode)); //创建头结点
r=L; //r始终指向尾结点,开始时指向头结点
for(int i=0;i<n;i++) //循环建立数据结点
{
s=(DLinkNode *)malloc(sizeof(DLinkNode));
s->data=a[i]; //创建数据结点s
r->next=s;
s->prior=r;
r=s; //r指向尾结点
}
r-next=NULL; //尾结点next域置为NULL
}
头插法核心:
利用头指针控制链表结点的增加。

newNode->next=head->next;
head-next=newNode;
尾插法创建链表需要借助一个辅助指针,指向当前列表的最后一个结点。

尾插法建立链表的核心:
newNode->next=rear->next;
rear->next=newNode;
rear=rear->next;
bool ListInsert(DLinkNode *&L,ElemType e,int i)
{
int j=0;
DLinkNode *p=L,*s; //p指向头结点,j设置为0
while(j<i-1&&p!=NULL) //查找第i-1个结点
{
j++;
p=p->next;
}
if(p==NULL) //未找到第1个结点
return false;
else
{
s=(DLinkNode *)malloc(sizeof(DLinkNode));
s->data=e; //创建新结点s
s-next=p->next; //在p结点之后插入s结点
if(p->next!=NULL) //若存在后继结点,则修改其前驱指针
p->next->prior=s;
s->prior=p;
p->next=s;
return ture;
}
}
bool ListDelete(DLinkNode *&L,Elemtype &e,int i)
{
int j=0;DLinkNode *p=L,*q; //p指向头结点,j设置为0
while(j<i-1&&p!=NULL)
{
j++;
p=p->next;
}
if(p==NULL) //未找到第i-1个结点
return false;
else
{
e=q->data;
p->next=q->next;
if(q-next!!=NULL)
q->next->prior=p;
free(p);
return ture;
}
}