###循环链表###
循环链表是一种头尾相接的链表(即:表中最后一个结点的指针域指向头结点,整一个链表形成一个环)。
注意:循环链表无NULL指针,故涉及遍历操作时,其终止条件就不像非循环链表那样判断p或p->next是否为空,而是判断它们是否等于头指针。
循环条件:p!=L或者p->next!=L
由于尾指针满足r->next->next就是指向首元结点,作用相当于头指针。因此在实际使用过程中,更经常使用的是这种尾指针的循环链表,这样既可以从头遍历,也可以从尾部遍历,有利于降低时间复杂度。
例子:如下图
操作如下图:
-
p存表头结点
-
Tb表头接到Ta表尾
-
释放Tb表头结点
-
修改指针
算法:
LinkList Connecto(LinkList Ta, LinkList Tb) {
//假设Ta、Tb都是非空的单循环链表
p = Ta -> next; //p存表头结点
Ta->next = Tb->next->next; //Tb表头连接Ta表尾
delete Tb->next; //释放Tb表头结点,或使用free(Tb->next);
return Tb;
} //O(1)
###双向链表###
双向链表相较于单链表和单循环链表需要重新定义结点类型
(prior,data,next)前指针域,数据域,后指针域
typedef struct DuLNode {
Elemtype data;
struct DuLNode *prior, *next;
} DuLNode, *DuLinkList;
双向链表的一些操作实现
- 算法1:双向链表的插入操作
void ListInsert DuL(DuLinkList &L, int i, ElemType e) {
//在带头结点的双向循环链表L中第i个位置之前插入元素e
if(!(p=GetElemP_DuL(L, i))) return ERROR;//获得第i个位置,与单链表操作同,不赘述
s=new duLNode; s->date= e
s->prior =p->prior; p->prior->next s;
s->next=p; p->prior=s;
return OK
} // ListInsert DuL
- 算法2:双线链表的删除操作
void ListDelete DuL(DuLink &L, int i, ElemType &e) {
//删除带头结点的双向循珠链表L的第ⅰ个元素,并用e返回
if(!(p=GetElemP DuL(L, i)) return ERROR; //找到位置不合理返回错误
e=p->data; //用于保存删除的数据,以便需要
p->prior->next=p->next;
p->next->prior=p->prior;
delete p; //free(p)
return OK;
}//LinkDelete_DuL
//查找算法时间复杂度是O(n),在这里最复杂,故算法时间复杂度也是O(n)