一、循环链表
优点:可以从任意一个结点出发查找其他结点
检空:判断尾指针是否指向头指针
p!=L p->next!=L
通过头指针 H 查找an的时间复杂度为O(n)、a1的时间复杂度为O(1)
a1的存储位置为R->next->next
an的存储位置为R
通过尾指针 R 查找an、a1的时间复杂度为O(1)
将两个带尾指针的循环链表合并
LinkList Connect(LinkList Ta,LinkList Tb){ p=Ta->next;//p保存表头结点 Ta->next = Tb = next->next;//Tb表头连接Ta表尾 delete Tb->next;//释放Tb的头指针 Tb->next = p;//修改指针 return Tb; } 时间复杂度为O(1)
二、双向循环链表(在每个结点里增加一个前驱指针域prior)
可以直接查找一个结点的前驱结点(不需要像单链表一样绕场一周)
定义
typedef struct DuLNode{ ElemType data; sturct DuLNode *prior,*next; }DuLNode,*DuLinkList;
双向链表具有对称性,在插入和删除时需要修改两个指针,操作的时间复杂度均为O(n)
插入
void ListInsert_Dul(DuLinkList &L,int i, ElemType e){ if(!(p=GetElemP_Dul(L,i))) return ERROR;//查找位置,如果没有直接返回错误 s= new DuLNode; s->data=e; s->prior = p->piror; p->prior->next=s;//连接前驱元素 s->next = p; p->piror=s;//连接后继元素 return OK; }
删除
void ListDelete_Dul(DuLink &L,int i,ElemType &e){ if(!(p=GetElemP_Dul(L,i))) return ERROR;//查找位置,如果没有直接返回错误 e=p->data; p->prior->next = p->next;//断开前驱指针 p->next->prior=p->prior;//断开后继指针 delete p; return OK; }
多种链表的比较(时间复杂度)
顺序表与链表的对比