题目:宿舍管理系统(为宿舍管理人员编写一个宿舍管理查询软件)
要求:
1.采用交互工作方式
2.建立数据文件,数据文件按关键字(姓名、学号、房号)进行排序(冒泡、选择、插入排序等任选一种)
3.查询菜单:用二分查找实现以下操作,并输出查询结果(可以连续操作)
A.按姓名查询
B.按学号查询
C.按房号查询
代码:
list.cpp
#include<iostream>
#include<string.h>
using namespace std;
struct Node { //定义结构体,存放学生信息
string sname;
int sid;
int sroom;
Node *next;
Node(); //构造函数
};
Node::Node()
{
sid = 0;
sname = '\0';
sroom = 0;
next = NULL;
}
class List {
public:
List(); //构造函数
int size() const; //返回线性表的大小
Node *set_position(int position) const; //让指针指向指定位置
void insert(const Node &x);//插入数据
void sid_sort(); //按学号排序
void sname_sort(); //按姓名排序
void sroom_sort(); //按房号排序
void sidbinary_search(int target); //按学号查找
void snamebinary_search(string target); //按名字查找
void sroombinary_search(int target); //按宿舍号查找
void print();
~List(); //析构函数
protected:
int count; //计数器
Node *head; //头指针
};
List::List() //构造函数
{
count = 0; //计数器置0
head = NULL;
}
int List::size() const //返回线性表大小
{
return count;
}
Node *List::set_position(int position) const //让指针指到指定位置
{
Node *q = head;
for (int i = 0; i < position; i++) q = q->next; //遍历,找到指定位置
return q;
}
void List::insert(const Node &x)//插入数据
{
Node *p = new Node();
p->sid = x.sid;
p->sname = x.sname;
p->sroom = x.sroom;
p->next = NULL;
if(count == 0)//如果原链表没有数据则插入的是表头
{
head = p;
}
else
{
Node *q = head;
while(q->next != NULL)
{
q = q->next;
}
q->next = p;
}
count++;
cout << "Success!" << endl;
}
void List::sid_sort()//按学号排序
{
if(count == 0)
{
cout << "No Student Information!" << endl;
return ;
}
Node *first_unsorted;//指向无序结点
Node *position; //指向可以插入结点位置
Node *inter; //找到的可以插入的结点
Node *current;//用来指向有序链表的结点
first_unsorted = head->next;//开始无序结点是current的下一个结点
current = head;
current->next = NULL;
while(first_unsorted)//直到链表最后一个结点结束
{
inter = first_unsorted;//每次从一个新的无序结点开始
first_unsorted = first_unsorted ->next;//指向下一个无序结点
current = head;
//而有序结点则从第一个开始,每次从最小的开始比较;如果比当前最小的还小放在它前面
while(current && (current->sid < inter->sid))//如果比当前有序结点大,则和下一个有序结点比较
{
position = current;
current = current->next;
}
if(current == head )//即比第一个有序结点还小,则头插
head = inter;
else //要插入的不是头结点则把它插入找出的合适的位置
position->next = inter;
inter->next = current;//将新结点与后面的链表连接起来
}
cout << "Sort Success!" << endl;
}
void List::sname_sort()//按姓名排序
{
if(count == 0)
{
cout << "No Student Information!" << endl;
return ;
}
Node *first_unsorted;//指向无序结点
Node *position; //指向可以插入结点位置
Node *inter; //找到的可以插入的结点
Node *current;//用来指向有序链表的结点
current = head;//开始认为第一个结点有序
first_unsorted = head->next;//开始无序结点是current的下一个结点
current->next = NULL;
while(first_unsorted)//直到链表最后一个结点结束
{
inter = first_unsorted;//每次从一个新的无序结点开始
first_unsorted = first_unsorted ->next ;//指向下一个无序结点
current = head ;
//而有序结点则从第一个开始,每次从最小的开始比较;如果比当前最小的还小放在它前面
while(current && (current->sname < inter->sname))//如果比当前有序结点大,则和下一个有序结点比较
{
position = current;
current = current->next ;
}
if(current == head )//即比第一个有序结点还小,则头插
head = inter;
else //要插入的不是头结点则把它插入找出的合适的位置
position->next = inter;
inter->next = current;//将新结点与后面的链表连接起来
}
cout << "Sort Success!" << endl;
}
void List::sroom_sort()//按房号排序
{
if(count == 0)
{
cout << "No Student Information!" << endl;
return ;
}
Node *first_unsorted;//指向无序结点
Node *position; //指向可以插入结点位置
Node *inter; //找到的可以插入的结点
Node *current;//用来指向有序链表的结点
current = head;//开始认为第一个结点有序
first_unsorted = head->next;//开始无序结点是current的下一个结点
current->next = NULL;
while(first_unsorted)//直到链表最后一个结点结束
{
inter = first_unsorted;//每次从一个新的无序结点开始
first_unsorted = first_unsorted ->next;//指向下一个无序结点
current = head ;
//而有序结点则从第一个开始,每次从最小的开始比较;如果比当前最小的还小放在它前面
while(current && (current->sroom < inter->sroom))//如果比当前有序结点大,则和下一个有序结点比较
{
position = current;
current = current->next ;
}
if(current == head )//即比第一个有序结点还小,则头插
head = inter;
else //要插入的不是头结点则把它插入找出的合适的位置
position->next = inter;
inter->next = current;//将新结点与后面的链表连接起来
}
cout << "Sort Success!" << endl;
}
void List::print() //按顺序打印出线性表数据
{
Node *p = head;
cout << "sid sname sroom" << endl;
while(p != NULL)
{
cout << p->sid << " " << p->sname << " " << p->sroom << endl;
p = p->next;
}
}
void List::sidbinary_search(int target) //按学号查找
{
Node *mid;
int frontnum = 0;
int lastnum = count - 1;//前后下标,用来规定范围
while (frontnum < lastnum) //当前下标小于后下标,继续循环
{
int midnum = (frontnum + lastnum) / 2;//找出中间坐标
mid = set_position(midnum);
if(mid->sid < target)
frontnum = midnum + 1; //如果中间的值小于要查找的值,说明要查找的值在后半部分,前下标移到中间位置的后一个位置
else
lastnum = midnum; //如果中间的值大于要查找的值,说明要查找的值在前半部分,后下标移到中间位置
}
if (lastnum < frontnum)
{
cout << "Student information is not exit!" << endl; //当前下标大于后下标时,说明没有找到
}
else //当前后下标指向同一个元素
{
mid = set_position(frontnum);
if (mid->sid == target) //判断这个结点中的数据与所查找的数据是否一致,如果一致则输出,该位置一定是在这个线性表中第一次出现的位置
{
cout << "sid" << " "<< "sname" << " "<< "sroom" << endl;
cout << mid->sid << " " << mid->sname << " " << mid->sroom << endl;
}
else //如果不是则说明表中没有这个数据
{
cout << "Student information is not exit!" << endl;
}
}
}
void List::snamebinary_search(string target) //按姓名查找
{
Node *mid;
int frontnum = 0;
int lastnum = count - 1;//前后下标,用来规定范围
while (frontnum < lastnum) //当前下标小于后下标,继续循环
{
int midnum = (frontnum + lastnum) / 2;//找出中间坐标
mid = set_position(midnum);
if (mid->sname < target)
frontnum = midnum + 1; //如果中间的值小于要查找的值,说明要查找的值在后半部分,前下标移到中间位置的后一个位置
else//当前后下标指向同一个元素
lastnum = midnum; //如果中间的值大于要查找的值,说明要查找的值在前半部分,后下标移到中间位置
}
if (lastnum < frontnum) //当前下标大于后下标时,说明没有找到
{
cout << "Student information is not exit!" << endl;
}
else
{ //当前后下标指向同一个元素
mid = set_position(frontnum);
if (mid->sname == target)//判断这个结点中的数据与所查找的数据是否一致,如果一致则输出,该位置一定是在这个线性表中第一次出现的位置
{
cout << "sname" << " "<< "sid" << " "<< "sroom" << endl;
cout << mid->sname << " " << mid->sid << " " << mid->sroom << endl;
if(mid->next != NULL)
{
Node *p = mid->next;
while(p && (p->sname == mid->sname)) //查找后面还有没有相同的数据
{
cout << p->sname << " " << p->sid << " " << p->sroom << endl;
p = p->next;
} //如果这个位置的值等于要查找的值,则该位置一定是在这个表中第一次出现的位置
}
}
else//如果不是则说明表中没有这个数据
{
cout << "Student information is not exit!" << endl;
}
}
}
void List::sroombinary_search(int target) //按房号查找
{
Node *mid;
int frontnum = 0;
int lastnum = count - 1;//前后下标,用来规定范围
while (frontnum < lastnum) //当前下标小于后下标,继续循环
{
int midnum = (frontnum + lastnum) / 2;//找出中间坐标
mid = set_position(midnum);
if (mid->sroom < target)
frontnum = midnum + 1; //如果中间的值小于要查找的值,说明要查找的值在后半部分,前下标移到中间位置的后一个位置
else
lastnum = midnum; //如果中间的值大于要查找的值,说明要查找的值在前半部分,后下标移到中间位置
}
if (lastnum < frontnum)//当前下标大于后下标时,说明没有找到
{
cout << "Student information is not exit!" << endl;
}
else { //当前后下标指向同一个元素
mid = set_position(frontnum);
if (mid->sroom == target)
{
cout << "sroom" << " "<< "sid" << " "<< "sname" << endl;
cout << mid->sroom << " " << mid->sid << " " << mid->sname << endl;
if(mid->next != NULL)
{
Node *p = mid->next;
while(p && (p->sroom == mid->sroom))//查找后面还有没有相同的数据
{
cout << p->sroom << " " << p->sid << " " << p->sname << endl;
p = p->next;
}//如果这个位置的值等于要查找的值,则该位置一定是在这个表中第一次出现的位置
}
}
else//如果不是则说明表中没有这个数据
{
cout << "Student information is not exit!" << endl;
}
}
}
List::~List() //析构函数
{
Node *p,*q;
for(p = head;p;p = q)
{
q = p->next;
delete p;
} //遍历,有数据的释放空间
count = 0;
head = NULL; //置空
}
main.cpp
#include <iostream>
#include <fstream>
#include "list.cpp"
using namespace std;
void print(List const &nowlist) //将线性表中的数据写入文件中
{
ofstream ofs;
ofs.open("student.txt",ios::out);
ofs.clear();
Node *p;
ofs << "sid" << " " << "sname" << " " << "sroom" << endl;
for(int i = 0;i < nowlist.size();i++)
{
p = nowlist.set_position(i);
ofs << p->sid << " " << p->sname << " " << p->sroom<< endl;
}
ofs.close();
}
int main()
{
List list1;
ofstream ofs;
ofs.open("student.txt",ios::out);
ofs << "sid" << " " << "sname" << " " << "sroom" << endl;
int t = 1;
char i = 0;
cout << "---------------------------------------------------" << endl;
cout << "欢迎进入宿舍查询软件" << endl;
cout << "---------------------------------------------------" << endl;
while(t)
{
cout << "1.插入学生信息 2.排序 3.查询 4.退出" << endl << "请选择要进行的操作:";
cin >> i;
switch(i)
{
case '1': //插入学生信息
{
Node newstu;
cout << "请输入该学生的学号:";
cin >> newstu.sid;
if(cin.fail())
{
cout << "Please enter the correct number!" << endl;
cin.clear(); //清除std::cin的错误状态
cin.sync(); //清空输入缓冲区
break;
}
cout << "请输入该学生的姓名:";
cin >> newstu.sname;
cout << "请输入该学生的房号:";
cin >> newstu.sroom;
if(cin.fail())
{
cout << "Please enter the correct number!" << endl;
cin.clear(); //清除std::cin的错误状态
cin.sync(); //清空输入缓冲区
break;
}
list1.insert(newstu);
ofs << newstu.sid << " " << newstu.sname << " " << newstu.sroom<< endl;
break;
}
case '2': //排序
{
char ch;
cout << "A.按姓名排序 B.按学号排序 C.按房号排序" << endl << "请选择排序的方式:";
cin >> ch;
switch(ch)
{
case 'A': //按姓名排序
{
list1.sname_sort();
print(list1);
continue;
}
case 'B': // 按学号排序
{
list1.sid_sort();
print(list1);
continue;
}
case 'C': //按房号排序
{
list1.sroom_sort();
print(list1);
continue;
}
default:
{
cout << "无此选项,请重新选择" << endl;
continue;
}
}
}
case '3': //查询
{
char ch;
cout << "A.按姓名查询 B.按学号查询 C.按房号查询 " << endl << "请选择查询的方式:";
cin >> ch;
switch(ch)
{
case 'A': //按姓名查询
{
string name;
cout << "请输入要查询的学生的姓名:";
cin >> name;
list1.sname_sort();
list1.snamebinary_search(name);
continue; //问题:运行这部分完程序直接结束
}
case 'B': //按学号查询
{
int id;
cout << "请输入要查询的学生的学号:";
cin >> id;
if(cin.fail())
{
cout << "Please enter the correct number!" << endl;
cin.clear(); //清除std::cin的错误状态
cin.sync(); //清空输入缓冲区
break;
}
list1.sid_sort();
list1.sidbinary_search(id);
continue;
}
case 'C': //按房号查询
{
int room;
cout << "请输入要查询的房号:";
cin >> room;
if(cin.fail())
{
cout << "Please enter the correct number!" << endl;
cin.clear(); //清除std::cin的错误状态
cin.sync(); //清空输入缓冲区
break;
}
list1.sroom_sort();
list1.sroombinary_search(room);
continue;
}
default:
{
cout << "无此选项,请重新选择" << endl;
continue;
}
}
}
case '4': //退出
{
t = 0;
break;
}
default:
{
cout << "无此选项,请重新选择" << endl;
break;
}
}
}
return 0;
}