数据结构——单向循环链表代码(补充)

发布于:2025-09-09 ⋅ 阅读:(15) ⋅ 点赞:(0)

在此前的文章中(链接如下),只有单向链表的代码,接下来我们来写单向循环链表,并用其实现一个简单的学生信息链表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);
}


网站公告

今日签到

点亮在社区的每一天
去签到