目录
以一个学生管理系统为例来学习顺序表————
题目如下:
1.顺序表理论知识
-顺序表开辟的是一片连续的内存空间,如同数组
-暂时想不起来其他的了
2.顺序表的定义
-定义是一切的基础,定义不分配内存空间,只有在表建立时分配,这点与类异曲同工
-定义使用结构体
-定义使用函数
1.typedef(重定义函数)
2.struct(结构体关键字)
分析题目可知,学生信息包括学号,姓名,成绩,成绩此处仅仅使用语数外为例子;
代码如下:
typedef struct grades
{
//只保存分数
float YW;
float SX;
float YY;
}GRA;
//结构体成绩
typedef struct student
{
//姓名
char name[20];
//学号
char num[15];
//成绩,此处只取语数外
GRA gra;
}STU;
//学生信息结构体,包含结构体成绩
//定义顺序表------
typedef struct I
{
STU* data;//顺序表数据指针,数据元素
int lenght;//顺序表当前长度
int Maxsize;//顺序表最大长度
}Sqlist;
定义完成——————————————————————
3.顺序表建立(初始化)
-注:个人在这方面还有一些疑问
-由定义可知,顺序表的初始化分为三部分
1.为data开辟一个存放数据的内存空间
2.为lenght赋值,使他等于当前顺序表长度
3.为Maxsize赋值,使他大于lenght(实际上就是此处不懂,这个数值限制最大长度,但lenght大于它也不会报错,不理解设置这个值的意义是什么,希望大佬能够解释。)
-由以上列出条件,可以知道需要使用的关键字为:
1.malloc
2.赋值的就不说了,等于号
-由题可知,学生个数需要由用户指定,学生总数即为表长,正式开始初始化
-要建立一个顺序表,首先需要在main函数中为其创造对象
main函数如下:
Sqlist I;
Sqlist* p = &I;//定义一个顺序表指针,保存顺序表I的地址,方便传入,此处使用引用更加快捷
//目的是让初始化的顺序表和定义的顺序表使用同一片内存空间
//尝试一下指针
创建函数如下:
int stu(Sqlist *p)
{
std::cout << "此次使用c++完成" << endl;
std::cout << "请指定学生位数:" << endl;
int n;
std::cin >> n;
p->data = (STU*)malloc(n * sizeof(STU));//开辟的内存空间,将数组首地址返回给data顺序表中的data
p->lenght = n;
p->Maxsize = MAX;
if (n > p->Maxsize)
{
p->Maxsize = n;
}
return n;//n就是表长,相当于p->lenght
}
到这里,我们需要的表已经创建完成,下面开始对表进行操作——————————
4.顺序表的输入和输出
-顺序表的输入和输出与结构体的输入和输出几乎没有区别,在c++更是如此
-使用引用,我在建表时使用的指针,但因为c++提供的更为简便的引用,不用白不用,谁还在固守c?
-数据的输入几乎没什么好讲的,这里讲一下自己遇到的小问题
-看题:
根据指定学生个数,逐个输入学生信息;
逐个显示学生表中所有学生的相关信息;
直接上代码:
//接下来是数据输入
void input(Sqlist &I,int gs)//gs是学生个数,即表长,前文中返回的n就是这
{
STU* p = I.data;//大家可能会好奇这是什么东西,实际上这是问题之一的解决办法
//请看问题1
for (int n = 0; n < gs; n++)
{
std::cout << "请输入学生姓名:" << endl;
cin >>(p+n)->name;
// getchar();这一列我本来是用来吃\n字符的,但cin好像没有这个问题
//再次诋毁c
std::cout << "请输入学生学号:" << endl;
cin >> (p+n)->num;
// getchar();
std::cout << "请输入成绩:\n语文:" << endl;
cin >> (p+n)->gra.YW;
//getchar();
cout << "数学:" << endl;
cin >> (p + n)->gra.SX;
//getchar();
cout << "英语:" << endl;
cin >> (p + n)->gra.YY;
// getchar();
}
//输入完成,输出
system("cls");
for (int i = 0; i < gs; i++)
{
printf("这是第%d位学生:\n", i);
printf("姓名:%s 学号:%s 语文:%.2f 数学:%.2f 英语:%.2f", (p+i)->name, (p+i)->num, (p+i)->gra.YW, (p+i)->gra.SX, (p+i)->gra.YY);
printf("\n");
}
}
//输入函数完成--------------------------
问题1:
-由代码可知,顺序表名字为I
在为顺序表赋值时,我遇到了无法为第二个元素赋值的情况——
例如要为第一个元素赋值,很简单,直接使用如下代码
cout<<"语文:"<<endl;
cin>>I.data.gar.YW;
如果是第二个元素呢?
cout<<"语文:"<<endl;
cin>>I.(data+1).gar.YW;
毫无疑问报错!!!
所以我使用了 :
STU* p = I.data;
cin>>(p+1)->gra.YW;
解决.
或许也可以用这个。
(I.data+1)->gra.YW;
到这里数据的输入和输出已经完成了,数据已经录入——————————
5.顺序表查找
-看题:
-1.根据姓名进行查找,返回此学生的学号和成绩;
-2. 根据指定的位置可返回相应的学生信息(学号,姓名,成绩);
-查找并不难,使用循环与顺序表中的数据项逐一判断,当相同时,输出即可
-只需要利用循环
第一题按名字查找代码:
void find(Sqlist& I, int gs)//由此可知,返回n很有必要,虽说也可以调用I.lenght
{
STU* p = I.data;
string name;
cout << "请输入你要查找的学生姓名:" << endl;
cin >> name;
int t = 0;
//t用来记录是否输出学生信息,如果没有输出,那么输出错误信息
for (int i = 0; i < gs; i++)
{
if (name == (p + i)->name)
{
cout << "你查找的学生姓名为:" << name << endl;
printf("姓名:%s 学号:%s 语文:%.2f 数学:%.2f 英语:%.2f\n", (p + i)->name, (p + i)->num, (p + i)->gra.YW, (p + i)->gra.SX, (p + i)->gra.YY);
t = 1;
}
}
if (t == 0)
{
cout << "找不到数据" << endl;
}
}
第二题更简单,不做讲解,直接看代码:
int find2(Sqlist& I, int gs)
{
STU* p = I.data;
int n = 0;
cout << "请输入你要查找的序号:" << endl;
cin >> n;
if (n > I.lenght)
{
cout << "你输入的数据不合法!请重新输入。" << endl;
return 0;
}
for (int i = 0; i < gs; i++)
{
if (i == n)
{
printf("姓名:%s 学号:%s 语文:%.2f 数学:%.2f 英语:%.2f", (p + i)->name, (p + i)->num, (p + i)->gra.YW, (p + i)->gra.SX, (p + i)->gra.YY);
}
}
}
6.顺序表插入
-像这种内存空间是连续的,插入基本都是一个思路
即:从插入点开始,后面的数据向后推移,前面的数据不变
如果你在第n位插入数据,那么第n位的数据要移到第n+1位,n+1移到n+2;
一般是倒着移,即从末尾开始移动,否则会造成数据丢失
-看题: 给定一个学生信息,插入到表中指定的位置;
-算法设计
1.由于我们在创建顺序表时,并没有为其开辟多余的内存空间,所以当我们要插入新的数据时,原本的内存空间是不够的,需要对其进行扩容
2.扩容后得到新的内存空间,进行插入操作
3.首先使用循环,循环第一条语句进行判断,如果循环值与插入序列值相等,跳过插入值所在的序列,我将这一行为称为留白,在留白后继续将原有的数据复制到新的内存空间
4.销毁原本的内存空间,将新空间地址赋值给顺序表数据指针
代码如下:
//插入函数————————
int insert(Sqlist &I,int gs)
{
STU stu1;
int n = 0;
int temp;
//合法判断
cout << "请选择你要插入的位置:" << endl;
cin >> n;
n = n - 1;
for (int tt = 0;; tt++)
{
if (n > I.lenght)
{
cout << "你要插入的位置不合法!请重新选择。" << endl;
cin >> n;
n = n - 1;
}
else
{
break;
}
}
//录入输入信息
STU* p2 = I.data;
cout << "请输入你要插入的数据:" << endl;
cout << "姓名:" << endl;
cin >> stu1.name;
cout << "学号:" << endl;
cin >> stu1.num;
cout << "语文:" << endl;
cin >> stu1.gra.YW;
cout << "数学:" << endl;
cin >> stu1.gra.SX;
cout << "英语:" << endl;
cin >> stu1.gra.YY;
//信息录入完成,现在开始扩顺序表及内存空间
I.lenght = I.lenght + 1;//容量扩大
STU* p = (STU*)malloc( I.lenght* sizeof(STU));//开辟新的内存空间并加一
//算法描述
//1.把原来的数据复制到新的内存空间
//2.在复制时进行判断,将插入点留白
//3.顺势插入
//---------------------------------------------
//现在开始执行,现在有两片内存空间,I.data和p,p是新的内存空间
int i2 = 0;
for (int i = 0; i < I.lenght; i++, i2++)
{
//首先进行判断
if (i == n)
{
strcpy_s((p + n)->name, stu1.name);
strcpy_s((p + n)->num, stu1.num);
(p + n)->gra.SX = stu1.gra.SX;
(p + n)->gra.YW = stu1.gra.YW;
(p + n)->gra.YY = stu1.gra.YY;
i++;
}
//开始复制
strcpy_s((p + i)->name, (p2 + i2)->name);
strcpy_s((p + i)->num, (p2 + i2)->num);
(p + i)->gra.SX = (p2 + i2)->gra.SX;
(p + i)->gra.YW = (p2 + i2)->gra.YW;
(p + i)->gra.YY = (p2 + i2)->gra.YY;
//复制完成
}
//到上面时,已经进行了留白,现在插入即可
//插入完成,所有数据用指针p调用
free(I.data);
I.data = p;
cout << "你最终的插入结果为:" << endl;
sc(I);
cout << "-----------请问您是继续插入?是请输入1" << endl;
cin >> temp;
return temp;
}
//返回的temp将在主函数进行判断,继续插入则从新调用函数
7.顺序表的删除
-删除函数与插入函数相差无几,都是用之后的数据来掩盖之前的数据
-代码由插入函数修改而来,可以对比一下,二者几乎没有区别
-算法描述:
1.新建一个内存空间
2.找到由用户执行的位置
3.在将原来的数据复制到新内存空间时,跳过指定的位置
请看代码:
int delete1(Sqlist& I)
{
//首先询问删除的位置
cout << "请问你要删除第几位?" << endl;
int n = 0;
cin >> n;//保存删除位置
STU* p2 = I.data;
//为其开辟新的内存空间
I.lenght = I.lenght - 1;//顺序表长度减一
STU* p = (STU*)malloc(I.lenght * sizeof(STU));
int i = 0;
for (int i2; i2 < I.lenght+1; i2++, i++)
{
if (i == n)
{
i2++;
}
strcpy_s((p + i)->name, (p2 + i2)->name);
strcpy_s((p + i)->num, (p2 + i2)->num);
(p + i)->gra.SX = (p2 + i2)->gra.SX;
(p + i)->gra.YW = (p2 + i2)->gra.YW;
(p + i)->gra.YY = (p2 + i2)->gra.YY;
}
free(p2);
I.data = p;
int temp;
cout << "如果你要继续输入,请按1" << endl;
cin >> temp;
return temp;
}
至此,顺序表的建立,数据写入,查找,删除,插入已经完成
放一段主函数的代码:
int main()
{
Sqlist I;
Sqlist* p = &I;//定义一个顺序表指针,保存顺序表I的地址,方便传入,此处使用引用更加快捷
//目的是让初始化的顺序表和定义的顺序表使用同一片内存空间
//尝试一下指针
int gs=stu(p);//初始化完成,gs用于保存学生个数
input(I, gs);//输出和输出
// find(I, gs);//查找
int temp= insert(I, gs);
for (int i = 0;; i++)
{
if (temp == 1)
{
temp = insert(I, gs);
}
else
{
break;
}
}
return 0;
}
由于本题尚未完全完成,所以主函数并不完整
cs函数就是输出函数,输出顺序表中的数据
接下来就是完成题目中的其他要求
————————————————————————
8.统计表中学生个数;
学生个数不做统计,因为已经保存在顺序表的lenget中了
-非要统计,也可以使用如下代码
int i=sizeof(I.data)/sizeof(STU);
//i中保存的就是学生个数
9.求出所有学生成绩的最高分并在主函数中显示
-成绩最高分用平均分来展示,保留两位小数
-算最高分我习惯使用选择排序,这样只需要输出第一位即可
代码如下:
void gramax(Sqlist& I)
{
STU stu1;//数据交换暂放处
STU* p = I.data;
int i = I.lenght;//统计学生个数
for (int n = 0; n < i - 1; n++)//选择排序,将平均成绩最大值的同学放在首位
{
float ma = ((p + n)->gra.SX + (p + n)->gra.YW + (p + n)->gra.YY) / 3;
printf("------%.2f---------\n", ma);
for (int n2 = n + 1; n2 < i; n2++)
{
float ma2 = ((p + n2)->gra.SX + (p + n2)->gra.YW + (p + n2)->gra.YY) / 3;
printf("--------%.2f--------\n", ma2);
if (ma < ma2)
{
//交换数据
strcpy_s(stu1.name, (p + n)->name);
strcpy_s((p + n)->name, (p + n2)->name);
strcpy_s((p + n2)->name, stu1.name);
strcpy_s(stu1.num, (p + n)->num);
strcpy_s((p + n)->num, (p + n2)->num);
strcpy_s((p + n2)->num, stu1.num);
stu1.gra.SX = (p + n)->gra.SX;
(p + n)->gra.SX = (p + n2)->gra.SX;
(p + n2)->gra.SX = stu1.gra.SX;
stu1.gra.YW = (p + n)->gra.YW;
(p + n)->gra.YW = (p + n2)->gra.YW;
(p + n2)->gra.YW = stu1.gra.YW;
stu1.gra.YY = (p + n)->gra.YY;
(p + n)->gra.YY = (p + n2)->gra.YY;
(p + n2)->gra.YY = stu1.gra.YY;
}
}
}
//数据交换完成
//输出数据
sc(I);
}
至此,题目中的要求已经全部完成,文章也差不多结束了,如果对你有帮助,不妨点个赞支持一下,拜谢
有一些bug,以下放上整个题完整代码:
#include <iostream>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<stdio.h>
#include<cstring>
#define MAX 10;
#pragma warning( disable : 4996)
using namespace std;
//顺序表操作
//1.定义学生群体,使用结构体
//成绩结构体
typedef struct grades
{
//只保存分数
float YW;
float SX;
float YY;
}GRA;
typedef struct student
{
//姓名
char name[20];
//学号
char num[15];
//成绩,此处只取语数外
GRA gra;
}STU;
//定义顺序表------
typedef struct I
{
STU* data;//顺序表数据指针,数据元素
int lenght;//顺序表当前长度
int Maxsize;//顺序表最大长度
}Sqlist;
//顺序表定义完成,不占用内存空间
//对象函数,询问有几个学生,为其开辟空间,并返回开辟空间的指针
//创建一个空表
int stu(Sqlist *p)
{
std::cout << "此次使用c++完成" << endl;
std::cout << "请指定学生位数:" << endl;
int n;
std::cin >> n;
p->data = (STU*)malloc(n * sizeof(STU));//开辟的内存空间,将数组首地址返回给data顺序表中的data
p->lenght = n;
p->Maxsize = MAX;
if (n > p->Maxsize)
{
p->Maxsize = n;
}
return n;
}
//输出函数————————
void sc(Sqlist& I)
{
STU* p = I.data;
for (int i = 0; i < I.lenght; i++)
{
printf("姓名:%s 学号:%s 语文:%.2f 数学:%.2f 英语:%.2f", (p + i)->name, (p + i)->num, (p + i)->gra.YW, (p + i)->gra.SX, (p + i)->gra.YY);
printf("\n");
}
}
//-----------------------------
//----------------------------
//接下来是数据输入
void input(Sqlist &I,int gs)
{
STU* p = I.data;
for (int n = 0; n < gs; n++)
{
std::cout << "请输入学生姓名:" << endl;
cin >>(p+n)->name;
// getchar();
std::cout << "请输入学生学号:" << endl;
cin >> (p+n)->num;
// getchar();
std::cout << "请输入成绩:\n语文:" << endl;
cin >> (p+n)->gra.YW;
//getchar();
cout << "数学:" << endl;
cin >> (p + n)->gra.SX;
//getchar();
cout << "英语:" << endl;
cin >> (p + n)->gra.YY;
// getchar();
}
//输入完成,输出
system("cls");
for (int i = 0; i < gs; i++)
{
printf("这是第%d位学生:\n", i);
printf("姓名:%s 学号:%s 语文:%.2f 数学:%.2f 英语:%.2f", (p+i)->name, (p+i)->num, (p+i)->gra.YW, (p+i)->gra.SX, (p+i)->gra.YY);
printf("\n");
}
}
//输入函数完成--------------------------
//查找函数————————————
void find(Sqlist& I, int gs)
{
STU* p = I.data;
string name;
cout << "请输入你要查找的学生姓名:" << endl;
cin >> name;
int t = 0;
for (int i = 0; i < gs; i++)
{
if (name == (p + i)->name)
{
cout << "你查找的学生姓名为:" << name << endl;
printf("姓名:%s 学号:%s 语文:%.2f 数学:%.2f 英语:%.2f\n", (p + i)->name, (p + i)->num, (p + i)->gra.YW, (p + i)->gra.SX, (p + i)->gra.YY);
t = 1;
}
}
if (t == 0)
{
cout << "找不到数据" << endl;
}
}
//查找函数结束————————
//查找函数2————————按位次查找
int find2(Sqlist& I, int gs)
{
STU* p = I.data;
int n = 0;
cout << "请输入你要查找的序号:" << endl;
cin >> n;
if (n > I.lenght)
{
cout << "你输入的数据不合法!请重新输入。" << endl;
return 0;
}
for (int i = 0; i < gs; i++)
{
if (i == n)
{
printf("姓名:%s 学号:%s 语文:%.2f 数学:%.2f 英语:%.2f", (p + i)->name, (p + i)->num, (p + i)->gra.YW, (p + i)->gra.SX, (p + i)->gra.YY);
}
}
}
//查找函数结束
//插入函数————————
int insert(Sqlist &I,int gs)
{
STU stu1;
int n = 0;
int temp;
//合法判断
cout << "请选择你要插入的位置:" << endl;
cin >> n;
n = n - 1;
for (int tt = 0;; tt++)
{
if (n > I.lenght)
{
cout << "你要插入的位置不合法!请重新选择。" << endl;
cin >> n;
n = n - 1;
}
else
{
break;
}
}
//录入输入信息
STU* p2 = I.data;
cout << "请输入你要插入的数据:" << endl;
cout << "姓名:" << endl;
cin >> stu1.name;
cout << "学号:" << endl;
cin >> stu1.num;
cout << "语文:" << endl;
cin >> stu1.gra.YW;
cout << "数学:" << endl;
cin >> stu1.gra.SX;
cout << "英语:" << endl;
cin >> stu1.gra.YY;
//信息录入完成,现在开始扩顺序表及内存空间
I.lenght = I.lenght + 1;//容量扩大
STU* p = (STU*)malloc(I.lenght * sizeof(STU));//开辟新的内存空间并加一
//算法描述
//1.把原来的数据复制到新的内存空间
//2.在复制时进行判断,将插入点留白
//3.顺势插入
//---------------------------------------------
//现在开始执行,现在有两片内存空间,I.data和p,p是新的内存空间
int i2 = 0;
for (int i = 0; i < I.lenght; i++, i2++)
{
//首先进行判断
if (i == n)
{
strcpy_s((p + n)->name, stu1.name);
strcpy_s((p + n)->num, stu1.num);
(p + n)->gra.SX = stu1.gra.SX;
(p + n)->gra.YW = stu1.gra.YW;
(p + n)->gra.YY = stu1.gra.YY;
i++;
}
//开始复制
strcpy_s((p + i)->name, (p2 + i2)->name);
strcpy_s((p + i)->num, (p2 + i2)->num);
(p + i)->gra.SX = (p2 + i2)->gra.SX;
(p + i)->gra.YW = (p2 + i2)->gra.YW;
(p + i)->gra.YY = (p2 + i2)->gra.YY;
//复制完成
}
//到上面时,已经进行了留白,现在插入即可
//插入完成,所有数据用指针p调用
free(I.data);
I.data = p;
cout << "你最终的插入结果为:" << endl;
sc(I);
cout << "-----------请问您是继续插入?是请输入1" << endl;
cin >> temp;
return temp;
}
int delete1(Sqlist& I)
{
//首先询问删除的位置
cout << "请问你要删除第几位?" << endl;
int n = 0;
cin >> n;//保存删除位置
n = n - 1;
STU* p2 = I.data;
//为其开辟新的内存空间
I.lenght = I.lenght - 1;//顺序表长度减一
STU* p = (STU*)malloc(I.lenght * sizeof(STU));
int i = 0;
for (int i2=0; i2 < I.lenght + 1; i2++, i++)
{
if (i == n)
{
i2++;
}
strcpy_s((p + i)->name, (p2 + i2)->name);
strcpy_s((p + i)->num, (p2 + i2)->num);
(p + i)->gra.SX = (p2 + i2)->gra.SX;
(p + i)->gra.YW = (p2 + i2)->gra.YW;
(p + i)->gra.YY = (p2 + i2)->gra.YY;
}
free(p2);
I.data = p;
int temp;
cout << "如果你要继续删除,请按1" << endl;
cin >> temp;
return temp;
}
void gramax(Sqlist& I)
{
STU stu1;//数据交换暂放处
STU* p = I.data;
int i = I.lenght;//统计学生个数
for (int n = 0; n < i - 1; n++)//选择排序,将平均成绩最大值的同学放在首位
{
float ma = ((p + n)->gra.SX + (p + n)->gra.YW + (p + n)->gra.YY) / 3;
printf("------%.2f---------\n", ma);
for (int n2 = n + 1; n2 < i; n2++)
{
float ma2 = ((p + n2)->gra.SX + (p + n2)->gra.YW + (p + n2)->gra.YY) / 3;
printf("--------%.2f--------\n", ma2);
if (ma < ma2)
{
//交换数据
strcpy_s(stu1.name, (p + n)->name);
strcpy_s((p + n)->name, (p + n2)->name);
strcpy_s((p + n2)->name, stu1.name);
strcpy_s(stu1.num, (p + n)->num);
strcpy_s((p + n)->num, (p + n2)->num);
strcpy_s((p + n2)->num, stu1.num);
stu1.gra.SX = (p + n)->gra.SX;
(p + n)->gra.SX = (p + n2)->gra.SX;
(p + n2)->gra.SX = stu1.gra.SX;
stu1.gra.YW = (p + n)->gra.YW;
(p + n)->gra.YW = (p + n2)->gra.YW;
(p + n2)->gra.YW = stu1.gra.YW;
stu1.gra.YY = (p + n)->gra.YY;
(p + n)->gra.YY = (p + n2)->gra.YY;
(p + n2)->gra.YY = stu1.gra.YY;
}
}
}
//数据交换完成
//输出数据
sc(I);
}
int face()
{
cout << "本程序编译环境为vs2022" << endl;
cout << "请选择你的操作:" << endl;
cout << "1.输入数据" << endl;
cout << "2.查找数据" << endl;
cout << "3.插入数据" << endl;
cout << "4.删除数据" << endl;
cout << "5.找出平均分最大的同学" << endl;
int n;
cin >> n;
return n;
}
int main()
{
Sqlist I;
Sqlist* p = &I;//定义一个顺序表指针,保存顺序表I的地址,方便传入,此处使用引用更加快捷
//目的是让初始化的顺序表和定义的顺序表使用同一片内存空间
//尝试一下指针
int gs=stu(p);//初始化完成,gs用于保存学生个数
int ch = 1;
int n;
int temp, temp1;
while (ch==1)
{
n = face();
switch (n)
{
case 1:
input(I, gs);
break;
case 2:
find(I,gs);
find2(I, gs);
break;
case 3:
temp = insert(I, gs);
while (temp == 1)
{
temp = insert(I, gs);
}
break;
case 4:
temp1 = delete1(I);
while (temp == 1)
{
temp1 = delete1(I);
}
break;
case 5:
gramax(I);
break;
}
cout << "如果你要继续操作,请按1" << endl;
cin >> ch;
}
return 0;
}
谢谢观看!请勿抄袭!