引入
我们讲了顺序存储结构、单链表、静态链表,今天我们学习一种新的链表,单循环链表,单循环链表很简单,其实就是在单链表的基础上,将头尾相连,形成一个单向环装循环。
单循环链表
我们知道,单链表非常有趣,虽然不连续,但却根据指针一个连着一个,但是单链表有一个问题,我们如果不从头结点出发,就无法访问所有结点。
解决方法也非常简单,就是把链表终端结点得指针由 NULL 改成指向头结点。也就是链表最后一个结点存储得指针为头结点得指针,也就是原来 head 存储的地址。
既然head 和 最后一个结点 都指向头结点,那么我们就称这种头尾相接得单链表位单循环链表。
单循环链表的特点
既然头尾相接,那么单循环链表有新增了下面几种特性
- head 指向头结点,尾部也指向头结点
- 判断空表得时候,只要头结点和头部指向得内容都是该结点本身,那么这个表就是空表。
- 头结点即尾部,头结点指向头结点,head 指向头结点
- 原来是 head->next 是否为 NULL,是就为
空表。 - 现在是 head 是否等于 head->next,即头结点指针指向它自己
- 我们把最
后一个结点得指针称为 rear
单循环链表
我们先生成一个5结点的链表,然后向后插入一位,看看,还是不是单向循环链表。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LEN sizeof(struct Student)
#define MAXSIZE 5
struct Student{
int num;
float score;
struct Student *next;
};
struct Student *stu_init(){
srand((time(0)));
struct Student *a,*b,*head;
a=b=(struct Student *)malloc(LEN);
int n=0;
while(n<=MAXSIZE){
a=(struct Student *)malloc(LEN);
a->num=n;
a->score=rand()%100+1;
if(n==1){
head=a;
b=a;
}else{
b->next=a;
b=a;
}
n=n+1;
}
b->next=head;
return head;
}
void stu_printf(struct Student *stu_p){
struct Student *stu,*head;
stu=head=stu_p;
while(stu->next!=head){
printf("%d号%3.1f分\n",stu->num,stu->score);
stu=stu->next;
}
}
void stu_insert(struct Student *stu_p , int num , float data){
struct Student *target , *temp;
target=stu_p;
if(num==1){
target->num=num;
target->score=data;
target->next=stu_p;
}else{
for(int l=0;l<num-1;l++){
target=target->next;
}
temp=(struct Student *)malloc(LEN);
temp->score=data;
temp->num=num;
temp->next=target->next;
target->next=temp;
}
printf("%d\n",temp->next->num);
}
int main(){
struct Student *stu;
stu=stu_init();
stu_insert(stu, 5, 11.1);
stu_printf(stu);
}
输出
1
1号65.0分
2号25.0分
3号66.0分
4号12.0分
5号47.0分
**初始化:**初始化完成后,一定要记得把首尾相连,否则构不成循环。
**插入:**插入的时候一定要记得沿着链表来找,找到前一个,然后将其指针域赋值给插入得结点,然后将指针域指向插入的结点的地址。
**判断:**上面的1输出得是printf("%d\n",temp->next->num); 也就是最后插入的这个结点的下一结点得编号,如果是循环链表的话,那么就应该是1才对,因为又会指向头结点。
尾巴
这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。
评论