在此前的文章中(鏈接如下),只有單向鏈表的代碼,接下來我們來寫單向循環鏈表,并用其實現一個簡單的學生信息鏈表https://blog.csdn.net/2301_80406299/article/details/151157051?spm=1011.2415.3001.10575&sharefrom=mp_manage_link
1、單向鏈表與單向循環鏈表的不同
單向鏈表:尾節點的?
next
?指針堅定地指向?NULL
。這個?NULL
?像一個終點站的標志,明確告知遍歷者:“鏈表至此結束,前方無路”。這使得單向鏈表在邏輯上呈現為一種線性開環結構,有頭有尾,有明確的起點和終點。
單向循環鏈表:尾節點的?
next
?指針則指向了頭節點。這一指向,如同將一條繩子的首尾相接,形成了一個閉合的環。它移除了結束的標志,使得遍歷操作可以在鏈表中無限循環。因此,它是一種環形結構,沒有傳統意義上的“終點”。
單向循環鏈表代碼——學生信息鏈表
主函數? main.c
/********************************************************************************* @file main.c* @author feng* @version V0.0.1* @date 2025.09.08* @brief 使用單向循環鏈表實現數據的增刪查改——學生信息鏈表* 環境:ubuntu18.04* 編譯+執行:./project.sh******************************************************************************** @attention** 本文檔只供裝逼學習使用,不得商用,違者必究** github: https://github.com/(求我拿鏈接)* CSDN: https://blog.csdn.net/(嘻嘻)* gitee: https://gitee.com/(求我拿鏈接)* 微信公眾號: 沒有* 沒有疑問或者建議:12345678910@qq.com** *******************************************************************************/#include "singly_circular_link_list.h"int main(int argc, char const *argv[])
{node_p head_node = sc_link_list_InitHeadNode();if (head_node == NULL){printf("頭節點初始化失敗!\n");return -1;}node_p new_node = NULL;int select = 0;char name[20];int id, grade, age;float score;int search_id, del_id, change_id;while (1){sc_link_list_ShowListData(head_node);printf("\n請選擇以下功能:\n");printf("1、插入數據(頭插法)\n");printf("2、插入數據(尾插法)\n");printf("3、刪除數據\n");printf("4、修改數據\n");printf("5、查找數據\n");printf("6、退出系統\n");printf("請選擇: ");scanf("%d", &select);while (getchar() != '\n'); // 清空輸入緩沖區switch (select){case 1: // 頭插法printf("\n--- 添加學生(頭插法) ---\n");printf("姓名: "); scanf("%19s", name);printf("學號: "); scanf("%d", &id);printf("年級: "); scanf("%d", &grade);printf("成績: "); scanf("%f", &score);printf("年齡: "); scanf("%d", &age);while (getchar() != '\n'); new_node = sc_link_list_InitDataNode(name, id, grade, score, age);if (!new_node) {printf("創建節點失敗!\n");break;}sc_link_list_HeadInsert(head_node, new_node);printf("添加成功!\n");break;case 2: printf("\n--- 添加學生(尾插法) ---\n");printf("姓名: "); scanf("%19s", name);printf("學號: "); scanf("%d", &id);printf("年級: "); scanf("%d", &grade);printf("成績: "); scanf("%f", &score);printf("年齡: "); scanf("%d", &age);while (getchar() != '\n'); new_node = sc_link_list_InitDataNode(name, id, grade, score, age);if (!new_node) {printf("創建節點失敗!\n");break;}sc_link_list_LastInsert(head_node, new_node);printf("添加成功!\n");break;case 3: // 刪除printf("\n請輸入要刪除的學生學號: ");scanf("%d", &del_id);while (getchar() != '\n');if (sc_link_list_DelNodeData(head_node, del_id) == 0) {printf("刪除成功!\n");}break;case 4: // 修改printf("\n請輸入要修改的學生學號: ");scanf("%d", &change_id);while (getchar() != '\n'); printf("輸入新的信息(留空則保持不變):\n");printf("姓名: "); scanf("%19s", name);printf("年級(0保持不變): "); scanf("%d", &grade);printf("成績(-1保持不變): "); scanf("%f", &score);printf("年齡(0保持不變): "); scanf("%d", &age);while (getchar() != '\n'); if (sc_link_list_ChangeNodeData(head_node, change_id, name[0] ? name : NULL, grade, score, age) == 0) {printf("修改成功!\n");}break;case 5:printf("\n請輸入要查找的學生學號: ");scanf("%d", &search_id);while (getchar() != '\n');sc_link_list_SearchNodeData(head_node, search_id);break;case 6: // 退出sc_link_list_Uninit(head_node);printf("系統已退出!\n");return 0;default:printf("無效選擇,請重新輸入!\n");break;}}
}
?
頭文件 singly_circular_link_list.h
/********************************************************************************* @file singly_circular_link_list.h* @author feng* @version V0.0.1* @date 2025.29.28* @brief 單向循環鏈表的增刪查改功能——學生信息鏈表* ******************************************************************************* @attention** 本文檔只供學習使用,不得商用,違者必究* * github: https://github.com/(求我拿鏈接)* CSDN: https://blog.csdn.net/(嘻嘻)* gitee: https://gitee.com/(求我拿鏈接)* 微信公眾號: 沒有* 沒有疑問或者建議:12345678910@qq.com* * *******************************************************************************/#ifndef SINGLY_CIRCULAR_LINK_LIST_H
#define SINGLY_CIRCULAR_LINK_LIST_H#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>typedef struct student {char name[20];int id;int grade;float score;int age;
} student_t;typedef struct node {student_t data; struct node *next_p;
} node_t, *node_p;node_p sc_link_list_InitHeadNode(void);
node_p sc_link_list_InitDataNode(const char *name, int id, int grade, float score, int age); // 修改3: 參數列表修改
void sc_link_list_HeadInsert(node_p head_node, node_p new_node);
void sc_link_list_LastInsert(node_p head_node, node_p new_node);
bool sc_link_list_IfEmpty(node_p head_node);
int sc_link_list_ShowListData(node_p head_node);
int sc_link_list_DelNodeData(node_p head_node, int del_id); // 修改4: 改為按學號刪除
int sc_link_list_ChangeNodeData(node_p head_node, int find_id, const char *new_name, int new_grade, float new_score, int new_age); // 修改5: 參數列表修改
int sc_link_list_SearchNodeData(node_p head_node, int search_id); // 修改6: 改為按學號查找
void sc_link_list_Uninit(node_p head_node);#endif
功能函數:singly_circular_link_list
#include "singly_circular_link_list.h"node_p sc_link_list_InitHeadNode(void)
{node_p p = malloc(sizeof(node_t));if (p != NULL){memset(p, 0, sizeof(node_t));p->next_p = p;}return p;
}node_p sc_link_list_InitDataNode(const char *name, int id, int grade, float score, int age)
{node_p p = malloc(sizeof(node_t));if (p != NULL){memset(p, 0, sizeof(node_t));strncpy(p->data.name, name, sizeof(p->data.name)-1);p->data.id = id;p->data.grade = grade;p->data.score = score;p->data.age = age;p->next_p = p;}return p;
}void sc_link_list_HeadInsert(node_p head_node, node_p new_node)
{new_node->next_p = head_node->next_p;head_node->next_p = new_node;
}void sc_link_list_LastInsert(node_p head_node, node_p new_node)
{node_p temp_p = head_node;while (temp_p->next_p != head_node){temp_p = temp_p->next_p;}temp_p->next_p = new_node;new_node->next_p = head_node;
}bool sc_link_list_IfEmpty(node_p head_node)
{return head_node->next_p == head_node;
}int sc_link_list_ShowListData(node_p head_node)
{if (sc_link_list_IfEmpty(head_node)){printf("鏈表為空!\n");return -1;}node_p tem_p = head_node->next_p;int i = 0;printf("\n==================學生信息列表===================\n");while (tem_p != head_node){printf("學生 %d:\n", i+1);printf(" 姓名: %s\n", tem_p->data.name);printf(" 學號: %d\n", tem_p->data.id);printf(" 年級: %d\n", tem_p->data.grade);printf(" 成績: %.2f\n", tem_p->data.score);printf(" 年齡: %d\n", tem_p->data.age);printf("--------------------------------------------\n");tem_p = tem_p->next_p;i++;}printf("================================================\n");return 0;
}int sc_link_list_DelNodeData(node_p head_node, int del_id)
{if (sc_link_list_IfEmpty(head_node))return -1;node_p prev_p = head_node;node_p curr_p = head_node->next_p;while (curr_p != head_node){if (curr_p->data.id == del_id){prev_p->next_p = curr_p->next_p;free(curr_p);return 0;}prev_p = curr_p;curr_p = curr_p->next_p;}printf("未找到學號為 %d 的學生\n", del_id);return -1;
}int sc_link_list_ChangeNodeData(node_p head_node, int find_id, const char *new_name, int new_grade, float new_score, int new_age)
{if (sc_link_list_IfEmpty(head_node))return -1;node_p tem_p = head_node->next_p;while (tem_p != head_node){if (tem_p->data.id == find_id){if (new_name) strncpy(tem_p->data.name, new_name, sizeof(tem_p->data.name)-1);if (new_grade > 0) tem_p->data.grade = new_grade;if (new_score >= 0) tem_p->data.score = new_score;if (new_age > 0) tem_p->data.age = new_age;return 0;}tem_p = tem_p->next_p;}printf("未找到學號為 %d 的學生\n", find_id);return -1;
}int sc_link_list_SearchNodeData(node_p head_node, int search_id)
{if (sc_link_list_IfEmpty(head_node))return -1;node_p tem_p = head_node->next_p;while (tem_p != head_node){if (tem_p->data.id == search_id){printf("\n找到學生信息:\n");printf(" 姓名: %s\n", tem_p->data.name);printf(" 學號: %d\n", tem_p->data.id);printf(" 年級: %d\n", tem_p->data.grade);printf(" 成績: %.2f\n", tem_p->data.score);printf(" 年齡: %d\n", tem_p->data.age);return 0;}tem_p = tem_p->next_p;}printf("未找到學號為 %d 的學生\n", search_id);return -1;
}void sc_link_list_Uninit(node_p head_node)
{if (!head_node) return;node_p curr_p = head_node->next_p;while (curr_p != head_node){node_p next_p = curr_p->next_p;free(curr_p);curr_p = next_p;}free(head_node);
}