对于单链表,由于每个结点只存储了向后的指针,到了尾标志就停止了向后的操作,这样,当某一个结点找不到前驱结点了,也不能回去找。而我们现在要解决这个问题,就要利用循环链表。
将单链表中终端结点的指针端由空指针改为指向头结点,就使整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。
循环链表解决了一个很麻烦的问题:如何从一个结点出发,访问到链表的全部结点。
为了使空链表与非空链表处理一致,我们通常设一个头结点,当然,并不是说循环链表一定要有头结点。
其实循环链表和单链表的主要差异在于循环的判断条件上,之前是判断temp->next是否为空,现在是temp->next不等于头结点。
一、设头结点
- #include <stdio.h>
- #include <stdlib.h>
- /*
- =================
- 定义链表数据结构
- =================
- */
- struct node
- {
- int num;
- struct node *next; //next存放下一个结点的地址
- };
- typedef struct node Node;
- typedef Node * Link;
- /*
- ===================
- 功能:设头结点
- 返回:void
- ===================
- */
- void init_link(Link *head)
- {
- *head = (Link)malloc(sizeof(Node));
- (*head)->next = *head;
- }
- int main()
- {
- Link head; //创建头指针
- init_link(&head); //设头结点
- return 0;
- }
二、插入结点
1、头插
- #include <stdio.h>
- #include <stdlib.h>
- /*
- =================
- 定义链表数据结构
- =================
- */
- struct node
- {
- int num;
- struct node *next; //next存放下一个结点的地址
- };
- typedef struct node Node;
- typedef Node * Link;
- /*
- ===================
- 功能:设头结点
- 返回:void
- ===================
- */
- void init_link(Link *head)
- {
- *head = (Link)malloc(sizeof(Node));
- (*head)->next = *head;
- }
- /*
- =========================
- 功能:从链表头部插入结点
- 返回:void
- =========================
- */
- void insert_head_node(Link newnode, Link *head)
- {
- newnode->next = (*head)->next;
- (*head)->next = newnode;
- }
- /*
- =================
- 功能:打印链表
- 返回:void
- =================
- */
- void print(Link head)
- {
- Link temp = head->next;
- while (temp != head) //遍历链表
- {
- printf("%d\n",temp->num);
- temp = temp->next;
- }
- }
- int main()
- {
- Link head; //创建头指针
- Link newnode; //创建新结点
- init_link(&head); //设头结点
- int i;
- for (i = 0; i < 10; i++)
- {
- newnode = (Link)malloc(sizeof(Node)); //逐一为结点分配空间
- newnode->num = i + 1; //逐一为结点数据域赋值
- insert_head_node(newnode,&head); //头插
- }
- printf("头插后的链表为:\n");
- print(head); //打印链表
- return 0;
- }
运行结果:
- 头插后的链表为:
- 10
- 9
- 8
- 7
- 6
- 5
- 4
- 3
- 2
- 1
2、尾插
- #include <stdio.h>
- #include <stdlib.h>
- /*
- =================
- 定义链表数据结构
- =================
- */
- struct node
- {
- int num;
- struct node *next; //next存放下一个结点的地址
- };
- typedef struct node Node;
- typedef Node * Link;
- /*
- ===================
- 功能:设头结点
- 返回:void
- ===================
- */
- void init_link(Link *head)
- {
- *head = (Link)malloc(sizeof(Node));
- (*head)->next = *head;
- }
- /*
- =========================
- 功能:从链表尾部插入结点
- 返回:void
- =========================
- */
- void insert_tail_node(Link newnode, Link *head)
- {
- Link temp = *head;
- while (temp->next != *head) //找到最后一个结点
- {
- temp = temp->next;
- }
- temp->next = newnode; //插入结点
- newnode->next = *head;
- }
- /*
- =================
- 功能:打印链表
- 返回:void
- =================
- */
- void print(Link head)
- {
- Link temp = head->next;
- while (temp != head) //遍历链表
- {
- printf("%d\n",temp->num);
- temp = temp->next;
- }
- }
- int main()
- {
- Link head; //创建头指针
- Link newnode; //创建新结点
- init_link(&head); //设头结点
- int i;
- for (i = 0; i < 10; i++)
- {
- newnode = (Link)malloc(sizeof(Node)); //逐一为结点分配空间
- newnode->num = i + 1; //逐一为结点数据域赋值
- insert_tail_node(newnode,&head); //尾插
- }
- printf("尾插后的链表为:\n");
- print(head); //打印链表
- return 0;
- }
运行结果:
- 尾插后的链表为:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
3、从中间插入
- #include <stdio.h>
- #include <stdlib.h>
- /*
- =================
- 定义链表数据结构
- =================
- */
- struct node
- {
- int num;
- struct node *next; //next存放下一个结点的地址
- };
- typedef struct node Node;
- typedef Node * Link;
- /*
- ===================
- 功能:设头结点
- 返回:void
- ===================
- */
- void init_link(Link *head)
- {
- *head = (Link)malloc(sizeof(Node));
- (*head)->next = *head;
- }
- /*
- =========================
- 功能:从链表尾部插入结点
- 返回:void
- =========================
- */
- void insert_tail_node(Link newnode, Link *head)
- {
- Link temp = *head;
- while (temp->next != *head) //找到最后一个结点
- {
- temp = temp->next;
- }
- temp->next = newnode; //插入结点
- newnode->next = *head;
- }
- /*
- =====================
- 功能:从中间插入结点
- 返回:是否成功执行
- =====================
- */
- int insert_mid_node(Link newnode, Link head, int num)
- {
- Link temp = head->next;
- while (temp != head) //遍历链表
- {
- if (num == temp->num) //判断是否为要插入的目标结点,是则插入
- {
- newnode->next = temp->next;
- temp->next = newnode;
- return 0;
- }
- temp = temp->next;
- }
- return -1; //遍历整个链表也找不到目标结点,退出
- }
- /*
- =================
- 功能:打印链表
- 返回:void
- =================
- */
- void print(Link head)
- {
- Link temp = head->next;
- while (temp != head) //遍历链表
- {
- printf("%d\n",temp->num);
- temp = temp->next;
- }
- }
- int main()
- {
- Link head; //创建头指针
- Link newnode; //创建新结点
- init_link(&head); //设头结点
- int i;
- for (i = 0; i < 10; i++)
- {
- newnode = (Link)malloc(sizeof(Node)); //逐一为结点分配空间
- newnode->num = i + 1; //逐一为结点数据域赋值
- insert_tail_node(newnode,&head); //尾插
- }
- newnode = (Link)malloc(sizeof(Node)); //为新结点分配空间
- newnode->num = 11;
- insert_mid_node(newnode,head,5); //在数据域为5的结点后插入结点
- printf("从中间插入后的链表为:\n");
- print(head); //打印链表
- return 0;
- }
运行结果:
- 从中间插入后的链表为:
- 1
- 2
- 3
- 4
- 5
- 11
- 6
- 7
- 8
- 9
- 10
三、删除结点
- #include <stdio.h>
- #include <stdlib.h>
- /*
- =================
- 定义链表数据结构
- =================
- */
- struct node
- {
- int num;
- struct node *next; //next存放下一个结点的地址
- };
- typedef struct node Node;
- typedef Node * Link;
- /*
- ===================
- 功能:设头结点
- 返回:void
- ===================
- */
- void init_link(Link *head)
- {
- *head = (Link)malloc(sizeof(Node));
- (*head)->next = *head;
- }
- /*
- =========================
- 功能:从链表尾部插入结点
- 返回:void
- =========================
- */
- void insert_tail_node(Link newnode, Link *head)
- {
- Link temp = *head;
- while (temp->next != *head) //找到最后一个结点
- {
- temp = temp->next;
- }
- temp->next = newnode; //插入结点
- newnode->next = *head;
- }
- /*
- ===================
- 功能:删除某个结点
- 返回:是否成功
- ===================
- */
- int del_mid_node(Link *head, int num)
- {
- if (*head == (*head)->next) //判断是否为空表,空表则退出
- {
- return -1;
- }
- Link temp = *head;
- Link ptr = temp; //ptr指向temp的结点
- temp = temp->next; //temp指向下一个结点,即ptr指向temp前面的结点
- while (temp != *head) //遍历链表
- {
- if (num == temp->num) //判断是否是要删除的结点,是则删除
- {
- ptr->next = temp->next;
- free(temp);
- temp = NULL;
- return 0;
- }
- ptr = temp;
- temp = temp->next;
- }
- return -1; //遍历整个链表也找不到目标结点,则退出
- }
- /*
- =================
- 功能:打印链表
- 返回:void
- =================
- */
- void print(Link head)
- {
- Link temp = head->next;
- while (temp != head) //遍历链表
- {
- printf("%d\n",temp->num);
- temp = temp->next;
- }
- }
- int main()
- {
- Link head; //创建头指针
- Link newnode; //创建新结点
- init_link(&head); //设头结点
- int i;
- for (i = 0; i < 10; i++)
- {
- newnode = (Link)malloc(sizeof(Node)); //逐一为结点分配空间
- newnode->num = i + 1; //逐一为结点数据域赋值
- insert_tail_node(newnode,&head); //尾插
- }
- del_mid_node(&head,5); //删除数据域为5的结点
- printf("删除数据域为5的结点后的链表为:\n");
- print(head); //打印链表
- return 0;
- }
运行结果:
- 删除数据域为5的结点后的链表为:
- 1
- 2
- 3
- 4
- 6
- 7
- 8
- 9
- 10
四、逆序
- #include <stdio.h>
- #include <stdlib.h>
- /*
- =================
- 定义链表数据结构
- =================
- */
- struct node
- {
- int num;
- struct node *next; //next存放下一个结点的地址
- };
- typedef struct node Node;
- typedef Node * Link;
- /*
- ===================
- 功能:设头结点
- 返回:void
- ===================
- */
- void init_link(Link *head)
- {
- *head = (Link)malloc(sizeof(Node));
- (*head)->next = *head;
- }
- /*
- =========================
- 功能:从链表尾部插入结点
- 返回:void
- =========================
- */
- void insert_tail_node(Link newnode, Link *head)
- {
- Link temp = *head;
- while (temp->next != *head) //找到最后一个结点
- {
- temp = temp->next;
- }
- temp->next = newnode; //插入结点
- newnode->next = *head;
- }
- /*
- ===============
- 功能:逆序链表
- 返回:是否成功
- ===============
- */
- int reverse_link(Link *head)
- {
- /*判断是否只有一个头结点或除了头结点只有一个结点,是则退出*/
- if (*head == (*head)->next || *head == (*head)->next->next)
- {
- return -1;
- }
- Link str = *head;
- Link ptr = str->next;
- Link temp = ptr->next;
- while (*head != temp)
- {
- ptr->next = str;
- str = ptr;
- ptr = temp;
- temp = temp->next;
- }
- ptr->next = str;
- (*head)->next->next = *head;
- (*head)->next = ptr;
- return 0;
- }
- /*
- =================
- 功能:打印链表
- 返回:void
- =================
- */
- void print(Link head)
- {
- Link temp = head->next;
- while (temp != head) //遍历链表
- {
- printf("%d\n",temp->num);
- temp = temp->next;
- }
- }
- int main()
- {
- Link head; //创建头指针
- Link newnode; //创建新结点
- init_link(&head); //设头结点
- int i;
- for (i = 0; i < 10; i++)
- {
- newnode = (Link)malloc(sizeof(Node)); //逐一为结点分配空间
- newnode->num = i + 1; //逐一为结点数据域赋值
- insert_tail_node(newnode,&head); //尾插
- }
- reverse_link(&head); //逆序
- printf("逆序后的链表为:\n");
- print(head); //打印链表
- return 0;
- }
运行结果:
- 逆序后的链表为:
- 10
- 9
- 8
- 7
- 6
- 5
- 4
- 3
- 2
- 1