#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef struct DuNode
{
ElemType data;
struct DuNode *prior;//直接前驱指针
struct DuNode *next;//直接后驱指针
}DuNode, *DuLinkList;
void Init(DuLinkList *L)
{
*L=(DuLinkList)malloc(sizeof(DuNode));//创建一个头结点
(*L)->prior=*L;//前驱指针指向头结点
(*L)->next=*L;//后驱指针指向头结点
}
void Add_Head(DuLinkList *L)//头插法
{
DuNode *p,*s;
p=*L;
for(int i=1;i<=10;i++)
{
s=(DuNode*)malloc(sizeof(DuNode));
/*先解决新结点s的前驱后继,再解决后一个结点的前驱,最后解决前一个结点的后继*/
s->data=i;
s->prior=p;
s->next=p->next;
p->next->prior=s;
p->next=s;
}
}
void Add_Tail(DuLinkList *L)//尾插法
{
DuNode *p,*s;
p=*L;
for(int i=1;i<=10;i++)
{
s=(DuNode*)malloc(sizeof(DuNode));
p->next=s;
s->data=i;
s->prior=p;
s->next=*L;
p=s;//p永远指向最后一个结点
}
}
int Delete(DuLinkList *L,int i)
{
int j=1;
DuLinkList p,q;
p=(*L)->next;
while(j<i&&p!=*L) {//查找第i个结点
p = p->next;
j++;
}
if(j>i||p==*L)
return 0;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);
return 1;
}
int Insert(DuLinkList *L,int i,ElemType e)//在位置i上面插入元素e
{
int j=1;
DuLinkList p,q,s;
p=*L;
q=*L;
while(j<i&&(j==1||p!=*L)) {//寻找第i-1的位置,删除时是查找第i个结点,当然删除时也可以查找第i-1个结点
p = p->next;
j++;
}
// printf("%d %d\n",j,p->data);
if(j>i||(p==*L&&j!=1))
return 0;
s=(DuNode*)malloc(sizeof(DuNode));
/*先解决新结点s的前驱后继,再解决后一个结点的前驱,最后解决前一个结点的后继*/
s->data=e;
s->prior=p;
s->next=p->next;
p->next->prior=s;
p->next=s;
return 1;
}
void Print(DuLinkList *L)//打印链表
{
DuNode *p=(*L)->next;//p指向第一个元素
while(p->next!=(*L)->next)//当p为头结点时,p->next指向头结点,此时结束
{
printf("%d ",p->data);
p=p->next;
}
}
int main()
{
DuLinkList *L;
Init(&L);
Add_Head(&L);
Print(&L);
printf("\n");
if( Delete(&L,10))
Print(&L);
printf("\n");
if( Insert(&L,10,0))
Print(&L);
printf("\n");
DuLinkList *L1;
Init(&L1);
Add_Tail(&L1);
Print(&L1);
return 0;
}
双向链表的删除可以直接查找第i个结点,无需像单向链表一样先查找第i-1个结点再删除,因为有prior指针。
但是对于插入,单向链表和循环双向链表都使查找第i-1个结点。
删除和插入不一样的原因在于,对于删除,你输入的位置i上面一定有元素,但是对于插入,在链表的最后一个元素后面的位置上是空的,倘若查找第i个元素对于单向链表就会遇到null而退出,对于循环双向链表就会搜索到第一个结点而退出。
while(j<i&&(j==1||p!=*L)) {//寻找第i-1的位置,删除时是查找第i个结点,当然删除时也可以查找第i-1个结点
p = p->next;
j++;
}
这样写循环终止条件的原因是当输入i=1时,不能retrun 0,因为初始时p的值和L一样,只有当你遍历一遍之后又回到了L,才能结束。