首页 > 其他分享 >带头结点单链表插入,删除,查找与排序实现一个简单的基于链表结构的学生管理系统

带头结点单链表插入,删除,查找与排序实现一个简单的基于链表结构的学生管理系统

时间:2023-06-29 17:33:49浏览次数:63  
标签:结点 单链 void list param 链表 link student data

链表结构和操作方法

//
// Created by Administrator on 2023/6/12.
//

#ifndef CODE_LINKEDLIST_H
#define CODE_LINKEDLIST_H

#include <iostream>
#include <cstring>
#include <stdlib.h>
#include "student.h"


typedef struct link_list {
    // 方便存放任意类型的数据
    void *data;
    struct link_list *next;
} link_list;

/**
 * 链表初始化
 * @return
 */
link_list *init_link_list();
/**
 * 链表尾部添加
 * @param head
 * @param data
 */
void push(link_list *head, void *data);

/**
 * 遍历链表
 * @param head
 * @param call_back
 */
void link_list_each(link_list *head, void (*call_back)(void *));

/**
 * 查找数据返回数据链表
 * @param head 需要查找的链表
 * @param find_list 返回最后一个找到的节点
 * @param call_back 根据传入的回调函数查找对应的数据
 * @param parameter 查找的数据
 * @return
 */
link_list *find(link_list *head, link_list *find_list, int (*call_back)(void *, void *), void *parameter);

/**
 * 删除结点
 * @param head
 * @param call_back
 * @param parameter
 */
int deleted(link_list *head, int (*call_back)(void *, void *), void *parameter);

/**
 * 冒泡排序
 * @param head
 * @param call_back 回调函数需要返回排序的内容
 */
void sort(link_list *head, char *(*call_back)(void *));


/**
 * 链表初始化
 * @return
 */
link_list *init_link_list() {
    link_list *head;
    head = (link_list *) malloc(sizeof(link_list));
    head->next = NULL;
    head->data = NULL;
    return head;
}

/**
 * 链表尾部添加
 * @param head
 * @param data
 */
void push(link_list *head, void *data) {
    link_list *p = head;
    while (p->next) {
        p = p->next;
    }
    link_list *q = init_link_list();
    q->data = data;
    q->next = NULL;
    p->next = q;
}

/**
 * 遍历链表
 * @param head 链表
 */
void link_list_each(link_list *head, void (*call_back)(void *)) {
    if (!head) return;
    link_list *node = head;
    while (node) {
        if (node->data)
            call_back(node->data);
        node = node->next;
    }
}


/**
 * 查找数据返回数据链表
 * @param head 需要查找的链表
 * @param find_list 返回最后一个找到的节点
 * @param call_back 根据传入的回调函数查找对应的数据
 * @param parameter 查找的数据
 * @return
 */
link_list *find(link_list *head, link_list *find_list, int (*call_back)(void *, void *), void *parameter) {
    link_list *p = head->next;
    link_list *find_data = init_link_list();
    static int i = 0;
    while (p) {
        if (call_back(p->data, parameter)) {
            // 支持返回多个相同的数据
            push(find_data, p->data);
            if (find_list)
            find_list->next = p;
        }
        p = p->next;
    }
    i = 0;
    if (find_data->next)
        return find_data;
    else return NULL;
}


/**
 * 删除结点
 * @param head
 * @param call_back
 * @param parameter
 */
int deleted(link_list *head, int (*call_back)(void *, void *), void *parameter) {
    link_list *p = head;
    link_list *q = p;
    while (p) {
        if (p->data && call_back(p->data, parameter)) {
            q->next = p->next;
            free(p);
            return 1;
        }
        q = p;
        p = p->next;
    }
    return -1;
}

/**
 * 冒泡排序
 * @param head
 * @param call_back 回调函数需要返回排序的内容
 */
void sort(link_list *head, char *(*call_back)(void *)) {
    link_list *node = head->next;
    link_list *node_next;
    void *temp;
    while (node) {
        for (node_next = node->next; node_next; node_next = node_next->next) {
            if (strcmp(call_back(node->data), call_back(node_next->data)) == 1) {
                temp = node_next->data;
                node_next->data = node->data;
                node->data = temp;
            }
        }
        node = node->next;
    }
}


#endif //CODE_LINKEDLIST_H

学生数据结构和操作方法

//
// Created by Administrator on 2023/6/12.
//

#ifndef CODE_STUDENT_H
#define CODE_STUDENT_H

#include <string>
#include <cstring>
#include <conio.h>
#include "linked_list.h"

using namespace std;

typedef struct student {
    char sno[10];
    char name[20];
    char gender[3];
    // 2023-06-12
    char birthday[11];
    char addr[50];
    char phone[12];
    char email[30];
    // 成绩
    void *course;
} student;

/**
 * 初始化
 * @return
 */
student *init_student();

/**
 * 根据学号对比学生
 * @param data
 * @param parameter
 * @return
 */
int get_student_by_sno(void *data, void *parameter);

/**
 * 根据姓名对比学生
 * @param data
 * @param parameter
 * @return
 */
int get_student_by_name(void *data, void *parameter);

/**
 * 根据姓名或者学号对比
 * @param data
 * @param parameter
 * @return
 */
int get_student_by_sno_or_name(void *data, void *parameter);

/**
 * 打印学生信息
 * @param data
 */
void display_student(void *data);

/**
 * 添加学生信息
 * @return
 */
student *add_student();

/**
 * 更新录入
 * @param sno
 * @return
 */
student *update_student(char *sno);

/**
 * 快速添加学生消息
 * @return
 */
student *add_student_fast();

/**
 * 根据接收的数据返回学号sno
 * @param data
 * @return
 */
char *get_student_sno(void *data);



///////////////////////////////////////////////

/**
 * 初始化
 * @return
 */
student *init_student() {
    return (student *) malloc(sizeof(student));
}

/**
 * 根据学号对比学生
 * @param data
 * @param parameter
 * @return
 */
int get_student_by_sno(void *data, void *parameter) {
    student *stu = (student *) data;
    if (!strcmp(stu->sno, (char *) parameter)) {
//        cout << "查询" << "学号:" << stu->sno << "\t" << "查询参数:" << (char *) parameter << "\t" << "对比结果" << !strcmp(stu->sno, (char *) parameter) << endl;
        return 1;
    }
    return 0;
}

/**
 * 根据姓名对比学生
 * @param data
 * @param parameter
 * @return
 */
int get_student_by_name(void *data, void *parameter) {
    student *stu = (student *) data;
    if (!strcmp(stu->name, (char *) parameter)) {
        return 1;
    }
    return 0;
}

/**
 * 根据姓名或者学号对比 支持模糊查找
 * @param data
 * @param parameter
 * @return
 */
int get_student_by_sno_or_name(void *data, void *parameter) {
    student *stu = (student *) data;
//    cout << stu->sno << ":" << (char *)parameter <<  ":" << !(strcmp(stu->sno, (char *) parameter) || !strcmp(stu->name, (char *)parameter)) << endl ;
    if (strstr(stu->sno, (char *) parameter) || strstr(stu->name, (char *)parameter)) {
        return 1;
    }
    return 0;
}



/**
 * 打印学生信息
 * @param data
 */
void display_student(void *data) {
    student *stu = (student *) data;
    cout << "----------------------------------------------------------------------------------------------------------"
            "-------------------------------------------------" << endl;
    cout << setiosflags(ios::left)
         << "|学号:" << setw(10) << stu->sno
         << "|姓名:" << setw(10) << stu->name
         << "|性别:" << setw(3) << stu->gender
         << "|邮箱:" << setw(20) << stu->email
         << "|电话号码:" << setw(15) << stu->phone
         << "|生日:" << setw(15) << stu->birthday
         << "|地址:" << setw(32) << stu->addr << "|"
         << endl;
    cout << "----------------------------------------------------------------------------------------------------------"
            "-------------------------------------------------" << endl;
    return;
}

/**
 * 添加学生信息
 * @return
 */
student *add_student() {
    student *stu = init_student();
    cout << endl << "请输入学号:";
    cin >> stu->sno;
    cout << endl << "请输入姓名:";
    cin >> stu->name;
    cout << endl << "请输入性别:";
    cin >> stu->gender;
    cout << endl << "请输入邮箱:";
    cin >> stu->email;
    cout << endl << "请输入手机号:";
    cin >> stu->phone;
    cout << endl << "请输入生日:";
    cin >> stu->birthday;
    cout << endl << "请输入地址:";
    cin >> stu->addr;
    return stu;
}

/**
 * 更新录入
 * @param sno
 * @return
 */
student *update_student(char *sno) {
    student *stu = init_student();
    strcpy(stu->sno, sno);
    cout << endl << "请输入姓名:";
    cin >> stu->name;
    cout << endl << "请输入性别:";
    cin >> stu->gender;
    cout << endl << "请输入邮箱:";
    cin >> stu->email;
    cout << endl << "请输入手机号:";
    cin >> stu->phone;
    cout << endl << "请输入生日:";
    cin >> stu->birthday;
    cout << endl << "请输入地址:";
    cin >> stu->addr;
    return stu;
}

/**
 * 快速添加学生消息
 * @return
 */
student *add_student_fast() {
    student *stu = init_student();
    cin >> stu->sno;
    cin >> stu->name;
    cin >> stu->gender;
    cin >> stu->email;
    cin >> stu->phone;
    cin >> stu->birthday;
    cin >> stu->addr;
    return stu;
}

/**
 * 根据接收的数据返回学号sno
 * @param data
 * @return
 */
char *get_student_sno(void *data) {
    student *stu = (student *)data;
    return stu->sno;
}

/**
 * 获取出生日期
 * @param data
 * @return
 */
char *get_student_birthday(void *data) {
    student *stu = (student *)data;
    return stu->birthday;
}

/**
 * 输入密码
 * @return
 */
char *input_password() {
    char *password = (char *)malloc(sizeof(char)*10); //存储密码
    int i = 0; //记录密码长度
    char c; //用于实现密码隐式输入
    while (1) {
        c = getch(); //用 _getch() 函数输入,字符不会显示在屏幕上
        if (c == '\r') { //遇到回车,表明密码输入结束
            break; //while 循环的出口
        }
        else if (c == '\b') { //遇到退格,需要删除前一个星号
            printf("\b \b");  //退格,打一个空格,再退格,实质上是用空格覆盖掉星号
            --i;
        }
        else {
            password[i++] = c;//将字符放入数组
            printf("*");
        }
    }
    password[i] = '\0';
    return password;
}


#endif //CODE_STUDENT_H

应用

//
// Created by Administrator on 2023/6/12.
//

#ifndef STUDENTMANNAGESYSTEM_MENU_H
#define STUDENTMANNAGESYSTEM_MENU_H

#include <iostream>
#include "student.h"
#include "file_util.h"

using namespace std;

void menu(link_list *list) {
    cout << "=========================学生管理系统=======================" << endl;
    cout << "\t\t\t 1.添加学生消息" << endl;
    cout << "\t\t\t 2.删除学生信息" << endl;
    cout << "\t\t\t 3.修改学生信息" << endl;
    cout << "\t\t\t 4.查询学生信息" << endl;
    cout << "\t\t\t 5.查询所有学生信息" << endl;
    cout << "\t\t\t 6.快速录入学生信息" << endl;
    cout << "\t\t\t 7.清空文件" << endl;
    cout << "\t\t\t 8.学生排序" << endl;
    cout << "\t\t\t 9.存档" << endl;
    cout << "\t\t\t 0.退出系统" << endl;
    cout << "===========================================================" << endl;
    int input;
    cin >> input;
    system("cls");
    char temp_input[50];
    link_list *link;
    switch (input) {
        case 1:
        	student *add;
			add = add_student(); 
        	{
                link = find(list, NULL, get_student_by_sno, (char *) add->sno);
                if (link) {
                	cout << "已存在该用户" << endl; 
                    cout << "该学生的信息如下:" << endl;
                    link_list_each(link, display_student);
                } else {
                    push(list, add);
                    break;
                }
            }
            
            break;
        case 2:
            cout << "请输入要删除学生的学号0R姓名:";
            cin >> temp_input;
            {
                link = find(list, NULL, get_student_by_sno_or_name, (char *) temp_input);
                if (link) {
                    cout << "该学生的信息如下:" << endl;
                    link_list_each(link, display_student);
                } else {
                    cout << endl << "======================找不到此人==================" << endl;
                    break;
                }
            }
            cout << "确认需要删除学生的学号:";
            cin >> temp_input;
            int d;
            d = deleted(list, get_student_by_sno, (void *) temp_input);
            if (d == 1) {
                cout << endl << "======================删除成功==================" << endl;
            } else {
                cout << endl << "======================找不到此人==================" << endl;
            }
            break;
        case 3:
            cout << "请输入要修改学生的学号OR姓名:";
            cin >> temp_input;
            {
                link = find(list, NULL, get_student_by_sno_or_name, (char *) temp_input);
                if (link) {
                    cout << "该学生的信息如下:" << endl;
                    link_list_each(link, display_student);
                } else {
                    cout << endl << "======================找不到此人==================" << endl;
                    break;
                }
            }
            cout << "确认需要修改的学号:";
            link_list *find_node;
            cin >> temp_input;
            find_node = init_link_list();

            link = find(list, find_node, get_student_by_sno, (char *) temp_input);
            // 指针深拷贝
//            memcpy(find_node, list, sizeof(link_list));
            link_list_each(link, display_student);

            if (find_node->next) {
                // 更新数据
                find_node->next->data = update_student(temp_input);
            } else {
                cout << endl << "======================找不到此人==================" << endl;
            }
            break;
        case 4:
            cout << "请输入要查询学生的学号OR姓名:";
            cin >> temp_input;
            link = find(list, NULL, get_student_by_sno_or_name, (char *) temp_input);
            if (link) {
                cout << "该学生的信息如下:" << endl;
                link_list_each(link, display_student);
            } else {
                cout << endl << "======================找不到此人==================" << endl;
            }
            break;
        case 5:
            system("cls");
            cout << "||===============================================================学生表==================================="
                    "===============================================||" << endl;
            link_list_each(list, display_student);
            break;
        case 6:
        	cout << "请输入:";
        	student *fast_add;
			add = add_student_fast(); 
        	{
                link = find(list, NULL, get_student_by_sno, (char *) add->sno);
                if (link) {
                	cout << "已存在该用户" << endl; 
                    cout << "该学生的信息如下:" << endl;
                    link_list_each(link, display_student);
                } else {
                    push(list, add);
                    break;
                }
            }
            break;
        case 7:
            cout << "这是一个危险操作请输入密码:\a\a\a";
            char *password;
            password = input_password();
            cout << endl;
            if (!strcmp(password, "password")) {
                clear_file();
                list->next = NULL;
            } else {
                cout << endl << "密码不正确!" << endl;
            }
            break;
        case 8:
            cout << "===========排序============" << endl;
            cout << "\t" << "1.学号排序" << endl;
            cout << "\t" << "2.年龄排序" << endl;
            cout << "==========================" << endl;
            int sort_in;
            cin >> sort_in;
            if (sort_in == 1) {
                sort(list, get_student_sno);
            } else if (sort_in == 2) {
                sort(list, get_student_birthday);
            }
            cout << "排序完成" << endl;
            link_list_each(list, display_student);
            break;
        case 9:
            ::system("cls");
            cout << endl << "=========================保存中。。。。。。。。。。";
            file_write(list);
            cout << endl << "======================保存成功==================" << endl;
            break;
        case 0:
            cout << "确认退出系统吗?没有存档会丢失数据哦!(y/n)" << endl;
            char in;
            cin >> in;
            if (in == 'y' || in == 'Y') {
                cout << "ヾ( ̄▽ ̄)Bye~Bye~";
                system("pause");
                exit(0);
            }
            break;
        default:
            cout << "非法操作请重试!" << endl;
    }
}

#endif //STUDENTMANNAGESYSTEM_MENU_H

标签:结点,单链,void,list,param,链表,link,student,data
From: https://www.cnblogs.com/oceanus/p/17514752.html

相关文章

  • JavaScript 链表的增删改查
       //节点对象classNode{constructor(data){this.data=data;//存储节点数据this.next=null;//存储下一个节点的引用,默认为null}}//链表对象classLinkedList{constructor(){this.head=null;//链表头节点,默认为null}......
  • 143. 重排链表
    给定一个单链表L的头节点head,单链表L表示为:L0→L1→…→Ln-1→Ln请将其重新排列后变为:L0→Ln→L1→Ln-1→L2→Ln-2→…不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。示例1:输入:head=[1,2,3,4]输出:[1,4,2,3]>代码1(前......
  • Shuffle Cards (牛客多校) (rope 块状链表 用作可持续优化平衡树, 用于区间的整体移动
    rope:#include<ext/rope>usingnamespace__gnu_cxx; 定义方法:rope<变量类型>变量名称;人话解释:超级string算法解释:块状链表(即讲链表与数组的优势结合,形成分块思想)用途解释:这本来是一个用于快速操作string的工具,却一般被定义成int,然后用作可持久化线段树!insert(intpos,s......
  • #yyds干货盘点# LeetCode程序员面试金典:重排链表
    题目:给定一个单链表L的头节点head,单链表L表示为:L0→L1→…→Ln-1→Ln请将其重新排列后变为:L0→Ln→L1→Ln-1→L2→Ln-2→…不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。 示例1:输入:head=[1,2,3,4]输出:[1,4,2,3]示例2:输入:head......
  • leetcode 21. 合并两个有序链表
    直接合并即可这道题是简单题,直接合并即可/**Definitionforsingly-linkedlist.publicclassListNode{intval;ListNodenext;ListNode(){}ListNode(intval){this.val=val;}ListNode(intval,ListNodenext){this.val=val;this.next=nex......
  • 【华为机试ACM基础#02】从单向链表中删除指定值的节点(熟悉链表的输入方式,虽然说本题可
    从单向链表中删除指定值的节点输入一个单向链表和一个节点的值,从单向链表中删除等于该值的节点,删除后如果链表中无节点则返回空指针。链表的值不能重复。构造过程,例如输入一行数据为:6212325145722则第一个参数6表示输入总共6个节点,第二个参数2表示头节点值为2,剩......
  • 用指针处理链表
    什么是链表?链表是一种常见的重要的数据结构。它是动态的进行春初分配的一种结构。用数组存放数据时,必须先定义固定的数组长度,显然这会浪费内存。链表则没有这个缺点,他根据需要开辟内存单元。 ......
  • [leetcode]114. 二叉树展开为链表
    总结:怎样写递归函数?关键是把递归函数的功能定义清楚,并在递归函数体中使用自身来做事,此时不要关注递归函数执行的细节。也就是写高层级代码的时候不要关注低层级的事情,这就叫抽象。关注也没有用,想不清楚的。 1classSolution{2publicvoidflatten(TreeNoderoot){......
  • #yyds干货盘点# LeetCode程序员面试金典:复制带随机指针的链表
    题目:给你一个长度为n的链表,每个节点包含一个额外增加的随机指针random,该指针可以指向链表中的任何节点或空节点。构造这个链表的 深拷贝。 深拷贝应该正好由n个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的next指针和random指针也都应指向复制......
  • 【代码设计】链表结构解决多流程校验
    目的使用合理的代码设计,解决业务场景的中的实际问题。背景介绍在实际的业务场景中,用户的一个操作行为,是否允许真正被执行,往往会涉及到多流程的校验,一旦有条件不满足将会被中止。以下面流程图为例:用户点击了打赏按钮,会进行是否有网络检查,没有网络,会有网络连接弹框,等待用户连接结果......