编程完成简易单链表及其删除操作的实现。

建立一个大小为3(可扩展为n)个学生成绩信息包括(学号、姓名、成绩)的单向链表,学生数据按学号由小到大顺序排列,要求实现删除操作。输入任意指定学号,从单向链表中删除该学生信息。

二、实验要求:

1、理解并掌握该问题的实现方法。

2、代码书写格式规范,测试结果符合期望结果。

3、通过动态内存产生结点、调用函数完成链表建立、链表遍历、指定结点删除操作,画流程图和实现代码。

5、测试用例如下:

输入:1 张三 80

      2 李四  95

      3 王五  70

删除:2

输出:1 张三 80

      3 王五  70

【流程图】

img


【运行截图】

img


【代码】


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

// 学生数据结构体
typedef struct Student {
    int id;       // 学号
    char name[20];  // 姓名
    float score;  // 成绩
    struct Student* next; // 下一节点指针
} Student;

// 动态生成学生数据节点
Student* createStudent(int id, char* name, float score) {
    Student* newStudent = (Student*)malloc(sizeof(Student));
    newStudent->id = id;
    strcpy(newStudent->name, name);
    newStudent->score = score;
    newStudent->next = NULL;
    return newStudent;
}

// 在单向链表中插入新节点
void insertNode(Student** head, Student* newNode) {
    if (*head == NULL) { // 如果链表为空,则直接将新节点作为头节点
        *head = newNode; 
    } else { // 否则按照学号大小插入新节点
        Student* p = *head;
        Student* q = NULL;
        while (p != NULL && p->id < newNode->id) { // 找到第一个比新节点大的节点
            q = p;
            p = p->next;
        }
        if (q == NULL) { // 如果新节点的学号最小,则将新节点插入头部
            newNode->next = *head;
            *head = newNode;
        } else { // 否则将新节点插入到合适的位置
            q->next = newNode;
            newNode->next = p;
        }
    }
}

// 删除指定学号节点
int deleteNode(Student** head, int id) {
    if (*head == NULL) { // 链表为空,无法删除
        return 0;
    }
    if ((*head)->id == id) { // 如果要删除的节点为头节点
        Student* p = *head;
        *head = (*head)->next; // 将头节点指向下一个节点
        free(p); // 删除原头节点
        return 1;
    }
    Student* p = *head;
    Student* q = NULL;
    while (p != NULL && p->id != id) { // 找到要删除的节点
        q = p;
        p = p->next;
    }
    if (p == NULL) { // 如果没有找到要删除的节点
        return 0;
    }
    q->next = p->next; // 将要删除的节点从链表中断开
    free(p); // 删除该节点
    return 1;
}

// 遍历并输出链表
void printList(Student* head) {
    while (head != NULL) { // 遍历整个链表并输出每个节点的信息
        printf("%d %s %.2f\n", head->id, head->name, head->score);
        head = head->next;
    }
}

int main() {
struct Student* head = NULL; // 头指针初始化为空
int choice;
do {
// 输出菜单
printf("请选择要执行的操作:\n");
printf("1. 插入学生信息\n");
printf("2. 删除学生信息\n");
printf("3. 显示所有学生信息\n");
printf("0. 退出\n");
scanf("%d", &choice);

    switch (choice) {
        case 1: { // 插入学生信息
            int id;
            char name[100];
            float score;
            printf("请输入学号、姓名、成绩:");
            scanf("%d %s %f", &id, name, &score);
            insertNode(&head, createStudent(id, name, score));
            break;
        }
        case 2: { // 删除指定学号的学生信息
            int id;
            printf("请输入要删除的学号:");
            scanf("%d", &id);
            if (deleteNode(&head, id)) {
                printf("删除成功!\n");
            } else {
                printf("未找到要删除的节点!\n");
            }
            break;
        }
        case 3: // 输出所有学生信息
            printf("所有学生信息如下:\n");
            printList(head);
            break;
        case 0: // 退出程序
            printf("退出程序\n");
            break;
        default: // 无效选择
            printf("选择无效,请重新输入!\n");
            break;
    }

} while (choice != 0);

return 0;
}
以下回答参考GPT,并由JoseKe整理完成,希望您能采纳:
实现方法如下:

可以先定义一个链表结构体,包括学生信息和下一个节点的指针。

c
// 链表结构体
typedef struct node{
int id; // 学号
char name[20]; // 姓名
int score; // 成绩
struct node *next; // 下一个节点的指针
}Node;


然后实现一个函数来创建链表,该函数首先要输入学生个数,然后循环输入每个学生信息,并按学号从小到大排序加入链表。想要从小到大插入节点,需要遍历节点找到插入位置,具体实现可以看下面的代码。

c
// 创建链表
Node *create(int n) {
if (n <= 0) {
return NULL;
}
// 输入第一个学生的信息
Node *head = (Node*) malloc(sizeof(Node));
head->next = NULL;
printf("请输入第1个学生的信息(学号 姓名 成绩):");
scanf("%d %s %d", &head->id, head->name, &head->score);
// 循环输入每个学生的信息并加入链表(按学号从小到大顺序排列)
for (int i = 1; i < n; i++) {
Node *p = (Node*) malloc(sizeof(Node));
printf("请输入第%d个学生的信息(学号 姓名 成绩):", i+1);
scanf("%d %s %d", &p->id, p->name, &p->score);
Node *q = head, *r = head->next;
while (r && r->id < p->id) {
q = r;
r = r->next;
}
q->next = p;
p->next = r;
}
return head;
}


接着实现删除操作的函数,首先需要遍历链表找到要删除的节点,删除操作也是需要遍历链表找到待删除节点的前一个节点,然后将该节点从链表中摘除并释放内存。

c
// 删除操作
Node *delete(Node *head, int id) {
Node *p = head->next;
Node *q = head;
while (p && p->id != id) {
q = p;
p = p->next;
}
if (p) {
q->next = p->next;
free(p);
} else {
printf("未找到学号为%d的学生信息
", id);
}
return head;
}


最后是完整的代码,包含链表创建、遍历、删除操作。具体实现过程中需要注意许多细节,所以建议认真看代码,并利用注释理解代码。

c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 链表结构体,包括学生信息和下一个节点的指针
typedef struct node {
int id; // 学号
char name[20]; // 姓名
int score; // 成绩
struct node *next; // 下一个节点的指针
} Node;

// 创建链表
Node *create(int n) {
if (n <= 0) {
return NULL; // 如果学生个数不大于0直接返回空指针
}
Node *head = (Node*) malloc(sizeof(Node)); // 创建头节点
head->next = NULL; // 头节点的指针置为NULL,表示链表为空
printf("请输入第1个学生的信息(学号 姓名 成绩):");
scanf("%d %s %d", &head->id, head->name, &head->score);
for (int i = 1; i < n; i++) { // 循环输入每个学生的信息并加入链表(按学号从小到大顺序排列)
Node *p = (Node*) malloc(sizeof(Node));
printf("请输入第%d个学生的信息(学号 姓名 成绩):", i+1);
scanf("%d %s %d", &p->id, p->name, &p->score);
Node *q = head, *r = head->next;
while (r && r->id < p->id) { // 遍历链表,找到要插入的位置
q = r;
r = r->next;
}
q->next = p; // 在q和r之间插入节点p
p->next = r;
}
return head;
}

// 遍历链表
void display(Node *head) {
if (head->next == NULL) { // 如果链表为空
printf("链表为空
");
return;
}
printf("%d %s %d
", head->id, head->name, head->score); // 先输出头节点信息
Node *p = head->next;
while (p) { // 循环遍历链表,输出每个节点的信息
printf("%d %s %d
", p->id, p->name, p->score);
p = p->next;
}
}

// 删除操作
Node *delete(Node *head, int id) {
Node *p = head->next;
Node *q = head;
while (p && p->id != id) { // 遍历链表找到要删除的节点
q = p;
p = p->next;
}
if (p) { // 如果找到了该节点
q->next = p->next; // 将该节点从链表中摘除并释放内存
free(p);
} else {
printf("未找到学号为%d的学生信息
", id);
}
return head;
}

int main() {
int num, id;
Node *head;
printf("请输入学生个数:");
scanf("%d", &num);
head = create(num); // 创建链表
printf("创建链表成功,链表中所有学生的信息如下:
");
display(head); // 遍历链表
printf("请输入要删除的学生的学号:");
scanf("%d", &id);
head = delete(head, id); // 删除指定学生的信息
printf("删除后,链表中所有学生的信息如下:
");
display(head);
return 0;
}

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

//定义学生信息结构体
struct student {
    int num; //学号
    char name[20]; //姓名
    int score; //成绩
    struct student *next; //指向下一个节点的指针
};

//创建链表,并返回头节点指针
struct student* create_list(int n) {
    struct student *head, *p, *q;
    int i;

    head = (struct student *)malloc(sizeof(struct student)); //头节点不存储有效数据
    head->next = NULL;
    q = head;

    for (i = 0; i < n; i++) {
        p = (struct student*)malloc(sizeof(struct student)); //创建新节点
        printf("请输入第%d个学生的学号、姓名、成绩:", i + 1);
        scanf("%d %s %d", &p->num, p->name, &p->score);

        //按照学号大小插入到链表中
        while (q->next != NULL && q->next->num < p->num) {
            q = q->next;
        }
        p->next = q->next;
        q->next = p;

        //将q指针重新指向头节点
        q = head;
    }

    return head;
}

//遍历链表并输出每个节点的信息
void traverse_list(struct student *head) {
    struct student *p;

    p = head->next;
    while (p != NULL) {
        printf("%d %s %d\n", p->num, p->name, p->score);
        p = p->next;
    }
}

//删除链表中指定学号的节点
void delete_node(struct student *head, int num) {
    struct student *p, *q;

    p = head->next;
    q = head;

    //查找要删除的节点
    while (p != NULL && p->num != num) {
        q = p;
        p = p->next;
    }

    if (p != NULL) { //找到了要删除的节点
        q->next = p->next; //将q的next指向p的下一个节点,跳过p这个节点
        free(p); //释放p节点的内存空间
    } else {
        printf("未找到该学生信息!\n");
    }
}

int main() {
    struct student* head;
    int n, num;

    printf("请输入学生的数量:");
    scanf("%d", &n);

    head = create_list(n);
    printf("建立的链表为:\n");
    traverse_list(head);

    printf("请输入要删除的学生学号:");
    scanf("%d", &num);

    delete_node(head, num);
    printf("删除后的链表为:\n");
    traverse_list(head);

    return 0;
}

引用chatGPT作答,以下是用C语言编写的简易单链表及其删除操作的实现:

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

// 定义学生结构体
typedef struct student {
    int id; // 学号
    char name[20]; // 姓名
    int score; // 成绩
    struct student *next; // 指向下一个节点的指针
} Student;

// 在单向链表中插入新的学生信息
Student* insert(Student *head, int id, char name[], int score) {
    Student *new_student = (Student *)malloc(sizeof(Student));
    new_student->id = id;
    strcpy(new_student->name, name);
    new_student->score = score;
    new_student->next = NULL;
    
    // 如果链表为空,则新学生成为头结点
    if (head == NULL) {
        head = new_student;
        return head;
    }
    
    // 如果新学生的学号小于头结点的学号,则将新学生成为头结点
    if (new_student->id < head->id) {
        new_student->next = head;
        head = new_student;
        return head;
    }
    
    // 在单向链表中插入新的学生信息
    Student *temp = head;
    while (temp->next != NULL && new_student->id > temp->next->id) {
        temp = temp->next;
    }
    new_student->next = temp->next;
    temp->next = new_student;
    
    return head;
}

// 在单向链表中删除指定学生信息
Student* delete(Student *head, int id) {
    // 如果链表为空,则直接返回
    if (head == NULL) {
        return head;
    }
    
    // 如果要删除的学生是头结点,则将头结点指向下一个节点
    if (head->id == id) {
        Student *temp = head;
        head = head->next;
        free(temp);
        return head;
    }
    
    // 在单向链表中删除指定学生信息
    Student *temp = head;
    while (temp->next != NULL && temp->next->id != id) {
        temp = temp->next;
    }
    if (temp->next != NULL) {
        Student *delete_student = temp->next;
        temp->next = temp->next->next;
        free(delete_student);
    }
    
    return head;
}

// 打印单向链表中所有学生信息
void print(Student *head) {
    printf("学号\t姓名\t成绩\n");
    Student *temp = head;
    while (temp != NULL) {
        printf("%d\t%s\t%d\n", temp->id, temp->name, temp->score);
        temp = temp->next;
    }
}

int main() {
    Student *head = NULL;
    int id, score, delete_id;
    char name[20];
    
    // 读入学生信息
    for (int i = 0; i < 3; i++) {
        printf("请输入第%d个学生的学号、姓名、成绩(用空格分隔):", i + 1);
        scanf("%d %s %d", &id, name, &score);
        head = insert(head, id, name, score);
    }
    
    // 输出所有学生信息
    printf("插入学生后,单向链表中所有学生信息如下:\n");
    print(head);
    
    // 删除指定学生信息
    printf("请输入要删除的学生的学号:");
    scanf("%d", &delete_id);
    head = delete(head, delete_id);
    
    // 输出所有学生信息
    printf("删除学生后,单向链表中所有学生信息如下:\n");
    print(head);
    
    return 0;
}

这个程序将会创建一个大小为3的学生成绩信息单向链表,读入每个学生的学号、姓名和成绩,将学生信息按学号由小到大顺序插入单向链表中。然后,程序将要求用户输入要删除的学生的学号,从单向链表中删除该学生信息,并输出删除后的单向链表中所有学生的信息。