[ 数据结构 ] DS链表—学生宿舍管理

来源:互联网 发布:模拟火车软件大全 编辑:程序博客网 时间:2024/06/08 03:37

问题 J: DS链表—学生宿舍管理

时间限制: 1 Sec  内存限制: 128 MB
提交: 170  解决: 111
[提交][状态][讨论版]

题目描述

假设某校有20间宿舍,宿舍编号101,102,...,120。每间只住一名学生。初始部分宿舍已用。用两个链表(已用宿舍链表和可用宿舍链表)维护宿舍的管理,实现宿舍分配、宿舍交回。

约定已用宿舍链表按宿舍号升序链接。初始可用宿舍链表也按宿舍号升序链接。

宿舍分配从可用宿舍链表中摘取第一间宿舍分配给学生。学生交回的宿舍挂在可用宿舍链表最后。

备注:使用list容器或静态链表。不用考虑宿舍分配和交回不成功的情况。

输入

初始宿舍状态,第一行输入n,表示已用宿舍n间

后跟n行数据,每行格式为:宿舍号 学生姓名

操作次数m,后跟m行操作,操作格式如下:

assign 学生  //为学生分配宿舍,从可用宿舍链表头摘取一间宿舍,

                    //按宿舍号升序挂在已用宿舍链表中。

return  宿舍号   //学生退宿舍,删除已用宿舍链表中对应结点,

                         //挂在可用宿舍链表尾部。

display_free   //输出可用宿舍链表信息。

display_used   //输出已用宿舍链表信息。


输出

 display_free依次输出当前可用宿舍链表中的宿舍号,具体格式见样例。

 display_used依次输出当前已用宿舍链表中的学生和宿舍号,具体格式见样例。

样例输入

5
李明 103
张三 106
王五 107
钱伟 112
章立 118
8
assign 李四
assign 赵六
return 118
return 101
assign 马山
display_used
assign 林立
display_free

样例输出

赵六(102)-李明(103)-马山(104)-张三(106)-王五(107)-钱伟(112)
108-109-110-111-113-114-115-116-117-119-120-118-101

提示

/*  看到这题第一反应:  STL里有list的话,肯定直接用STL啊!自己写想必会麻烦多了!    但是,用list的时候,又出了一些问题  ----------------我本来的思路是这样子的:----------------  写一个类 dorm 表示宿舍,有 string 类的元素姓名,和 int 类的元素,数字标号;并且给dorm类重载小于号等等..    然后,再建2个list,存 dorm 类的元素,再按照题目要求写    但是最后,这个思路被我废掉了,因为我遇到了各种各样的问题,比如说:  1. 怎么让list对自定义类型排序  这个其实我倒是查了不少资料,好像重载<即可,但是最后写出来,在DevC上,出了许多不知道怎么解决的问题    2. 怎么找到给定标号的指定宿舍    如果用 class dorm,并非不能处理,但是比较麻烦,不仅写得麻烦,比起我最终采用的方法,在时间效率上也糟糕许多    还有许许多多的麻烦,不一一列举了,总之就是这个思路,我发现需要许多基本的知识,我都不懂,需要一一去查,所以...决定先放一放这个写自定义类型,并且用它来作为list的类型的方法    嗯,先把别的题目都做完,还有机会再来看看这种方法,如果要实现,应该怎么实现  ----------------我后来采取的思路:----------------  后来的思路,就,写法上的简洁性和逻辑性上,就比我最初的思路好了不少(这个方法还是向同学请教的),所以说,有时方法很重要啊!~选错了方法,就是要查很多资料,最后发现这个方法没那么容易走通... T^T      这个方法就很巧妙了,我来总结一下为什么可以这么做:  1. 对于空余的宿舍,我们只是需要知道它的标号即可,这个用 1个 list<int>来保存    2.  对于有人住的宿舍,我们要输出的信息比较多,而且含有中文,就势必需要用 char* 后者 string 类来完成,但是毕竟  C++ 的 string 类有很多方便操作字符串的函数,所以还是选 string 类    但是这里有个小细节需要注意(一开始时,我就没有想明白这个问题,所以后来把这部分翻盘重写了一次):  能不能在 assign 分配宿舍以后,直接将它转换为最终输出的那种格式呢?  就是这种:  姓名(宿舍号)这样?    其实是不可以的!!!这个点有点隐蔽,我一开始为了方便输出,也想这么处理,但后来发现绝对不行!    以为你输出时,已用宿舍是按照宿舍号排列,如果直接转为输出的格式,那么就变成了按名字排    你说你去用 substr截取出名字?  可你又知道名字一定是两位?虽然发出来的数据,名字都是2位的,但万一后台的名字,有些人名字是4位呢?    你说你用 string类的 find_first_of来找到宿舍号的第一位?    嗯,那如果宿舍号的范围改动一下,我只保证宿舍号是3位数,从100~999,而不是像这题,最高位一定是1,那用 find_first_of也没用啊!!!    所以,最好的处理方式,就是将这3位放在最前面,在输出时,再用substr函数处理一下  ----------------关于这题,更进一步的思考:----------------  后来突然想到一个有意思的问题,如果这道题,我连宿舍号的位数相同都不保证了,比如说,从 1~1000,这样你用 substr,也不一定就是截取3位嘛...那此时该怎么办呢?    我现在想到的就是,还是把宿舍号放前面,名字放后面,来一个循环:*/string s; //s = num + name; int pos;for (pos = 0; pos <(int)s.size() && isdigit(s[pos]); pos++);//这样最终得到的pos,就是名字的起始位置了,pos的前一个位置,就是宿舍号的终止位置了/*  我觉得这题特别巧妙的地方,也就是对串的处理了    另外...  ----------------列举一下这题可能用到的相关函数----------------string::size() //注意返回值为 size_t,严格说来,用前需要强制转换为int,有时不转也不会错,但是最好还是转string::substr() //截取字串stringstream::.str()函数 //将stringstream类转化为string类to_string() //[ http://www.cplusplus.com/reference/string/to_string/ ]list::remove() //删除list中的指定元素list::erase() //删除迭代器内的元素值list::sort() //排序----------------查阅资料后,觉得应该注意的细节----------------1. 来自  c++ 字符串流 sstream(常用于格式转换) [ http://blog.csdn.net/xiaogugood/article/details/21447431 ]在多次转换中重复使用同一个stringstream(而不是每次都创建一个新的对象)对象最大的好处在于效率。stringstream对象的构造和析构函数通常是非常耗费CPU时间的。//这个在 ACM 里就有体验过了,string 和 stringstream 真的是很慢的,虽然说 STL 好像都或多或少有性能瓶颈2. stream 的清空,并不是用 clear(),上篇文章说是用clear(),但我亲自测验过了,用clear()没用,而是应该用ss.str("");详见:[ http://blog.csdn.net/chenlei0630/article/details/39643887 ]摘录:clear() 方法只是重置了stringstream的状态标志,并没有清空数据。如果需要清空数据,可以用s1.str(“”)来实现这个目的。谨记!不然很容易使你的程序出现错误,并且吃掉你的内存!*/
//用sstream#include <iostream>#include <list>#include <string>#include <sstream>#define rep(i, n) for ( int i = 0; i < (n); i++ )using namespace std;int n; // num of dormsint t; // num of commans void solve (){list<int> free;list<string> used;list<int>::iterator it1;list<string>::iterator it2;string s;stringstream ss;int num;int first; // if it is the first element to be outputcin >> n;for (int i = 101; i <= 120; i++) free.push_back(i);rep(i, n){cin >> s >> num;free.remove(num);//ss.clear();ss.str("");ss << num;string tp = ss.str() + s;//cout << tp << endl;used.push_back( tp );}cin >> t;rep(i, t){cin >> s;if ( s[0] == 'a' ){cin >> s;//cout << "why WA?" << s << endl;num = free.front();free.pop_front();ss.str("");//ss.clear(); //不知道为什么,明明用了 clear() 以后,下一行仍然有输出 //cout << "wrong there? " << ss.str() << endl;ss << num;string tp = ss.str() + s;//cout << tp << endl;used.push_back( tp );}else if ( s[0] == 'r' ){cin >> num;//ss.clear();ss.str("");ss << num;//cout << "wrong there? " << ss.str() << endl;string tp = ss.str();for ( it2 =  used.begin(); it2 != used.end(); it2++ ){if ( (*it2).substr(0, 3) == tp ){used.erase(it2);break;}}free.push_back(num);}else if ( s == "display_free" ){first = 1;for ( it1 = free.begin(); it1 != free.end(); it1++ ){if ( first ) first = 0;else cout << "-";cout << (*it1);}cout << endl;}else{used.sort();first = 1;for ( it2 = used.begin(); it2 != used.end(); it2++ ){if ( first ) first = 0;else cout << "-";cout << (*it2).substr(3) << "(" << (*it2).substr(0, 3) << ")";}cout << endl;}}}int main (){solve();return 0;}

//不用 stream,用 to_string 函数:/*  说明:  学校的oj用不了 C++11的语法特性,所以这个写法,只是理论可行,没真正在oj上判过    查阅过的相关资料:  http://bbs.csdn.net/topics/392033713  https://stackoverflow.com/questions/15569179/to-string-not-declared-in-scope  http://blog.csdn.net/qiqi123i/article/details/53150837  http://blog.csdn.net/qiqi123i/article/details/61912466*/#include <iostream>#include <list>#include <string>#define rep(i, n) for ( int i = 0; i < (n); i++ )using namespace std;int n; // num of dormsint t; // num of commans void solve (){list<int> free;list<string> used;list<int>::iterator it1;list<string>::iterator it2;string s;int num;int first; // if it is the first element to be outputcin >> n;for (int i = 101; i <= 120; i++) free.push_back(i);rep(i, n){cin >> s >> num;free.remove(num);string tp = to_string(num) + s;used.push_back( tp );}cin >> t;rep(i, t){cin >> s;if ( s[0] == 'a' ){cin >> s;num = free.front();free.pop_front();string tp = to_string(num) + s;used.push_back( tp );}else if ( s[0] == 'r' ){cin >> num;string tp = to_string(num);for ( it2 =  used.begin(); it2 != used.end(); it2++ ){if ( (*it2).substr(0, 3) == tp ){used.erase(it2);break;}}free.push_back(num);}else if ( s == "display_free" ){first = 1;for ( it1 = free.begin(); it1 != free.end(); it1++ ){if ( first ) first = 0;else cout << "-";cout << (*it1);}cout << endl;}else{used.sort();first = 1;for ( it2 = used.begin(); it2 != used.end(); it2++ ){if ( first ) first = 0;else cout << "-";cout << (*it2).substr(3) << "(" << (*it2).substr(0, 3) << ")";}cout << endl;}}}int main (){solve();return 0;}