读书人

严蔚敏习题集的停车场的有关问题望高

发布时间: 2012-02-25 10:01:49 作者: rapoo

严蔚敏习题集的停车场的问题,望高手看看,气死了!
小弟因为C语言指针和数组那一块没学好,现在编写清华大学严蔚敏数据结构习题集上停车场这个程序,弄了一周还是出问题。望在论坛上闲逛的高手看下,小弟万分感谢!
程序在调试的时候,编译运行可以,但是一用数据测试就出问题。具体我也不清楚,在我这里看来是不存在任何问题了!因这个程序可说是小弟的处女作,所以非常想弄清楚。在这里先谢谢了。
这个问题的描述是:
设有一个可以停放n辆汽车的狭长停车场,它只有一个大门可以供车辆进出。车辆按到达停车场时间的早晚依次从停车场最里面向大门口处停放(最先到达的第一辆车放在停车场的最里面)。如果停车场已放满n辆车,则后来的车辆只能在停车场大门外的便道上等待,一旦停车场内有车开走,则排在便道上的第一辆车就进入停车场。停车场内如有某辆车要开走,在它之后进入停车场的车都必须先退出停车场为它让路,待其开出停车场后,这些车辆再依原来的次序进场。每辆车在离开停车场时,都应根据它在停车场内停留的时间长短交费。
基本要求是:
以栈模拟停车场,按照从终端读入的输入数据序列进行模拟管理。每一组输入数据包括三个数据项:汽车到达或者离去信息、汽车牌照号码、汽车到达或离开的时刻。对每一组输入数据进行操作后的输出信息为:若是汽车到达,则输出汽车在停车场内或者便道上的位置;若是汽车离去,则输出汽车在停车场内停留的时间和应交付的费用(在便道停留的时间不收费)。栈以顺序结构实现,队列以链表形式实现。PS:当我读到这里的时候,我总感觉汽车到达的时候输出在停车场的位置没用。但是题目是这么要求的也就这么做了。
源代码为:
//停车场问题——栈:模拟车站&队列:模拟便道
#include <iostream.h>
#include "string.h "
#include "stdlib.h "

#define n 2 //车站容量
#define Price 1 // 元/分

typedef struct{//时间节点
int hour,min;
}Time;

typedef struct{//车辆信息
char num[10];
Time reach,leave;
}CarNode;

typedef struct{//模拟车站
CarNode *base,*top;//基址指针和top指针
int Length;
}SqStack;

typedef struct Node{//便道节点
CarNode *data;//车辆信息
struct Node *next;
}QNode;

typedef struct{//模拟便道
QNode *front,*rear;
int Length;
}LinkQueue;

int GetPrice(CarNode *y){//计算价钱
return (((y-> leave.hour-y-> reach.hour)*60+(y-> leave.min-y-> reach.min))*Price);
}//GetPrice

int InitStack(SqStack *S){//车站初始化
S-> base=(CarNode *)malloc((n+1)*sizeof(CarNode));
S-> top=S-> base;
S-> Length=0;

return 1;
}//InitStack

int InitQueue(LinkQueue *Q){//便道初始化
Q-> front=(QNode *)malloc(sizeof(QNode));
Q-> front-> next=NULL;

Q-> rear=Q-> front;

return 1;
}//InitQueue

int Arrival(SqStack *S,LinkQueue *Q){//到达函数
CarNode *p;
p=(CarNode *)malloc(sizeof(CarNode));
QNode *e;

cout < < "\n车牌号为: ";
cin> > (p-> num);

if(S-> Length <n){//进站
++S-> top;
++S-> Length;
cout < < "\n该车在车站的位置为: " < <(S-> Length);
cout < < "\n现在时间为: ";
cin> > (p-> reach.hour)> > (p-> reach.min);
S-> top=p;

return 1;
}//if

else{//站满进便道
cout < < "\n站满,该车须进便道! " < <endl;
e=(QNode *)malloc(sizeof(QNode));
e-> data=p;
e-> next=NULL;
Q-> rear-> next=e;
Q-> rear=e;
}//else
return 1;
}//Arrival

int Leave(SqStack *S,SqStack *T,LinkQueue *Q){//离开函数
CarNode *q,*s;
s=(CarNode *)malloc(sizeof(CarNode));
QNode *t;

cout < < "\n要离开车的牌号为: ";
cin> > (s-> num);

while(S-> Length){//找车
q=(CarNode *)malloc(sizeof(CarNode));
q=S-> top;
S-> top=NULL;
if(strcmp((q-> num),(s-> num))) break;
S-> top--;
--S-> Length;
++T-> top=q;
++T-> Length;
free(q);
}//while

if(strcmp((q-> num),(s-> num))){//找到
cout < < "\n现在时间为: ";
cin> > (q-> leave.hour)> > (q-> leave.min);

cout < < "\n您应缴纳的费用为: " < <GetPrice(q) < <endl;



if(Q-> front!=Q-> rear){//便道车进站
t=Q-> front-> next;
t-> next=NULL;
Q-> front-> next=t-> next;

if(t==Q-> rear) Q-> rear=Q-> front;

t-> data-> reach.hour=q-> leave.hour;//获得便道车进入时间
t-> data-> reach.min=q-> leave.min;
free(q);

cout < < "\n " < <t-> data-> num < < "车现在进入车站第 " < <S-> Length < < "位置! ";
}//if

while(T-> Length> 0){//临时站车回站
if(q) free(q);
q=(CarNode *)malloc(sizeof(CarNode));
q=T-> top;
++S-> top=q;
T-> top;
T-> top--;
}//while
}//if

else{//未找到
cout < < "\n没有找到该车! " < <endl;
return 1;
}//if

return 1;
}//Leave

void main(){
char x;
SqStack S,T;
LinkQueue Q;

InitStack(&S);
InitStack(&T);
InitQueue(&Q);

cout < < "A = 车辆到达;D = 车辆离开;E = 退出程序! " < <endl;

while(1){
while(1){
cin> > x;
if(x== 'a '||x== 'A '||x== 'd '||x== 'D '||x== 'e '||x== 'E ') break;
}//while

if(x== 'a '||x== 'A ') Arrival(&S,&Q);//转到到达函数
if(x== 'd '||x== 'D ') Leave(&S,&T,&Q);//转到离开函数
if(x== 'e '||x== 'E ') break;//退出循环
}//while

cout < < "\nLenic欢迎您的使用!\n ";
}//main
我相信,如果能够从上面依次看到这里的,就是真正想帮我的人,在这里小弟先谢谢了。毕竟这个程序也不能算短!由于是第一次在CSDN上面发表帖子,心里又有点燥,所以有什么不足的地方请指正,谢谢!对了,我好像还不知道分在这里面有什么用,怎么给……
能不能在回复的时候也告诉下,谢谢了!

[解决办法]
看到几点问题:

1.在程序退出前,没有释放掉栈的存储空间(base指向的)、队列的存储空间(每个LinkQueue)和队列中剩余汽车的存储空间(data指向的);这造成了内存泄漏。(虽然很快进程就退出了,但是在任何时候防止内存泄漏,是需要重视的)

2.到达函数有很大纰漏,按代码解释一下(去掉了原文的注释,下面的注释都是解释的内容):
int Arrival(SqStack *S,LinkQueue *Q){
CarNode *p;
p=(CarNode *)malloc(sizeof(CarNode)); //这里不算是错的,虽然时机早了。
QNode *e;

cout < < "\n车牌号为: ";
cin> > (p-> num);

if(S-> Length <n){
++S-> top;
++S-> Length;
cout < < "\n该车在车站的位置为: " < <(S-> Length);
cout < < "\n现在时间为: ";
cin> > (p-> reach.hour)> > (p-> reach.min); //到此为止还是正确的
S-> top=p; // 严重错误!现在S-> top已经不指向栈中的元素了,它指向一个独立对象!
// 应该 *(S-> top) = *p; 然后free(p);
// 并且在进栈的情况下,在堆中分配空间是不高效的,应该用局部变量代替p
return 1;
}

else{
cout < < "\n站满,该车须进便道! " < <endl;
e=(QNode *)malloc(sizeof(QNode));
e-> data=p; //开始分配p的空间,真正的用途在这里
//所以考虑到效率,分配的动作应该下移到这里
//并且将前面用局部变量得到的车牌赋给p
e-> next=NULL;
Q-> rear-> next=e;
Q-> rear=e;
}
return 1;
}

3.离开函数也有与上面对应的纰漏,按代码解释一下:
int Leave(SqStack *S,SqStack *T,LinkQueue *Q){
CarNode *q,*s;
s=(CarNode *)malloc(sizeof(CarNode)); //同样的,这里可以用局部变量 CarNode s;
QNode *t;

cout < < "\n要离开车的牌号为: ";
cin> > (s-> num);

while(S-> Length){
q=(CarNode *)malloc(sizeof(CarNode)); //这是不必要的,下面一行指出了它的错误
q=S-> top; // 前一句q指向的内存再也无法访问了,内存泄漏!!
S-> top=NULL; // 这里是希望启动了出栈程序,应该S-> top--;
if(strcmp((q-> num),(s-> num))) break;
S-> top--; // 在上述top=NULL之后再-- ??
--S-> Length; // 这句也应该再break之前运行。


++T-> top=q; //和进栈时一样,应该*(++T-> top) = *q;
++T-> Length;
free(q); // 结合上面分配内存的错误,这里不应该释放内存,因为它实际指向S的栈空间
}

if(strcmp((q-> num),(s-> num))){
cout < < "\n现在时间为: ";
cin> > (q-> leave.hour)> > (q-> leave.min);

cout < < "\n您应缴纳的费用为: " < <GetPrice(q) < <endl;

//注意此时q仍然指向S的栈空间,所以不再这里free(q)时正确的

if(Q-> front!=Q-> rear){
t=Q-> front-> next;
t-> next=NULL;
Q-> front-> next=t-> next;

if(t==Q-> rear) Q-> rear=Q-> front;

t-> data-> reach.hour=q-> leave.hour;
t-> data-> reach.min=q-> leave.min;
free(q); //仍然是上面的化,在正确的代码中,此处的q应该指向S栈中的空间,不能释放!

cout < < "\n " < <t-> data-> num < < "车现在进入车站第 " < <S-> Length < < "位置! ";
//这句不正确,应该先让临时站车回站回栈
}

while(T-> Length> 0){
if(q) free(q); //不说了,同样的问题,在修改代码后,请逐一审视
q=(CarNode *)malloc(sizeof(CarNode)); // 同样在下一句引起内存泄漏
q=T-> top;
++S-> top=q; //同样...参照上述S到T的注释
T-> top;
T-> top--;
}
}

//这里应该将t(便道车的第一辆)加入栈中
//并释放t及t-> data

else{//未找到
cout < < "\n没有找到该车! " < <endl;
return 1;
}

return 1;
}
// 这个函数还有一个问题,就是没有处理从便道出车的情况。因为要离开的车可能正在便道
// 上。并且为效率考量,这种情况应该在从栈出车之前就处理。

好了,主要就是这几点。

以上解释给LZ一个参考,细节方面可能有缺陷(因为没有从头到尾自己写一遍,并检查)。
重点在于:
1)内存分配的问题(一定要一一对应,分配出来的指针要对应的释放,绝对不能泄漏)。
2)栈和队列的用法还需强化,最好多学习一下别人写的栈类和队列类的代码,清楚其意义。


读书人网 >C++

热点推荐