结构-循环链表的实现
3.循环链表的实现
3.1定义一个结点
typedef struct list{
int data;
struct list *next;
}list;
//data为存储的数据,next指针为指向下一个结点
//和单链表的结点一样。
3.2初始化一个结点
//初始结点
list *initlist(){
list *head=(list*)malloc(sizeof(list));
if(head==NULL){
printf("创建失败,退出程序");
exit(0);
}else{
head->next=NULL;
return head;
}
}
//由于循环链表的特殊性,已经为之后的方便使用,一个初始化好的循环链表的头结点的next需要指向自身。
//所以上面的操作是不完整的,在具体使用的时候,我们还需要在主函数里加上如下操作:
在主函数重调用可以是这样
//////////初始化头结点//////////////
list *head=initlist();
head->next=head;
3.3创建循环链表
注意是’创建---插入数据‘,这说明一个循环链表的创建是在数据逐个的插入中完成的。
但这个插入还和插入操作的插入不一样,那个插入是在目标位置,而这个插入是在表的末尾(虽然循环链表没有什么开始结束之类的,但名义上的head和end还是有的)
//创建——插入数据
int insert_list(list *head){
int data; //插入的数据类型
printf("请输入要插入的元素:");
scanf("%d",&data);
list *node=initlist();
node->data=data;
//初始化一个新的结点,准备进行链接
if(head!=NULL){
list *p=head;
//找到最后一个数据
while(p->next!=head){//①
p=p->next;
}
p->next=node;
node->next=head;
return 1;
}else{
printf("头结点已无元素\n");
return 0;
}
}
//①前面的单链表和双向链表通过NULL找到链表的结尾,而循环链表通过链表头next的地址head找到链表名义上的结尾。循环链表也正是通过这种方法实现在链表所谓结尾的插入。
3.4插入新结点
//插入元素
list *insert_list(list *head,int pos,int data){
//三个参数分别是链表,位置,参数
list *node=initlist(); //新建结点
list *p=head; //p表示新的链表
list *t;
t=p;
node->data=data;
if(head!=NULL){
for(int i=1;i<pos;i++){
t=t->next; //走到需要插入的位置处
}
node->next=t->next;
t->next=node;
return p;
}
return p;
}
3.5删除结点
//删除元素
int delete_list(list *head) {
if(head == NULL) {
printf("链表为空!\n");
return 0;
}
//建立临时结点存储头结点信息(目的为了找到退出点)
//如果不这么建立的化需要使用一个数据进行计数标记,计数达到链表长度时自动退出
//循环链表当找到最后一个元素的时候会自动指向头元素,这是我们不想让他发生的------①
list *temp = head; //此时temp指向头结点
list *ptr = head->next; //此时ptr指向头结点的下一个节点
int del;
printf("请输入你要删除的元素:");
scanf("%d",&del);
while(ptr != head) {
if(ptr->data == del) {
if(ptr->next == head) { //判断删除节点是否为尾结点
temp->next = head;
free(ptr);
return 1; //跳出循环
}
temp->next = ptr->next; //核心删除操作代码
free(ptr); //说明了ptr是目标删除结点。
//printf("元素删除成功!\n");
return 1;
}
temp = temp->next;
ptr = ptr->next; //标准的遍历操作。
}c
printf("没有找到要删除的元素\n");
return 0;
}
//观察前面的链表就能明白是什么意思。前面链表用while和NULL判断循环并退出,而循环列表没有NULL。为了避免死循环,我们需要采用其他策略——例如利用链表头的地址当作循环条件判断跳出循环,当然也可以用代码注释中说的计数器来判断终止循环。
3.6循环链表的遍历
//遍历元素
int display(list *head) {
if(head != NULL) {
list *p = head;
//遍历头节点到,最后一个数据
while(p->next != head ) {
printf("%d ",p->next->data);
p = p->next;
}
printf("\n"); //习惯性换行 ( o=^•ェ•)o ┏━┓
//把最后一个节点赋新的节点过去
return 1;
} else {
printf("头结点为空!\n");
return 0;
}
}
//关键还是找到合适的终止循环条件。目前已知的就是计数器和链表头地址。
3.7完整的循环链表代码
#include<stdio.h>
#include<stdlib.h>
typedef struct list{
int data;
struct list *next;
}list;
//data为存储的数据,next指针为指向下一个结点
//初始结点
list *initlist(){
list *head=(list*)malloc(sizeof(list));
if(head==NULL){
printf("创建失败,退出程序");
exit(0);
}else{
head->next=NULL;
return head;
}
}
//创建--插入数据
int create_list(list *head){
int data; //插入的数据类型
printf("请输入要插入的元素:");
scanf("%d",&data);
list *node=initlist();
node->data=data;
//初始化一个新的结点,准备进行链接
if(head!=NULL){
list *p=head;
//找到最后一个数据
while(p->next!=head){
p=p->next;
}
p->next=node;
node->next=head;
return 1;
}else{
printf("头结点已无元素\n");
return 0;
}
}
//插入元素
list *insert_list(list *head,int pos,int data){
//三个参数分别是链表,位置,参数
list *node=initlist(); //新建结点
list *p=head; //p表示新的链表
list *t;
t=p;
node->data=data;
if(head!=NULL){
for(int i=1;i<=pos;i++){
t=t->next;
}
node->next=t->next;
t->next=node;
return p;
}
return p;
}
//删除元素
int delete_list(list *head) {
if(head == NULL) {
printf("链表为空!\n");
return 0;
}
//建立零时结点存储头结点信息(目的为了找到退出点)
//如果不这么建立的化需要使用一个数据进行计数标记,计数达到链表长度时自动退出
//循环链表当找到最后一个元素的时候会自动指向头元素,这是我们不想让他发生的
list *temp = head;
list *ptr = head->next;
int del;
printf("请输入你要删除的元素:");
scanf("%d",&del);
while(ptr != head) {
if(ptr->data == del) {
if(ptr->next == head) { //循环结束的条件换成ptr->next == head
temp->next = head;
free(ptr);
return 1;
}
temp->next = ptr->next;
free(ptr);
//printf("元素删除成功!\n");
return 1;
}
temp = temp->next;
ptr = ptr->next;
}
printf("没有找到要删除的元素\n");
return 0;
}
//遍历元素
int display(list *head) {
if(head != NULL) {
list *p = head;
//遍历头节点到,最后一个数据
while(p->next != head ) {
printf("%d ",p->next->data);
p = p->next;
}
printf("\n"); //习惯性换行 ( o=^•ェ•)o ┏━┓
//把最后一个节点赋新的节点过去
return 1;
} else {
printf("头结点为空!\n");
return 0;
}
}
int main(){
//////////初始化头结点//////////////
list *head=initlist();
head->next=head;
////////通过插入元素完善链表/////////
for(int i=0;i<5;i++){ //只是演示使用,不具体提供输入
create_list(head);
}
display(head);
////////////插入元素////////////////
head=insert_list(head,1,10);
display(head);
////////////删除元素////////////////
delete_list(head);
display(head);
return 0;
}

浙公网安备 33010602011771号