实验题目: 线性表的基本操作
实验环境: Visual Studio
实验目的:
1、掌握线性表的定义;
2、掌握线性表的基本操作,如建立、查找、插入和删除等。
实验内容:
定义一个包含学生信息(学号,姓名,成绩)的顺序表和链表,使其具有如下功能:
(1) 根据指定学生个数,逐个输入学生信息;
(2) 逐个显示学生表中所有学生的相关信息;
(3) 根据姓名进行查找,返回此学生的学号和成绩;
(4) 根据指定的位置可返回相应的学生信息(学号,姓名,成绩);
(5) 给定一个学生信息,插入到表中指定的位置;
(6) 删除指定位置的学生记录;
(7) 统计表中学生个数。
实验提示:
学生信息的定义:
typedef struct {
char no[8]; //8位学号
char name[20]; //姓名
int grade; //成绩
}Student;
顺序表的定义
typedef struct {
Student *elem; //指向数据元素的基地址
int length; //线性表的当前长度
}SqList;
链表的定义:
typedef struct LNode{
Student data; //数据域
struct LNode *next; //指针域
}LNode,*linkList;
实验要求:
(1) 程序要添加适当的注释,程序的书写要采用缩进格式。
(2) 程序要具有一定的健壮性,即当输入数据非法时,程序也能适当地做出反应,如插入删除时指定的位置不对等等。
(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。
顺序表代码:
#include#include #include #define MAXSIZE 5 #define OK 1 #define ERROR 0 #define Free -1 typedef int Status; typedef int ElemType; struct Student { int id; //八位学号 char name[20];//姓名 float grade; //成绩 }; typedef struct { //创建结构体 Student* elem; int length; }SqList; //创建 Status Cj_List(SqList& L) { //数据长度为0时就是创建成功了,不允许再次创建 if (L.length >= 0) { printf("创建失败!原因:内存已被创建。an"); return ERROR; } L.elem = (Student*)malloc(MAXSIZE * sizeof(Student)); if (L.elem) { L.length = 0; //创建成功,赋值长度为0 return OK; } return ERROR; } //插入 Status Cr_List(SqList& L, int i, Student e) { if (L.length < 0) { printf("插入失败!原因:内存未被创建!an"); return ERROR; //当长度小于0就是未创建内存,不允许插入数据 } if (L.length >= MAXSIZE) { //长度大于顺序表最大值时不允许插入数据 printf("插入失败!原因:顺序表已满。an"); return ERROR; } if (i <= 0 || i > L.length + 1) { printf("插入位置不合法!an"); return ERROR; } for (int j = L.length - 1; j >= i - 1; j--) { L.elem[j + 1] = L.elem[j]; } L.elem[i - 1] = e; ++L.length; printf("插入成功!n当前顺序表长度为:%dn", L.length); return OK; } //提取 Status Tq_List(SqList L, int i) { if (i <= 0 || i > L.length) { printf("提取位置不合法!an"); return ERROR; } printf("学号:%d 姓名:%s 成绩:%.2f n", L.elem[i - 1].id, L.elem[i - 1].name, L.elem[i - 1].grade); //输出当前i位置的学生数据 return OK; } //查找 Status Cz_List(SqList L, Student p) { for (int i = 0; i < L.length; i++) { if (strcmp(L.elem[i].name, p.name) == 0)return(i + 1); } //用strcmp()对比学生姓名,相等则输出序号 return ERROR; } //删除 Status Sc_List(SqList& L, int i) { if (i <= 0 || i > L.length) { printf("删除的位置不合法!an"); return ERROR; } printf("需删除的数据为:n学号: % d 姓名 : % s 成绩 : %.2f n", L.elem[i - 1].id, L.elem[i - 1].name, L.elem[i - 1].grade); for (i; i < L.length; i++) { L.elem[i - 1] = L.elem[i]; }printf("删除成功!n当前顺序表长度为:%dn", --L.length); return OK; } //清空 void Qk_List(SqList& L) { printf("正在清空数据...........0%%n"); for (int j = L.length; j > 0; j--) { L.elem[j - 1] = L.elem[j]; //清楚表内所有数据 printf("正在清除...............%d%%n", 100 - (--L.length)); } printf("数据已清空成功!n"); printf("正在清空内存......n"); free(L.elem); //将顺序表内存释放 L.length = Free; printf("清空内存成功!n"); } //输出 Status print_List(SqList L) { if (L.length < 0) { printf("输出失败!原因:顺序表不存在。an"); return ERROR; } if (L.length == 0) { printf("输出失败!原因:该顺序表没有数据。an"); return ERROR; } else { printf("全部学生数据:n"); for (int i = 0; i < L.length; i++) { printf("学号:%d 姓名:%s 成绩:%.2f n", L.elem[i].id, L.elem[i].name, L.elem[i].grade); } return OK; } } int main() { SqList L; int i, choose = -1; Student e,p; int id; L.length=-1; while (1) { printf("*******************************n"); printf("1.创建n"); printf("2.插入n"); printf("3.查找n"); printf("4.提取n"); printf("5.删除n"); printf("6.输出n"); printf("7.清空n"); printf("8.退出n"); printf("请选择操作:"); scanf("%d", &choose); printf("n"); switch (choose) { case 1: { if (Cj_List(L))printf("分配内存成功!n"); break; } case 2: { printf("输入插入的位置、学号、姓名、成绩(空格隔开)n"); scanf("%d %d %s %f", &i, &e.id, &e.name, &e.grade); Cr_List(L, i, e); break; } case 3: { printf("输入需查找学生的姓名:"); scanf("%s", p.name,20); printf("n"); if (Cz_List(L, p)) { printf("学生所在排序位置为:%dn", Cz_List(L, p)); } else { printf("没有找到该学生!n"); } break; } case 4: { printf("输入提取的位置: "); scanf("%d", &i); printf("n"); Tq_List(L, i); break; } case 5: { printf("输入删除的位置: "); scanf("%d", &i); Sc_List(L, i); break; } case 6: { print_List(L); break; } case 7: { Qk_List(L); break; } case 8: { printf("已成功退出!n"); system("pause"); return 0; } } } return 0; }
单链表代码:
#include#include #include #define MAXSIZE 10 #define OK 1 #define ERROR 0 #define T 1 #define F -1 typedef int Status; struct Student { int id; char name[20]; float grade; }; typedef struct Dlist { Student data; struct Dlist* next; }Dlist,*Zdlist; //创建 Status Cj_List(Zdlist& L) { L = (Zdlist)malloc(sizeof(Student)); if (L) { L->next = NULL; printf("创建成功!n"); return OK; } printf("创建失败!an"); return ERROR; } //插入 Status Cr_List(Zdlist &L ,int i,Student e) { Zdlist p ,s; p = L; int j = 0; //判断是否有头结点,无头节点则创建失败。 while (p && (j < i - 1)) { p = p->next; ++j; } if (!p || j > i - 1) { printf("插入失败!an"); return ERROR; } s = (Zdlist)malloc(sizeof(Student));//插入时先新建头结点 s->next = NULL; //定义p=L用p代替L进行指针遍历,防止丢失头结点 s->data = e; s->next = p->next; p->next = s; printf("插入成功!n"); return OK; } //查找 Status Cz_List(Zdlist L, Student e) { Zdlist p ; int i = 1; p = L->next; while (p && strcmp(p->data.name, e.name) != 0) { // 比较名字字符 p = p->next; i++; } if (p) { printf("学生数据在第 %d 位n", i); return OK; } printf("未找到该学生!an"); return ERROR; } //取值 Status Qz_List(Zdlist L, int i) { //找到位置直接输出学生信息 Zdlist p = L; int j = 0; while (p && (j < i )) { p = p->next; ++j; } if (!p || (j > i )) { printf("取值位置不合理!an"); return ERROR; }printf("该学生信息为:学号:%d 姓名:%s 成绩:%.2fn", p->data.id, p->data.name, p->data.grade); return OK; } //删除 Status Sch_List(Zdlist& L, int i) { Zdlist p = L; int j = 0; while ((p->next) && (j < i - 1)) { p = p->next; ++j; } if (!(p->next) || (j > i - 1)) { printf("删除的位置不合理!an"); return ERROR; } Zdlist q = (Zdlist)malloc(sizeof(Student)); Dlist* temp = q; q = p->next; p->next = q->next; free (temp); //使指针指向删除节点的下一个节点,用free将删除节点内存释放 temp->next = NULL; printf("删除成功!n"); return OK; } //输出 Status Sc_List(Zdlist L) { Zdlist p = L; int sum=0; if (!p->next) { printf("链表为空!an"); return ERROR; } printf("全部学生数据:n"); while (p->next!=NULL) { p = p->next; sum++; //输出总人数 printf("学号:%d 姓名:%s 成绩:%.2fn学生总数量:%d个n", p->data.id, p->data.name, p->data.grade,sum); } return OK; } //清空 Status Qk_List(Zdlist& L,int open) { if (open != T) { printf("内存未被创建!an"); return ERROR; } while (L->next!=NULL) { //调用删除函数遍历清空链表所有元素及释放内存 Sch_List(L, 1); } L = NULL; printf("清楚数据完成!n内存已清空n"); return OK; } int main() { Zdlist L; Student e; int choose; int i; int open = F; //判断内存是否已经创建,防止键盘非法输入造成遍历越界报错异常 while (1) { printf("*******************************n"); printf("1.创建n"); printf("2.插入n"); printf("3.查找n"); printf("4.提取n"); printf("5.删除n"); printf("6.输出n"); printf("7.清空n"); printf("8.退出n"); printf("请选择操作:"); scanf("%d", &choose); printf("n"); switch (choose) { case 1: if (open != F) { printf("请勿重复创建!an"); break; } Cj_List(L); open = T; //open=T 已申请内存 open=F 内存未被申请 break; case 2: if (open != T) { printf("内存未被创建!an"); break; } printf("输入插入的位置、学号、姓名、成绩(空格隔开)n"); scanf("%d %d %s %f", &i, &e.id, &e.name,&e.grade); Cr_List(L, i, e); break; case 3: if (open != T) { printf("内存未被创建!an"); break; } printf("输入需查找学生的姓名:"); scanf("%s", e.name); printf("n"); Cz_List(L, e); break; case 4: if (open != T) { printf("内存未被创建!an"); break; } printf("输入提取的位置n"); scanf("%d", &i); Qz_List(L, i); break; case 5: if (open != T) { printf("内存未被创建!an"); break; } printf("输入删除的位置n"); scanf("%d", &i); Sch_List(L, i); break; case 6: if (open != T) { printf("内存未被创建!an"); break; } Sc_List(L); break; case 7: Qk_List(L,open); open = F; break; case 8: printf("已成功退出!n"); system("pause"); return 0; } } }
由于作者内存分配知识非常薄弱,可以说是没有,尤其是单链表,作者想将头指针L的内存释放掉,但是用free一直会报错,到现在还没有找到解决的办法,所以干脆先将它赋值为NULL。请各位老师指出问题,多多提建议,谢谢。



