双链表与循环链表的实现(C语言版)

 双链表和循环链表都是单链表的扩展只用在单链表的基础上稍加修改就可以了。
 如果对单链表还不是很了解可以去看一下我写的另一篇博文https://blog.csdn.net/weixin_43599057/article/details/95176560

1.双链表
双链表就是每个节点含有两个指针的链表,一个指针与单链表一样为next指针指向下一个,而另一个指针为prior指向前一个节点。因此也很容易理解双链表与单链表的不同之处就在于既可以从头访问到尾,也可以从尾访问到头。
因此很容易得到双链表的基本定义为

typedef struct DNode{
ElemType data;
struct DNode *prior,*next;
}DNode,*DLinkList;

接下来就讨论以下几个操作(也是与单链表稍有不同的操作).
1.ListInsert

Status ListInsert(DLinkList &L,int i,int e){
if(i<=0||i>ListLength(L)) return FALSE;
DLinkList p,r;
p=GetElem(L,i-1);
r=GetElem(L,i);
DLinkList s=(DLinkList)malloc(sizeof(DNode));
s->data=e;
s->next=p->next;
p->next=s;  
s->prior=r->prior;
r->prior=s;

return OK;
}

可见ListInsert操作中对后驱的操作与单链表完全相同,而对前驱的操作也基本与对后驱的操作完全一样,而值得注意的是r=GetElem(L,i)而不是GetElem(L,i+1)我当时就是这里搞错了。至于为什么,建议大家画一个图就很好理解了。
2.ListDelete操作

Status ListDelete(DLinkList &L,int i){
if(i<1||i>ListLength(L)) return FALSE;
DLinkList p,s,t;
t=GetElem(L,i);
p=t->prior;
s=t->next;
p->next=s;
s->prior=p;
free(t);
return OK;
}

方法不唯一,但我认为这是比较好理解的方法。相当于把中间一个跳过去了。

其他操作如ListTraverse,ListLength与单链表的操作都是完全相同的。

循环链表
循环链表与单链表的不同是就在于循环列表的尾节点的后继是指向链表的头节点从而达到循环的效果。其他操作与单链表完全相同。
下面就InitList为例

LinkList InitList(LinkList &L){
 L=(LinkList)malloc(sizeof(LNode));
 LinkList p;
 p=L;
 int num;
 scanf("%d",&num);
 while(num){
  LinkList s=(LinkList)malloc(sizeof(LNode));
  s->data=num;
  p->next=s;
  p=s;
  scanf("%d",&num);
 }
 p->next=L;
 return L;
}

可以看到关键一步就是p->next=L;

循环双链表
理解循环列表和双链表后,循环双链表自然不在话下,
以InitList为例

LinkList InitList(LinkList &L){
L=(LinkList)malloc(sizeof(LNode));
LinkList p;
p=L;
int num=1;
while(num){
LinkList s=(LinkList)malloc(sizeof(LNode));
s->data=num;
p->next=s;
s->prior=p;
p=s;
scanf("%d",&num);  
}
p->next=L;
L->prior=p;
return L; 
}

即多了对prior的一些操作,在这里就不赘述了。
希望对大家能有些帮助。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值