目录
一、循环链表
1.与循环链表相关知识
循环链表:是一种头尾相接的链表(即:表中最后一个结点的指针或指向头结点,整个链表形成一个环)。
优点:从表中任一结点出发均可找到表中其他结点。
注意:
由于循环链表中没有NULL指针,故涉及遍历操作时。其终止条件不再像非循环链表那样判断p或p->next是否为空,而是判断它们是否等于头指针。
头指针表示单循环链表:(不方便)
- 找a1的时间复杂度:O(1)
- 找an的时间复杂度:O(n)
注意:表的操作常常是在表的首尾位置上进行。
尾指针表示单循环链表:(时间复杂度均为O(1))
- a1的存储位置是:R->next->next
- an的存储位置是:R
2.带尾指针循环链表的合并
【算法描述】
LinkList Connect(LinkList Ta,LinkList Tb){
//假设Ta、Tb都是非空的单循环链表
P=Ta->next; //①p存表头结点
Ta->next=Tb->next->next; //②Tb表头连接Tb表尾
delete Tb->next; //③释放Tb表头结点(或free(Tb->next);)
Tb->next=p; //④修改指针
return Tb;
}
时间复杂度是:O(1)。
三、双向链表
1.有关双向链表的知识点
①双向链表定义
双向链表:在单链表的每个结点里再增加一个指向其直接前驱的指针域prior,这样链表中就形成了有两个方向不同的链,故称为双向链表。
②双向链表的结构
双向链表结点结构:
prior | data | next |
双向链表的结构可定义如下:
typedef struct DuLNode{
Elemtype data;
struct DuLNode *prior,*next;
}DuLNode,*DuLinkList;
2.双向循环链表
和单链的循环表类似,双向链表也可以有循环表
- 让头结点的前驱指针指向链表的最后一个结点;
- 让最后一个结点的后继指针指向头结点。
3.双向链表结构的对称性(设指针p指向某一结点)
p->prior->next=p=p->next->prior
在双向链表中有些操作(如:ListLength,GetElem等),因仅涉及一个方向的指针,故它们的算法与线性链表的相同。但在插入、删除时,则需同时修改两个方向的指针,两者的操作的时间复杂度均为O(n)。
4.在双向链表上的操作
①双向链表的插入
void ListInsert_DuL(DuLinkList &L,int i,ElemType e){
//在带头结点的双向循环链表L中第i个位置之前插入元素e
if(!(p=GetElemP_DuL(L,i)))return ERROR;
s=new DuLNode; s->date=e;
s->prior=p->prior; p->prior->next=s;
s->next=p; p->prior=s;
return OK;
}//ListInsert_DuL
②双向链表的删除
void ListDelete_DuL(DuLink &L,int i,ElemType &e){
//删除带头结点的双向循环链表L的第i个元素,并用e返回。
if(!(p=GetElemP_DuL(L,i))) return ERROR;
e=p->data;
p->prior->next=p->next;
p->next->prior=p->prior;
free(p);
return OK;
}//ListDelete_DuL