title: 数据结构-循环链表与双向链表
date: 2022-10-16 12:18:05
tags:数据结构
循环链表
特点
表中最后一个节点的指针域指向头节点,整个链表形成一个环
如图
操作
循环单链表的操作和单链表基本一致(点这里查看单链表操作),差别在于:当链表遍历时,判别当前指针p是否指向表节点的终止条件不同
。在单链表中,判别条件为p!=NULL或p->next = NULL,而循环单链表的判别条件为p! = NULL或p->next !=L。
在某些情况下,在循环链表中设立尾指针而不设立头指针,可使一些操作简化。如将两个线性表合并成一个表时。
将上图两表合并:
主要语段:
p = B->next->next
; 建立工作指针p,存放表2的头节点的后继指针地址(表2的红色节点)
B->next = A->next
; 将表2尾节点的指针指向表1的头节点(表3的绿色线)
A->next = p
; 将表1的尾指针A指向表2头节点的后继节点(表3蓝色的线)
最后free表2的头节点
;
双向链表
特点
在单链表中,查找直接后继的执行时间为O(1),而查找直接后前驱的执行时间为O(n)。为克服单链表这中单向性的缺点,可利用双向链表。
如图
算法描述
//双向链表的存储结构
typedef struct DuLNode
{
ElemType data; //数据域
struct DuLNode *prior; //指向直接前驱
struct DuLNode *next; //指向直接后驱
}DuLNode, *DuLinkList;
在双向链表中,有些操作(ListLength,GetElem和LocateElem等)仅需涉及一个方向的指针,他们的算法描述和线性链表一样(点这里查看单链表操作)。但在插入,删除时有很大不同。
操作
插入
算法描述
Status ListInsert_Dul(DuLinkList &L, int i, ElemType e)
{//在带头节点的双向链表L中第i个元素之前插入元素e
if(!(p = GetElem_DuL(L, i))) //在L中确定第i个元素的位置指针p
{
return ERROR; //p为NULL时,第i个元素不存在
}
s = new DuLNode; //生成新节点*s
s->data = e; //将节点*s的数据域置为e
s->prior = p->next; //将节点*s插入L中,此步对应下图①
p->prior->next = s; //对应下图②
s->next = p; //对应下图③
p->prior = s; //对应下图④
return OK;
}
如图
删除
算法描述
Stauts ListDelete_Dul(DuLinkList &L, int i)
{//删除头节点的双向链表L中的第i个元素
if(!(p = GetElem_DuL(L, i))) //在L中确定第i个元素的位置指针p
{
return ERROR; //p为NULL时,第i个元素不存在
}
p->prior->next = p->next; //修改被删除节点的前驱节点的后继指针,对应下图①
p->next->prior = p->prior; //修改被删除节点的后继节点的后继指针,对应下图②
delete p; //释放被删除节点的空间
return OK;
}
如图