循环链表
定义
循环链表是一种头尾相接的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
循环链表的优点是从表中任意结点出发都可以找到表中其他结点。由于表的操作往往是在表的首尾进行的,当头指针表示单链表循环时,找结点1和结点n的时间复杂度分别为O(1)和O(n);当尾指针表示单链表循环时,找结点1和结点n的时间复杂度都为O(1),故通常用尾指针。
结点定义如下:
typedef struct LinkList{
int data;
LinkList* next;
}LNode,*LinkNode;
初始化
循环链表只需让组后一个结点的指针域指向头结点,以单链表为例,只需在初始化时将最后结点的指针指向头结点。
void InitLink (LinkNode & L){
L = (LinkNode)malloc(sizeof(LNode));
L->next = L;
return;
}
但由于循环链表中没有NULL指针,故涉及遍历操作时,其终止条件变为判断指针是否等于头结点,以验空为例。
void CheckLinkEmpty(LinkNode L) {
if (L == NULL) { printf("No exist\n"); }
else if (L->next == L) { printf("Empty!\n"); }
else { printf("No empty!\n"); }
return;
}
循环链表合并
将两个带头结点的循环单链表ListA和ListB合并为一个带头结点的循环单链表ListC。第一步储存ListA,ListB的头结点,第二步将两个表的结点移至尾结点,第三步将A的尾结点连到B的首结点,将B的尾结点连到A的头结点,第四步释放B的头结点,第五步,返回A的头结点。
LinkNode ConnectLinkList(LinkNode &ListA, LinkNode &ListB) {
LNode* q = ListA;
LNode* p = ListB;
LNode* m = (LinkNode)malloc(sizeof(LNode));
while (ListA->next!=q)
{
ListA = ListA->next;
}
while (ListB->next != p)
{
ListB = ListB->next;
}
m = ListA->next;
ListA->next = ListB->next->next;
free(p);
ListB->next = m;
ListA = q;
return ListA;
}
测试:输入A{8,7,6,5,9},B{1,2,3,4},输出链表C的1~9位,结果如下:
双向链表
定义
双向链表是在单向链表基础上的一个改进,每个节点指向其直接前驱和直接后继节点。对于双向链表来说,它的每个节点要指向“直接前驱”和“直接后继”,所以节点类需要含有两个指针域。指向直接前驱的指针使用pre表示,指向后继的指针使用next表示。双向链表的优点是:从双向链表的任意位置开始,都能访问所有的节点。双向链表定义如下:
typedef struct DuLinkList {
DuLinkList* pre;
int data;
DuLinkList* next;
}DuNode, * DuLinkNode;
相关操作
初始化
双向链表不仅需让头结点next指针域指向NULL,还需要让头结点pre指针指向NULL。
typedef struct DuLinkList {
DuLinkList* pre;
int data;
DuLinkList* next;
}DuNode, * DuLinkNode;
插入
双向链表的插入操作更加复杂,需要改变pre指针。双向链表的插入操作时间复杂度为O(n)。
void DuAddLink(DuLinkNode& L, int r, int e) {
DuNode* p = L;
DuNode* q = (DuLinkNode)malloc(sizeof(DuNode));
q->data = e;
for (int i = 1; i < r; i++) {
p = p->next;
}
q->next = p->next;
q->pre=p;
p->next = q;
q->next->pre = q;
return;
}
删除
双向链表的删除操作时间复杂度也为O(n)。
void DuDeleteLink(DuLinkNode& L, int r) {
DuNode* p = L;
DuNode* q = (DuLinkNode)malloc(sizeof(DuNode));
for (int i = 1; i < r; i++) {
p = p->next;
}
q->next = p->next;
q->pre = p->next->pre;
p->next = p->next->next;
p->next->pre = p;
free(q);
return;
}