一郎科技|就靠这20+张图了,一口气搞懂「链表」( 七 )


//插入元素
list*insert_list(list*head,intpos,intdata){
//三个参数分别是链表 , 位置 , 参数
list*node=initlist;//新建结点
list*p=head;//p表示新的链表
list*t;
t=p;
node->data=https://pcff.toutiao.jxnews.com.cn/p/20200829/data;
if(head!=){
for(inti=1;it=t->next;//走到需要插入的位置处
}
node->next=t->next;
t->next=node;
returnp;
}
returnp;
}
循环单链表的删除操作如下图所示 , 循环单链表的删除操作是先找到需要删除的结点 , 将其前一个结点的next指针直接指向删除结点的下一个结点即可 。
需要注意的是尾结点 , 因为删除尾节点后 , 尾节点前一个结点就成了新的尾节点 , 这个新的尾节点需要指向的是头结点而不是空 。
//删除元素
intdelete_list(list*head){
if(head==){
printf("链表为空!n");
return0;
}
//建立临时结点存储头结点信息(目的为了找到退出点)
//如果不这么建立的化需要使用一个数据进行计数标记 , 计数达到链表长度时自动退出
//循环链表当找到最后一个元素的时候会自动指向头元素 , 这是我们不想让他发生的
list*temp=head;
list*ptr=head->next;
intdel;
printf("请输入你要删除的元素:");
scanf("%d",&del);
while(ptr!=head){
if(ptr->data=https://pcff.toutiao.jxnews.com.cn/p/20200829/=del){
if(ptr->next==head){
temp->next=head;
free(ptr);
return1;
}
temp->next=ptr->next;//核心删除操作代码
free(ptr);
//printf("元素删除成功!n");
return1;
}
temp=temp->next;
ptr=ptr->next;
}
printf("没有找到要删除的元素n");
return0;
}
循环单链表的遍历与普通的单链表和双向链表的遍历不同 , 循环链表需要进行结点的特殊判断 。
先找到尾节点的位置 , 由于尾节点的next指针是指向头结点的 , 所以不能使用链表本身是否为空的方法进行简单的循环判断 , 我们需要通过判断结点的next指针是否等于头结点的方式进行是否完成循环的判断 。
此外还有一种计数的方法 , 即建立一个计数器count=0 , 每一次next指针指向下一个结点时计数器+1 , 当count数字与链表的节点数相同的时候即完成循环;
但是这样做会有一个问题 , 就是获取到链表的节点数同时 , 也需要完成一次遍历才可以达成目标 。
其代码如下:
//遍历元素
intdisplay(list*head){
if(head!=){
list*p=head;
//遍历头节点到 , 最后一个数据
while(p->next!=head){
printf("%d",p->next->data);
p=p->next;
}
printf("n");//换行
//把最后一个节点赋新的节点过去
return1;
}else{
printf("头结点为空!n");
return0;
}
}
进阶概念——双向循环链表循环单链表也有一个孪生兄弟——双向循环链表 , 其设计思路与单链表和双向链表的设计思路一样 , 就是在原有的双向链表的基础上 , 将尾部结点和头部结点进行互相连接 。 交给大家了 。


推荐阅读