实现功能:
[问题描述] 请设计一个学生成绩管理系统。学生信息包括学号、姓名、性别、英语、数学、程序设 计、数据结构、总分、名次等内容。请实现如下功能:
(1) 学生信息的录入(并能够检查学号重复者、成绩不超过 100 分检查,计算总分);
(2) 学生信息的查询(可以按照学号和姓名两种方式查询);
(3) 学生信息的修改(一律按照学号对应修改,仅对四门课程成绩修改);
(4) 学生总分的排序(要求稳定排序,有相同分数时按照并列名次处理);
(5) 学生信息的输出;
(6) 退出管理系统 [基本要求]
设计合适的数据结构和算法编写程序完成上述功能,并具有主控菜单,能够按照菜单选 项进行功能操作。
思路 1:
根据学生管理系统所需要的功能进行函数实现,存储学生的信息用双链表实现。
学生的信息的录入功能: 我实现的学生信息录入学生总分的排序是一体的,每次录入学生信息后立即进行位置排序,因此用双链表 就非常方便,可以很方便地进行插入,而不需要像数组那样拖拽大量元素,这就是我采用双链表的原因。位置 排序采用的是根据总分排序的内置改进后的顺序插入排序,与修改学生信息的算法一致,会在思路2中详细解 读。
每次通过新的学生学号信息,在双链表中顺序遍历看是否有重复学号,而选择顺序遍历的原因是由于学号 在双链表中的排序是无序的,有序的只要总分的排序,因此采用顺序查找。
在学号没问题后才检测分数不超过100,用while循环使检测到后的超100分的成绩修改直到不超过为止。
学生信息查询功能:
(1):根据学号查询: 由于学号不可重复和学号无序,因此用while循环使指针不断顺序前进。因此顺序查找会在找到后立即输 出,然后break。
(2):根据名字查询: 由于名字可以重复和名字无序,因此用while循环使指针不断前进遍历整个链表,使每个该名字的学生信 息都输出。
学生信息修改功能: 利用指针,找到该学号的学生位置,修改后总分会变,因此需要进行排序。在链表中删除该学生节点,利 用内置的改进顺序插入算法进行插入该节点。
学生总分的排序: 初始化i=1,p指针;p顺序前进,p.总分>.总分,则令p的排名为i且i++。但若p.总分=.总 分,则令p的排名为i即可,使下一个的排名不变,实现并列名次。
学生信息的输出: 利用指针不断前进,在指针不为NULL时输出每个学生的信息。 退出管理系统: 利用return 0退出main函数。
思路 2:
算法思想:
1.改进的顺序插入算法:
顺序比较指针p和录入的节点*stu,但是指针p每次前进,为p=,也就是每一次走 两步,比较位置正确就插入,不对就通过比较大小选择后退一步还是p=。 这样改进后就比正常的顺序算法快了一倍。
2.修改学生信息中的双链表添加头结点:
需要删除的节点为*stu;
添加头结点是服务于修改学生信息功能中的删除功能,因为我的思路为每次修改先删 除该节点,然后再插入排序。
没有添加头结点的话需要分多种情况进行讨论,比如删除后链表空,删除的节点位置 不同而删除后链表只有一个元素或多个元素时需要有很多删除条件。因此采用头结点可以有 效解决这个问题,只需要令删除的节点stu的前一个节点指向,也就是指 向;if(!=NULL){=;}两个语句即可,减少了大量代码。
采用的方法:
1.存储方法:双链表 利用双链表的特点,一个连接一个。
每次插入,只需要先将前后两元素和自己相互连接即可。删除也只需要把前后两元素 相互连接即可,因此可以很方便地插入和删除,而不用像数组那样拖拽许多元素,使算法的 时间复杂度大大减小。
2.排序方法:顺序查找和改进的顺序插入
顺序查找:
基于查找的选项为学号和名字都是无序的,因此采用顺序查找比较好。一个个地寻 找,找到对应的数据输出。
改进的顺序插入:
从头到尾顺序插入,利用一次走两步进行比较,使时间减少了一倍。
3.功能菜单:while包含switch
Swtich组成功能菜单,break破除本次switch,return 0破除main函数,结束运行。
源码:
#include<iostream>
#include<string>
#include<stack>
using namespace std;
class datatype
{
public:
long long int id;
string sex, name;
int eng, math, c, shuju, sum, i;
datatype()
{
id = 0;
eng = math = c = shuju = sum = 0;
i = 0;
}
};
class student
{
public:
datatype myinfo;
student* nextstu, *backstu;
student()
{
nextstu = backstu = NULL;
}
};
class students
{
public:
student* stus;
int length;
students()
{
stus = new student;
length = 0;
}
};
bool ifture(long long int theid, students thestus);//判断学号重复问题
int nextque(student* &stu, students &thestus);//改进的顺序插入算法(一次两个地寻找,进行顺序插入)
void stuin(students &thestus);//输入学生
void find(string thename, students thestus);//名字查找学生
void find(long long int theid, students thestus);//学号查找学生
void revise(long long int theid, students &thestus);//修改学生信息
void outstus(students thestus);//输出全部学生信息
void que(students &thestus);//内置排序
//改进:
//1.插入算法的一次排序两个,速度为普通的顺序查找的两倍2.头结点,让删除节点快了许多
int main()
{
students thestus;
while(1)
{
int x;
cout << "------此为学生管理系统,请输入数字以选择功能操作:" << endl;
cout << "------功能1:学生信息录入。" << endl;
cout << "------功能2:学生信息查询。" << endl;
cout << "------功能3:学生信息修改。" << endl;
cout << "------功能4,全部学生信息输出。" << endl;
cout << "------功能5:退出系统。" << endl;
cin >> x;
switch(x)
{
case 1:
stuin(thestus);//输入学生
system("pause");
system("cls");
break;
case 2:
cout << "-----请选择查找方式:数字1:名字查找,数字2:学号查找。" << endl;
int x1; cin >> x1;
if(x1==1)
{
string thename;
cout << "-----请输入名字:" << endl; cin >> thename;
find(thename,thestus);//名字查找学生
system("pause");
system("cls");
break;
}
else if(x1==2)
{
long long int theid;
cout << "-----请输入学号:" << endl; cin >> theid;
find(theid, thestus);//学号查找学生
system("pause");
system("cls");
break;
}
else
{
cout << "-----您输入的选项不对,退出。" << endl;
system("pause");
system("cls");
break;
}
case 3:
cout << "-----请输入学生的学号:" << endl;
long long int theid; cin >> theid;
revise(theid,thestus);//修改学生信息
system("pause");
system("cls");
break;
case 4:
outstus(thestus);//输出全部学生信息
system("pause");
system("cls");
break;
case 5:
return 0;
default:
cout << "你输入的选项错误。" << endl;
system("pause");
system("cls");
break;
}
}
}
void stuin(students &thestus)//输入学生
{
cout << "请输入录入的学生个数:" << endl;
int n=0; cin >> n;
= + n;
for (int i = 0; i < n; i++)
{
student* stu = new student;
cout << "请依次输入学生的学号,姓名,性别,英语,数学,程序设计,数据结构的信息或成绩." << endl;
cout << "性别只有男和女!!!!!" << endl;
cin >> stu-> >> stu-> >> stu-> >> stu-> >> stu-> >> stu-> >> stu->;
if (stu-><=0)
{
cout << "学号小于等于0,如果还剩下操作学生次数,请进行下一次输入,学生个数减一。" << endl;
--;
}
else
{
if (ifture(stu->, thestus))//ture则没有重复学号
{//某项成绩是否超过一百
if (stu-> > 100 || stu-> > 100 || stu-> > 100 || stu-> > 100)
{
while (stu-> > 100)
{
cout << "成绩超过100啦,请重新输入英语成绩:" << endl;
cin >> stu->;
}
while (stu-> > 100)
{
cout << "成绩超过100啦,请重新输入程序设计成绩:" << endl;
cin >> stu->;
}
while (stu-> > 100)
{
cout << "成绩超过100啦,请重新输入数学成绩:" << endl;
cin >> stu->;
}
while (stu-> > 100)
{
cout << "成绩超过100啦,请重新输入数据结构成绩:" << endl;
cin >> stu->;
}
}
stu-> = stu-> + stu-> + stu-> + stu->;
nextque(stu, thestus);//改进的顺序插入算法(一次两个地寻找,进行顺序插入)
}
else
{
cout << "学号重复,如果还剩下操作学生次数,请进行下一次输入,学生个数减一。" << endl;
--;
}
}
}
//得到名次
que(thestus);
}
void find(string thename,students thestus)//名字查找学生
{
student* p = ->nextstu; int i = 0;//i为标记
while(p!=NULL)
{
if((p->)==0)//找到该名字
{
cout << "学生的学号,姓名,性别,英语,数学,程序设计,数据结构,总分的信息或成绩:" << endl;
cout << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << endl;
cout << "该学生名次为:" << p-> << endl << endl;
i++;
}
p = p->nextstu;
}
if (i == 0) { cout << "该名字没有学生。" << endl; }
}
void find(long long int theid, students thestus)//学号查找学生
{
student* p = ->nextstu; int i = 0;
while (p!=NULL&&p-> != theid) { p = p->nextstu; }
//p==NULL没找到||找到就停
if (p == NULL) { cout << "该学号没有学生。" << endl; }
else
{
cout << "学生的学号,姓名,性别,英语,数学,程序设计,数据结构,总分的信息或成绩:" << endl;
cout << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << endl;
cout << "该学生名次为:" << p-> << endl;
}
}
void revise(long long int theid, students &thestus)//修改学生信息
{
student* p; p = ->nextstu;
while (p!=NULL&&p-> != theid) { p = p->nextstu; }//找到该学号位置
if (p == NULL) { cout << "该学号没有学生。" << endl; }
else
{
cout << "请修改四门成绩,英语,数学,程序设计,数据结构:" << endl;
cin >> p-> >> p-> >> p-> >> p->;
if (p-> > 100 || p-> > 100 || p-> > 100 || p-> > 100)
{
while (p-> > 100)
{
cout << "成绩超过100啦,请重新输入英语成绩:" << endl;
cin >> p->;
}
while (p-> > 100)
{
cout << "成绩超过100啦,请重新输入程序设计成绩:" << endl;
cin >> p->;
}
while (p-> > 100)
{
cout << "成绩超过100啦,请重新输入数学成绩:" << endl;
cin >> p->;
}
while (p-> > 100)
{
cout << "成绩超过100啦,请重新输入数据结构成绩:" << endl;
cin >> p->;
}
}
p-> = p-> + p-> + p-> + p->;
//还要排序,p为修改对象
//先删点
p->backstu->nextstu = p->nextstu;
if (p->nextstu != NULL) { p->nextstu->backstu = p->backstu; }
//插入该节点
nextque(p, thestus);//改进的顺序插入算法(一次两个地寻找,进行顺序插入)
}
}
void outstus(students thestus)//输出全部学生信息
{
student* p = ->nextstu;
if (p== NULL) { cout << "此时没有学生" << endl; }
else
{
cout << "学生的学号,姓名,性别,英语,数学,程序设计,数据结构,总分的信息或成绩和名次:" << endl;
while (p != NULL)
{
cout << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << '\t' << p-> << endl;
cout << "该学生名次为:" << p-> << endl;
p = p->nextstu;
}
}
}
void que(students &thestus)//内置排序
{
int i = 1; student* p = ->nextstu;
for (int i2 = 0; i2 < ; i2++)
{
if (p->nextstu == NULL || p-> > p->nextstu->)
{
p-> = i; i++;
}
else { p-> = i; }//=
p = p->nextstu;
}
}
bool ifture(long long int theid,students thestus)//判断学号重复问题
{//ture则没有重复学号
student* p = ->nextstu;
while(p!=NULL)
{
if (p-> == theid) { return 0; }
p = p->nextstu;
}
return 1;
}
int nextque(student* &stu,students &thestus)//改进的顺序插入算法(一次两个地寻找,进行顺序插入)
{
student* p; p = ->nextstu;
stu->backstu = stu->nextstu = NULL;
if (p == NULL) { ->nextstu = stu; stu->backstu = ; }//空表
else//不空
{
while(p!=NULL)
{
if (stu-> >= p->) { p->backstu->nextstu = stu; stu->backstu = p->backstu; p->backstu = stu; stu->nextstu = p; return 0; }//stu>=p
else//stu<p
{
if (p->nextstu == NULL) { p->nextstu = stu; stu->backstu = p; return 0; }//=NULL&&p>stu
else//!=NULL&&p>stu
{
if (p->nextstu-> <= stu->) { p->nextstu->backstu = stu; stu->nextstu = p->nextstu; p->nextstu = stu; stu->backstu = p; return 0; }//p>stu&&stu>=
else//>stu
{
if (p->nextstu->nextstu == NULL) { p->nextstu->nextstu = stu; stu->backstu = p->nextstu; return 0; }//=NULL&&>stu
else { p = p->nextstu->nextstu; }//p=
}
}
}
}
}
}