数据结构实验:单链表(一)

实验目的

掌握线性表的链式存储结构及其基本操作。

二、实验内容

实现一个简单的学生信息管理系统,该系统的功能有:

1、利用单链表建立学生基本信息表;

2、浏览每个学生的信息;

3、根据学号查询某个学生的基本信息;

4、添加学生信息到单链表中;

5、删除一个学生的信息。

三、实验环境

Visual Studio 2022

四、实验内容与完成情况

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义学生信息结构体类型
struct Student {
    char id[20];  
    char name[20]; 
    int age;       
    char sex;      
};

// 定义单链表的节点类型
struct Node {
    struct Student data;  
    struct Node* next;    
};

// 定义单链表类型
struct LinkedList {
    struct Node* head;   // 表头
    int size;           
};

// 初始化单链表
void initList(struct LinkedList* list) {
    list->head = (struct Node*)malloc(sizeof(struct Node));
    list->head->next = NULL;
    list->size = 0;
}

// 浏览每个学生的信息
void browse(struct LinkedList* list) {
    struct Node* p = list->head->next;
    while (p != NULL) {
        printf("学号:%s\t姓名:%s\t年龄:%d\t性别:%c\n",
            p->data.id, p->data.name, p->data.age, p->data.sex);
        p = p->next;
    }
}

// 根据学号查询某个学生的基本信息
void search(struct LinkedList* list) {
    char id[20];
    printf("请输入要查询的学生学号:");
    scanf("%s", id);

    struct Node* p = list->head->next;
    int found = 0;
    while (p != NULL) {
        if (strcmp(p->data.id, id) == 0) {
            found = 1;
            printf("学号:%s\t姓名:%s\t年龄:%d\t性别:%c\n",
                p->data.id, p->data.name, p->data.age, p->data.sex);
            break;
        }
        p = p->next;
    }

    if (!found) {
        printf("未找到该学生信息!\n");
    }
}

// 添加学生信息到单链表中
void add(struct LinkedList* list) {
    char id[20];
    char name[20];
    int age;
    char sex;

    printf("请输入学生学号:");
    scanf("%s", id);
    printf("请输入学生姓名:");
    scanf("%s", name);
    printf("请输入学生年龄:");
    scanf("%d", &age);
    printf("请输入学生性别(M/F):");
    scanf(" %c", &sex);

    struct Node* p = (struct Node*)malloc(sizeof(struct Node));
    strcpy(p->data.id, id);
    strcpy(p->data.name, name);
    p->data.age = age;
    p->data.sex = sex;
    p->next = list->head->next;
    list->head->next = p;
    list->size++;

    printf("添加成功!\n");
}

// 删除一个学生的信息
void removeStudent(struct LinkedList* list) {
    char id[20];
    printf("请输入要删除的学生学号:");
    scanf("%s", id);

    struct Node* p = list->head;
    int found = 0;
    while (p->next != NULL) {
        if (strcmp(p->next->data.id, id) == 0) {
            found = 1;
            struct Node* q = p->next;
            p->next = q->next;
            free(q);
            list->size--;
            printf("删除成功!\n");
            break;
        }
        p = p->next;
    }

    if (!found) {
        printf("未找到该学生信息!\n");
    }
}

// 主函数
int main() {
    struct LinkedList list;
    initList(&list);

    // 将这些学生信息加入到链表中
     const char* ids[] = { "20180001","20180003","20180004","20180010",
                   "20180008","20180002","20180007","20180005",
                   "20180009","20180006" };
    const char* names[] = { "王晓佳","林一鹏","谢宁","张丽娟","刘家琪",
                     "成平","赵学意","江永康","郑可欣","李小燕" };
    int ages[] = { 21, 22, 23, 24, 23, 21, 23, 24, 23, 22 };
    char sexes[] = { 'F', 'M', 'M', 'F', 'F',
                    'M', 'M', 'M', 'F', 'F' };

    for (int i = 0; i < 10; i++) {
        struct Node* p = (struct Node*)malloc(sizeof(struct Node));
        strcpy(p->data.id, ids[i]);
        strcpy(p->data.name, names[i]);
        p->data.age = ages[i];
        p->data.sex = sexes[i];
        p->next = list.head->next;
        list.head->next = p;
        list.size++;
    }

    // 循环显示菜单,等待用户操作
    while (1) {
        printf("请选择要进行的操作:\n");
        printf("1:浏览学生信息\n");
        printf("2:查询学生信息\n");
        printf("3:添加学生信息\n");
        printf("4:删除学生信息\n");
        printf("5:退出程序\n");
        int control;
        scanf("%d", &control);
        switch (control) {
        case 1:
            browse(&list);
            break;
        case 2:
            search(&list);
            break;
        case 3:
            add(&list);
            break;
        case 4:
            removeStudent(&list);
            break;
        case 5:
            printf("程序已退出!\n");
            return 0;
        default:
            printf("输入错误,请重新选择!\n");
        }
    }

    return 0;
}

五、出现的问题及对问题的解决方案

1. 语法错误:因为写错标点符号、函数名等导致编译失败。解决方案: 认真检查代码并逐个排查可能存在错误的地方。

2. 提示" error C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.",解决方案: 因为用CPP运行C语言程序中strcpy 函数不安全,可以使用更加安全的strcpy_s函数代替。也可以在文件开头加上一行代码:#define _CRT_SECURE_NO_WARNINGS。

六、实验思考

1.链表头节点的作用:链表头节点是指第一个节点之前的节点,它并不保存数据,只是为了方便操作而存在。在创建链表时,要给头节点分配内存空间,并将头节点的next指针初始化为NULL。

2.节点的创建和销毁:链表中的每个节点都需要动态申请内存空间,创建完之后需要手动释放。在插入和删除节点时,一定要注意释放被删除节点的内存空间,避免内存泄漏。

3.插入和删除节点:插入和删除节点时,需要考虑新节点的位置和相邻节点的关系。头插法和尾插法是两种常见的插入操作,头插法适用于不需要保持顺序的情况,而尾插法适用于需要保持顺序的情况。删除节点时,要先找到要删除节点的前驱节点,然后将前驱节点的next指针指向后继节点,最后释放被删除节点的内存空间。

4.遍历链表:遍历链表时,可以使用一个指针从头节点开始,逐一访问每个节点,直到最后一个节点。在访问每个节点时,可以使用节点中存储的数据,执行具体的操作。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值