目录
循环链表
循环链表与单链表的区别和联系
循环链表的访问顺序
循环队列的常用操作
排序
合并
合并并保留序列
反转
判空
后续操作待补充
代码实现
循环链表和单链表最大区别就是最后一个节点指向头节点。遍历时节点迭代指针 p!=头节点 L就行了。
循环链表也算是继承自单链表,起到模拟环的效果。解决单链表无法首尾相连的弊端。故而,在结构上与单链表无异。
由于循环链表起到模拟环的作用,所有访问顺序是一个圈,即遍历一次后能够返回到头节点。
除了增加、删除、查询、修改外,这里再补充几个操作。其实放在前面的单双队列也是有这些操作的,只是我没有写罢了。
判空 | 清空链表保留头节点 | 合并多个链表 |
排序 | 合并后保持序列 | 反转 |
暂时只能想到这么多,往后我再补充。
排序实际上在插入的过程中就可以完成。没插入一个节点,先找到这个节点应该放在哪个位置。这种不难。
难的是链表赋值之后再排序。一种最常见的方法就是冒泡,这种时间复杂度比较高,达到o(n2),有没有更快速的方法?
有的!o(nlogn)够不够,这种做法是
跑一遍链表,把链表里面的数值取出来放入数组,然后再跑一边快排,然后再放回链表就行了。于是我又想到第一篇文章里面的单链表快排能不能做到?如果按照这个思路来,是可以的!
了解各种排序时间复杂度和空间复杂度戳这里
这里举快速排序的例子吧,算法时间复杂度高的咱不写。
用到了malloc.h中的
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))
使用这个函数之前需要知道节点数
int Count(Linklist L){
Linklist p = L->next;
int i = 0;
while(p->next != L){
i++;
p = p->next;
}
return i+1;
}
还要有一个比较函数(这个函数如果是 “-” 表示升序 “+”表示降序
int cmpfunc (const void * a, const void * b)
{
return ( *(int*)a - *(int*)b );
}
排序函数
Linklist sort(Linklist &L){
int count = Count(L);
int a[count],i=0;
Linklist p = L->next;
while(p->next != L){
a[i] = p->value;
p = p->next;
i++;
}
a[i] = p->value;
qsort(a,count,sizeof(int),cmpfunc);
p = L->next;
i = 0;
while(p->next != L){
p->value = a[i];
i ++;
p = p->next;
}
p ->value = a[i];
return L;
}
有两种合并方式:
两种方式的优缺点分析:
方法一保留了原来的链表,但是创建了一个新链表,空间复杂度有所提高。
方法二破坏了原来的链表,使得所有链表合并成一个链表,空间上并没有多大改变,甚至还可以释放几个链表的头节点。
//function18 王道考研数据结构 p39 T18,循环链表合并
Linklist combine(Linklist &A,Linklist &B){
Linklist p = A->next,q = B->next;
while(p->next != A){
p = p->next;
}
while(q->next != B){
q = q->next;
}
p->next = B->next;
q->next = A;
return A;
}
创建一个新链表,然后把每个链表的数据都取出来,跑一遍排序,最后放入新链表。
反转也有两种方法:
这里挑第二种方法跑了一遍代码、
Linklist reverse(Linklist &L){
printf("revesing\n");
Linklist p = L->next;
int i = 0,count = Count(L);
int a[count];
while(p->next!= L){
a[i] = p->value;
p = p->next;
i++;
}
a[i] = p->value;
p = L->next;
while(p!=L){
p->value = a[i];
p = p->next;
i--;
}
return L;
}
对于循环链表来说,判空等价于头节点的next是否指向自己或者链表记录数据的节点数为0。
单链表就是记录数据的节点数为0或者头节点的next指向空
代码只有一些常规操作,新增的一些操作会在后期补上。
#include
#include
typedef struct CNode{
int value;
struct CNode *next;
}Cnode,*Linklist;
Linklist initList(Linklist &L){
L = (Linklist)malloc(sizeof(Cnode));
L->next = L;
return L;
}
//一个一个插入数据
Linklist insert(Linklist &L){
int x;
printf("input x\n");
scanf("%d",&x);
Linklist p = (Linklist)malloc(sizeof(Cnode)),q = L;
p->value = x;
p->next = L;
while(q->next != L){
q = q->next;
}
q->next = p;
}
void display(Linklist L){
Linklist p = L->next;
int i = 0 ;
while(p != L){
printf("%d ",p->value);
p = p->next;
i ++;
}
printf("\n");
return;
}
int main(){
Linklist L,A,B;
initList(A);
initList(B);
int i = 0;
while(i<4){
insert(A);
insert(B);
i ++;
display(A);
display(B);
}
//combine(A,B);
//display(A);
//Emptyandfree(B);
display(B);
}