马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
一、学习内容
1、有关次序表的利用(功能函数)
1、创建次序表
- Plist create_list(){
- Plist L = malloc(sizeof(list)); // 为顺序表分配内存空间
- if(NULL == L){
- printf("申请空间失败\n");
- return NULL; // 如果内存分配失败,返回 NULL
- }
- L->len = 0; // 初始化表的长度为0
- printf("创建成功\n");
- return L; // 返回顺序表的指针
- }
复制代码 2、次序表的判满
- int full(Plist L){
- if(L->len == MAX){ // 如果学生数量等于最大容量,返回1表示已满
- return 1;
- }
- return 0;
- }
复制代码 3、次序表的判空
- int empty(Plist L){
- if(L->len == 0){ // 如果表长为0,表示顺序表为空
- return 1;
- }
- return 0;
- }
复制代码 4、次序表增长数据
- int input_list(Plist L){
- int n;
- printf("要输入学生的个数:\n");
- scanf("%d",&n); // 输入学生数量
- for(int i=0; i<n; i++){
- printf("请输入第%d个学生信息:", i+1);
- printf("请输入学号:");
- scanf("%d",&L->data[i].id); // 输入学号
- printf("请输入姓名:");
- scanf("%s",L->data[i].name); // 输入姓名
- printf("请输入专业:");
- scanf("%s",L->data[i].major); // 输入专业
- printf("请输入年龄:");
- scanf("%d",&L->data[i].age); // 输入年龄
- L->len++; // 学生数量增加
- }
- return 0;
- }
复制代码 5、次序表的遍历
- int output_list(Plist L){
- for(int i=0; i<L->len; i++){
- // 按格式输出每个学生的信息
- printf("学号:%d\t姓名:%s\t专业:%s\t年龄:%d\n",L->data[i].id,L->data[i].name,L->data[i].major,L->data[i].age);
- }
- return 0;
- }
复制代码 6、次序表恣意位置插入数据
- int insert_stu(Plist L, int pos, student e){
- int sub = pos -1; // 转换为数组下标
- if(sub<0 || sub>L->len || L==NULL || full(L)){ // 检查插入位置合法性和顺序表是否已满
- printf("插入失败\n");
- return -1;
- }
- for(int i=L->len-1; i>=sub; i--){ // 将元素后移,给插入新学生腾出位置
- L->data[i+1] = L->data[i];
- }
- L->data[sub] = e; // 插入新学生信息
- L->len++; // 学生数量增加
- printf("插入成功\n");
- return 0;
- }
复制代码 7、 次序表恣意位置删除利用
- int delete_stu(Plist L, int pos){
- int sub = pos - 1; // 转换为数组下标
- if(sub < 0 || sub > L->len-1 || L == NULL || empty(L)){ // 检查删除位置合法性和是否为空表
- printf("删除失败\n");
- return -1;
- }
- for(int i=sub; i<L->len; i++){ // 将后面的元素前移,覆盖要删除的元素
- L->data[i] = L->data[i+1];
- }
- L->len--; // 学生数量减少
- printf("删除成功\n");
- return 0;
- }
复制代码 8、按位置修改函数
- int change_stu(Plist L, int pos, student e){
- int sub = pos - 1; // 转换为数组下标
- if(sub < 0 || sub > L->len-1 || L == NULL || empty(L)){ // 检查修改位置合法性和是否为空表
- printf("查找失败\n");
- return -1;
- }else{
- // 修改学生信息
- L->data[sub] = e;
- printf("修改成功\n");
- return 0;
- }
- }
复制代码 9、按值修改函数
- int delete_stu(Plist L, int pos){
- int sub = pos - 1; // 转换为数组下标
- if(sub < 0 || sub > L->len-1 || L == NULL || empty(L)){ // 检查删除位置合法性和是否为空表
- printf("删除失败\n");
- return -1;
- }
- for(int i=sub; i<L->len; i++){ // 将后面的元素前移,覆盖要删除的元素
- L->data[i] = L->data[i+1];
- }
- L->len--; // 学生数量减少
- printf("删除成功\n");
- return 0;
- }
复制代码 10、 按值查找返回位置
- int find_stu_all(Plist L, char key[20]){
- int i, sub = -1;
- for(i=0; i<L->len; i++){
- // 输出所有符合条件的学生信息
- if(strcmp(L->data[i].name, key) == 0){
- printf("位置:%d\t是%s\n",i+1,L->data[i].name);
- sub = i;
- }
- }
- if(sub == -1){
- return -1; // 没有找到则返回 -1
- }
- return sub + 1;
- }
复制代码 11、查找指定位置上的元素
- int find_stu(Plist L, char key[20]){
- int i, sub = -1;
- for(i=0; i<L->len; i++){
- // 找到符合条件的学生
- if(strcmp(L->data[i].name, key) == 0){
- sub = i; // 记录找到的位置
- }
- }
- if(sub == -1){
- return -1; // 没有找到则返回 -1
- }
- return sub + 1; // 返回学生在表中的位置,位置从1开始计数
- }
复制代码 12、次序表去重
- nt delete_repeat(Plist L){
- int i, j;
- for(i=0; i<L->len; i++){
- for(j=i+1; j<L->len; j++){
- // 如果发现两个学生姓名相同,则删除后者
- if(strcmp(L->data[i].name, L->data[j].name) == 0){
- delete_stu(L, j+1); // 删除重复的学生信息
- j--; // 调整索引,继续检查下一个
- }
- }
- }
- return 0;
- }
复制代码
二、作业
制作部分门生管理体系
实现的功能有:
1、输入门生信息
2、恣意位置插入一个门生
3、恣意位置删除一个门生
4、恣意位置查找一个门生
5、恣意位置修改一个门生
6、表头插入一个门生
7、表尾插入一个门生
8、表头删除一个门生
t9、表尾删除一个门生
10、去除重复的门生
11、按照姓名查找返回位置
12、查找输出全部的门生
代码解答 :
头文件:
- #ifndef LIST_H_ // 防止头文件被重复包含,定义预处理宏 LIST_H_
- #define LIST_H_
- #include <myhead.h> // 包含自定义头文件 "myhead.h"
- #define MAX 30 // 定义顺序表的最大容量为 30,表示最多可以存储 30 个学生信息
- // 定义学生信息的结构体
- typedef struct {
- int id; // 学号,用整数表示
- char name[20]; // 姓名,最多存储 20 个字符
- char major[20]; // 专业,最多存储 20 个字符
- int age; // 年龄,用整数表示
- } student; // 结构体类型 student,用于表示单个学生的信息
- // 定义顺序表的结构体
- typedef struct {
- student data[MAX]; // 存储学生信息的数组,最多包含 MAX 个 student 结构体
- int len; // 统计学生个数,表示顺序表中当前已存储的学生数量
- } list, *Plist; // 定义顺序表类型 list,并定义 Plist 为指向 list 结构体的指针类型
- // 函数声明区域
- // 创建一个顺序表并返回指向该表的指针
- Plist create_list();
- // 输入学生信息并存储到顺序表中
- int input_list(Plist);
- // 输出顺序表中的所有学生信息
- int output_list(Plist);
- // 判断顺序表是否已满(即学生数量是否达到 MAX)
- int full(Plist);
- // 在顺序表的指定位置插入一个学生信息
- int insert_stu(Plist, int, student);
- // 判断顺序表是否为空
- int empty(Plist);
- // 删除顺序表中指定位置的学生
- int delete_stu(Plist, int);
- // 查找顺序表中指定位置的学生
- int inserach_stu(Plist, int);
- // 修改顺序表中指定位置的学生信息
- int change_stu(Plist, int, student);
- // 在顺序表的表头插入一个学生
- int insert_front(Plist, student);
- // 在顺序表的表尾插入一个学生
- int insert_rear(Plist, student);
- // 删除顺序表的表头学生
- int delete_front(Plist);
- // 删除顺序表的表尾学生
- int delete_rear(Plist);
- // 删除顺序表中重复的学生信息
- int delete_repeat(Plist);
- // 根据学生姓名查找并返回其在顺序表中的位置
- int find_stu(Plist, char *);
- // 根据学生姓名查找并输出所有符合条件的学生信息
- int find_stu_all(Plist, char *);
- #endif // 结束宏定义 LIST_H_
复制代码 函数文件:
- #include "list.h"// 创建次序表,分配内存并初始化表长为0
- Plist create_list(){
- Plist L = malloc(sizeof(list)); // 为顺序表分配内存空间
- if(NULL == L){
- printf("申请空间失败\n");
- return NULL; // 如果内存分配失败,返回 NULL
- }
- L->len = 0; // 初始化表的长度为0
- printf("创建成功\n");
- return L; // 返回顺序表的指针
- }// 输入门生信息并存储到次序表中
- int input_list(Plist L){
- int n;
- printf("要输入学生的个数:\n");
- scanf("%d",&n); // 输入学生数量
- for(int i=0; i<n; i++){
- printf("请输入第%d个学生信息:", i+1);
- printf("请输入学号:");
- scanf("%d",&L->data[i].id); // 输入学号
- printf("请输入姓名:");
- scanf("%s",L->data[i].name); // 输入姓名
- printf("请输入专业:");
- scanf("%s",L->data[i].major); // 输入专业
- printf("请输入年龄:");
- scanf("%d",&L->data[i].age); // 输入年龄
- L->len++; // 学生数量增加
- }
- return 0;
- }// 输出次序表中的全部门生信息
- int output_list(Plist L){
- for(int i=0; i<L->len; i++){
- // 按格式输出每个学生的信息
- printf("学号:%d\t姓名:%s\t专业:%s\t年龄:%d\n",L->data[i].id,L->data[i].name,L->data[i].major,L->data[i].age);
- }
- return 0;
- }// 判断次序表是否已满
- int full(Plist L){
- if(L->len == MAX){ // 如果学生数量等于最大容量,返回1表示已满
- return 1;
- }
- return 0;
- }// 在次序表的指定位置插入一个门生信息
- int insert_stu(Plist L, int pos, student e){
- int sub = pos -1; // 转换为数组下标
- if(sub<0 || sub>L->len || L==NULL || full(L)){ // 检查插入位置合法性和顺序表是否已满
- printf("插入失败\n");
- return -1;
- }
- for(int i=L->len-1; i>=sub; i--){ // 将元素后移,给插入新学生腾出位置
- L->data[i+1] = L->data[i];
- }
- L->data[sub] = e; // 插入新学生信息
- L->len++; // 学生数量增加
- printf("插入成功\n");
- return 0;
- }// 判断次序表是否为空
- int empty(Plist L){
- if(L->len == 0){ // 如果表长为0,表示顺序表为空
- return 1;
- }
- return 0;
- }// 删除次序表中指定位置的门生信息
- int delete_stu(Plist L, int pos){
- int sub = pos - 1; // 转换为数组下标
- if(sub < 0 || sub > L->len-1 || L == NULL || empty(L)){ // 检查删除位置合法性和是否为空表
- printf("删除失败\n");
- return -1;
- }
- for(int i=sub; i<L->len; i++){ // 将后面的元素前移,覆盖要删除的元素
- L->data[i] = L->data[i+1];
- }
- L->len--; // 学生数量减少
- printf("删除成功\n");
- return 0;
- }// 查找次序表中指定位置的门生信息int inserach_stu(Plist L, int pos){ int sub = pos - 1; // 转换为数组下标 if(sub < 0 || sub > L->len-1 || L == NULL || empty(L)){ // 查抄查找位置正当性和是否为空表 printf("查找失败\n"); return -1; }else{ // 输出找到的门生信息 printf("该门生存在\n"); printf("学号:%d\t姓名:%s\t专业:%s\t年事:%d\n",L->data[sub].id,L->data[sub].name,L->data[sub].major,L->data[sub].age); return 0; }}// 修改次序表中指定位置的门生信息
- int change_stu(Plist L, int pos, student e){
- int sub = pos - 1; // 转换为数组下标
- if(sub < 0 || sub > L->len-1 || L == NULL || empty(L)){ // 检查修改位置合法性和是否为空表
- printf("查找失败\n");
- return -1;
- }else{
- // 修改学生信息
- L->data[sub] = e;
- printf("修改成功\n");
- return 0;
- }
- }
- // 在次序表的表头插入一个门生信息int insert_front(Plist L, student e){ if(L == NULL || full(L)){ // 查抄表是否已满或次序表为空 printf("表头插入失败\n"); return -1; } for(int i=L->len-1; i>=0; i--){ // 将全部门生信息后移 L->data[i+1] = L->data[i]; } L->data[0] = e; // 将新门生信息插入表头 L->len++; // 门生数量增长 printf("表头插入乐成\n"); return 0;}// 在次序表的表尾插入一个门生信息int insert_rear(Plist L, student e){ if(L == NULL || full(L)){ // 查抄表是否已满或次序表为空 printf("表尾插入失败\n"); return -1; } L->data[L->len] = e; // 将新门生信息插入表尾 L->len++; // 门生数量增长 printf("表尾插入乐成\n"); return 0;}// 删除次序表的表头门生信息int delete_front(Plist L){ if(L == NULL || empty(L)){ // 查抄是否为空表 printf("表头删除失败\n"); return -1; } for(int i=0; i<L->len; i++){ // 将表中的门生信息前移 L->data[i] = L->data[i+1]; } L->len--; // 门生数量镌汰 printf("表头删除乐成\n"); return 0;}// 删除次序表的表尾门生信息int delete_rear(Plist L){ if(L == NULL || empty(L)){ // 查抄是否为空表 printf("表尾删除失败\n"); return -1; } L->len--; // 表尾元素直接被忽略,相称于删除末了一个元素 printf("表尾删除乐成\n"); return 0;}// 删除次序表中重复的门生信息i
- nt delete_repeat(Plist L){
- int i, j;
- for(i=0; i<L->len; i++){
- for(j=i+1; j<L->len; j++){
- // 如果发现两个学生姓名相同,则删除后者
- if(strcmp(L->data[i].name, L->data[j].name) == 0){
- delete_stu(L, j+1); // 删除重复的学生信息
- j--; // 调整索引,继续检查下一个
- }
- }
- }
- return 0;
- }// 根据门生姓名查找并返回其在次序表中的位置
- int find_stu(Plist L, char key[20]){
- int i, sub = -1;
- for(i=0; i<L->len; i++){
- // 找到符合条件的学生
- if(strcmp(L->data[i].name, key) == 0){
- sub = i; // 记录找到的位置
- }
- }
- if(sub == -1){
- return -1; // 没有找到则返回 -1
- }
- return sub + 1; // 返回学生在表中的位置,位置从1开始计数
- }// 根据门生姓名查找并输出全部符合条件的门生信息
- int find_stu_all(Plist L, char key[20]){
- int i, sub = -1;
- for(i=0; i<L->len; i++){
- // 输出所有符合条件的学生信息
- if(strcmp(L->data[i].name, key) == 0){
- printf("位置:%d\t是%s\n",i+1,L->data[i].name);
- sub = i;
- }
- }
- if(sub == -1){
- return -1; // 没有找到则返回 -1
- }
- return sub + 1;
- }
复制代码 主函数文件:
- #include <myhead.h>
- #include "list.h"
- int main(int argc, const char *argv[])
- {
- // 创建一个顺序表,并将其地址存储在指针 L 中
- Plist L = create_list();
- int ch; // 用于存储用户的选择
- student e; // 用于插入或修改的学生信息
- int pos; // 用于指定操作的位置
- char name[20]; // 用于存储查找时输入的学生姓名
- // 无限循环,直到用户选择退出(或通过外部手段中断)
- while(1) {
- // 提示用户选择要执行的操作
- printf("\t\t1、输入学生信息\n");
- printf("\t\t2、任意位置插入一个学生\n");
- printf("\t\t3、任意位置删除一个学生\n");
- printf("\t\t4、任意位置查找一个学生\n");
- printf("\t\t5、任意位置修改一个学生\n");
- printf("\t\t6、表头插入一个学生\n");
- printf("\t\t7、表尾插入一个学生\n");
- printf("\t\t8、表头删除一个学生\n");
- printf("\t\t9、表尾删除一个学生\n");
- printf("\t\t10、去除重复的学生\n");
- printf("\t\t11、按照姓名查找返回位置\n");
- printf("\t\t12、查找输出所有的学生\n");
- printf("\t\t请输入你的选择:\n");
- // 读取用户输入的选择
- scanf("%d", &ch);
- // 根据用户的选择执行相应的操作
- switch(ch) {
- case 1:
- // 输入学生信息并输出整个学生列表
- input_list(L);
- output_list(L);
- break;
- case 2:
- // 在指定位置插入一个学生
- printf("请输入要插入的学生位置:\n");
- scanf("%d", &pos); // 读取要插入的学生位置
- printf("请输入学生ID、姓名、专业、年龄:\n");
- scanf("%d %s %s %d", &e.id, e.name, e.major, &e.age); // 读取学生信息
- insert_stu(L, pos, e); // 在指定位置插入学生
- output_list(L); // 输出更新后的学生列表
- break;
- case 3:
- // 在指定位置删除一个学生
- printf("请输入要删除的学生位置:\n");
- scanf("%d", &pos); // 读取要删除的学生位置
- delete_stu(L, pos); // 删除指定位置的学生
- output_list(L); // 输出更新后的学生列表
- break;
- case 4:
- // 在指定位置查找一个学生
- printf("请输入要查找的学生位置:\n");
- scanf("%d", &pos); // 读取要查找的学生位置
- inserach_stu(L, pos); // 查找并输出指定位置的学生信息
- break;
- case 5:
- // 修改指定位置的学生信息
- printf("请输入要修改的学生位置:\n");
- scanf("%d", &pos); // 读取要修改的学生位置
- printf("请输入新的学生ID、姓名、专业、年龄:\n");
- scanf("%d %s %s %d", &e.id, e.name, e.major, &e.age); // 读取新的学生信息
- change_stu(L, pos, e); // 修改指定位置的学生信息
- output_list(L); // 输出更新后的学生列表
- break;
- case 6:
- // 在表头插入一个学生
- printf("请输入学生ID、姓名、专业、年龄:\n");
- scanf("%d %s %s %d", &e.id, e.name, e.major, &e.age); // 读取学生信息
- insert_front(L, e); // 将学生插入表头
- output_list(L); // 输出更新后的学生列表
- break;
- case 7:
- // 在表尾插入一个学生
- printf("请输入学生ID、姓名、专业、年龄:\n");
- scanf("%d %s %s %d", &e.id, e.name, e.major, &e.age); // 读取学生信息
- insert_rear(L, e); // 将学生插入表尾
- output_list(L); // 输出更新后的学生列表
- break;
- case 8:
- // 删除表头的学生
- delete_front(L); // 删除表头学生
- output_list(L); // 输出更新后的学生列表
- break;
- case 9:
- // 删除表尾的学生
- delete_rear(L); // 删除表尾学生
- output_list(L); // 输出更新后的学生列表
- break;
- case 10:
- // 删除重复的学生
- delete_repeat(L); // 删除学生列表中重复的学生
- output_list(L); // 输出更新后的学生列表
- break;
- case 11:
- // 按照姓名查找学生,并返回位置
- printf("请输入要查找的学生姓名:\n");
- scanf("%s", name); // 读取要查找的学生姓名
- pos = find_stu(L, name); // 查找学生
- if(pos == -1) { // 如果找不到学生
- printf("查找失败\n");
- } else { // 如果找到学生
- printf("查找成功,该学生位于第%d个位置\n", pos);
- }
- break;
- case 12:
- // 查找并输出所有匹配的学生
- printf("请输入要查找的学生姓名:\n");
- scanf("%s", name); // 读取要查找的学生姓名
- find_stu_all(L, name); // 查找并输出所有符合条件的学生
- break;
- default:
- // 输入无效的选择时提示用户重新输入
- printf("无效的选择,请重新输入。\n");
- break;
- }
- }
- return 0;
- }
复制代码 结果显现:
三、总结
学习内容概述
编写了一个基于次序表管理门生信息的项目。项目包罗以下功能:创建次序表、查抄次序表是否满或空、增长门生信息、遍历次序表、在恣意位置插入或删除门生、按位置或按值修改门生信息、按值查找门生、删除重复门生信息。代码实现了次序表的根本利用,接纳数组存储门生数据。
学习难点
1. 次序表利用边界查抄:
在插入和删除利用时,必须查抄位置是否正当以及次序表是否为空或已满。这些边界查抄确保次序表利用的稳固性。
2. 内存管理:
创建次序表时须要动态分配内存,内存分配失败时要准确处理处罚。
3. 删除和插入利用中的数据移动:
插入数据时须要将插入位置后的全部元素后移;删除数据时,须要将被删除位置后的元素前移。
4. 去重功能的实现:
通过两层嵌套循环比力门生姓名来删除重复信息,且删除时须要调解索引。
紧张事项
1. 数组长度温次序表长度的关系:
次序表长度不能凌驾数组长度。每次增长或删除门生信息后,都须要更新次序表长度。
2. 位置和下标的转换:
在对次序表举行插入、删除和查找利用时,用户输入的位置要转换为数组下标(即位置-1)。
3. 动态内存分配:
须要确保动态分配内存乐成,否则大概会导致步调瓦解或出现未界说举动。
4. 字符串利用:
在查找和去重利用中,使用`strcmp`函数比力门生姓名,须要确保字符串的准确输入和处理处罚。
将来学习的重点
1. 非常处理处罚:
可以增长更多的非常处理处罚逻辑,确保次序表利用的结实性。比方,在利用过程中假如次序表出现错误,实时提示并处理处罚。
2. 内存管理:
深入学习动态内存分配与开释,制止内存走漏的题目。
3. 优化查找和去重算法:
现在的查找和去重利用时间复杂度较高,可以思量优化查找算法,如引入二分查找或哈希查找。
4. 扩展次序表功能:
进一步扩展次序表功能,如添加排序功能、批量删除或插入等利用,提升次序表的实用性。
|