一、循环链表
1、定义:
循环链表是一种头尾相接的链表(即:表中最后一个结点的指针域指向头结点,整一个链表形成一个环)。
注意:循环链表无NULL指针,故涉及遍历操作时,其终止条件就不像非循环链表那样判断p或p->next是否为空,而是判断它们是否等于头指针。
循环条件:p!=L或者p->next!=L
在实际使用过程中,更经常使用的是这种尾指针的循环链表,有利于降低时间复杂度。
示例:
操作步骤:
代码实现:
(时间复杂度为O(1))
LinkList Connect(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;
}
二、双向链表
需要重新定义结点类型:
(prior,data,next)前指针域,数据域,后指针域
typedef struct DuLNode {
Elemtype data;
struct DuLNode *prior, *next;
} DuLNode, *DuLinkList;
1.双向链表的插入操作:
Status ListInsert_DuL(DuLinkList &L, int i, ElemType e) {
//在带头结点的双向循环链表L中第i个位置之前插入元素e
if(!(p = GetElemP_DuL(L, i))) return ERROR;//在L中获得第i个元素的位置指针p
s = new DuLNode; s->data = e
s->prior = p->prior; p->prior->next = s;
s->next = p; p->prior = s;
return OK
}
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;
}
//查找算法时间复杂度是O(n),在这里最复杂,故算法时间复杂度也是O(n)