通过第三章【栈与队列】的学习,我掌握了对两种特殊线性表—栈与队列的
一系列操作方法。栈的特点是后进后出,队列的特点是后进先出。这两种操作受
限的线性表在帮助我们解决特定的问题时能带来相当大的便利。
本章的作业一是pta上的括号匹配编程题,题目要求我们对一串输入的字符
串进行扫描判断该串字符中的括号是否匹配。再学完栈之后,我第一个想到的便
是利用栈后出后进的特点对字符串中的括号进行操作。
这是我最先写出的算法版本:
int main() { SqStack S; InitStack(S); char ch; char x; cin.get(ch); while(ch!='\n') { switch (ch) { case'{': Push(S, ch); break; //将左括号压入栈 case'[': Push(S, ch); break; case'(': Push(S, ch); break; case'}': if (!StackEmpty(S) && GetTop(S) == '{') Pop(S, x); //正确匹配栈顶元素 break; case']': if (!StackEmpty(S) && GetTop(S) == '[') Pop(S, x); //正确匹配栈顶元素 break; case')': if (!StackEmpty(S) && GetTop(S) == '(') Pop(S, x); //正确匹配栈顶元素 break; } } if (StackEmpty(S) ) //判断栈是否为空且是否出现错误匹配 cout << "yes"; else cout << "no"; return 0; }
在vs中初步运行后,输入几个样例进行验证,结果正确。
但是提交到pta上,出现了运行超时的问题(五个样例全部超时)。介于上一章
所学的教训,我再次将目光放回主函数,试图对算法进行简化提高效率。经过一系
列演算并参考书本例题后,我对算法进行了修改,加入了初始标识值flag=1,当swtich
循环中出现括号不匹配的情况,直接将flag赋值为0并直接结束while循环。
更改后的算法:
int main() { int flag=1;//设置匹配结果初始值为1 SqStack S; InitStack(S); char ch; char x; cin.get(ch); while(ch!='\n'&&flag) { switch (ch) { case'{': Push(S, ch); break; //将左括号压入栈 case'[': Push(S, ch); break; case'(': Push(S, ch); break; case'}': if (!StackEmpty(S) && GetTop(S) == '{') Pop(S, x); //正确匹配栈顶元素 else flag = 0; //错误匹配 break; case']': if (!StackEmpty(S) && GetTop(S) == '[') Pop(S, x); //正确匹配栈顶元素 else flag = 0; //错误匹配 break; case')': if (!StackEmpty(S) && GetTop(S) == '(') Pop(S, x); //正确匹配栈顶元素 else flag = 0; //错误匹配 break; } } if (StackEmpty(S)&&flag ) //判断栈是否为空且是否出现错误匹配 cout << "yes"; else cout << "no"; return 0; }
对算法进行优化后,提交到pta上后,发现五个样例中只有两个正确,另外两个是运行超时和
答案错误。在一句一句检查了n次以后仍没有发现错误在哪,最后有点烦躁将这个题目晾了几天。
之后在与舍友的交流中,舍友告诉我他了解到运用cin.get读取单个元素会造成超时的问题,于
是将cin.get换成了cin.getline,用一个数组接受输入的字符串,对循环语句等稍作改动后,终于过
了验证。
修改成cin.getline之后的算法:
int main() { int flag = 1;//设置匹配结果初始值为1 SqStack S; InitStack(S); char ch[MAXSIZE]; char x; cin.getline(ch, MAXSIZE); for (int i=0;i<MAXSIZE&&flag;i++) { switch (ch[i]) { case'{': Push(S, ch[i]); break; //将左括号压入栈 case'[': Push(S, ch[i]); break; case'(': Push(S, ch[i]); break; case'}': if (!StackEmpty(S) && GetTop(S) == '{') Pop(S, x); //正确匹配栈顶元素 else flag = 0; //错误匹配 break; case']': if (!StackEmpty(S) && GetTop(S) == '[') Pop(S, x); //正确匹配栈顶元素 else flag = 0; //错误匹配 break; case')': if (!StackEmpty(S) && GetTop(S) == '(') Pop(S, x); //正确匹配栈顶元素 else flag = 0; //错误匹配 break; } } if (StackEmpty(S) && flag) //判断栈是否为空且是否出现错误匹配 cout << "yes"; else cout << "no"; return 0; }
总的来说这次我的算法没出现多少错误,而是在cin.get函数上吃了亏。下次进行编程时
要时刻注意,减少cin.get的使用。
至于pta上的第二题则较为简单,对题目条件进行分析以后就是对一串整数数组进行操作,
让其按照输入的先后顺序,输出两个奇数再输出一个偶数,直至用完所有读取的元素。针对该
题,我建立了两个队列分别用于接受奇数与偶数,最后再按顺序输出即可。
算法如下:
int main() { LinkQueue Q1,Q2;//建立两个队列Q1(奇数队) Q2(偶数队) InitQueue(Q1);//初始化队列 InitQueue(Q2); int n, x; cin >> n;//输入元素个数 for (int i = 0; i < n; i++) { cin >> x; if (x % 2 == 0) //将奇数插入到Q1队尾 Enqueue(Q2, x); else Enqueue(Q1, x);//将偶数插入到Q2队尾 } while (!QueueEmpty(Q1) || !QueueEmpty(Q2))//判断队列Q1、Q2是否为空 { for (int j = 0; j < 2 && !QueueEmpty(Q1); j++)//先判断Q1是否为空,再移出Q1的两个元素 { DeQueue(Q1, x); cout << x; if (!QueueEmpty(Q1) || !QueueEmpty(Q2))//根据Q1、Q2是否为空判断是否为最后一项 cout << " "; } if (!QueueEmpty(Q2)) { //执行Q1的出队后再执行Q2的队头元素出队 DeQueue(Q2, x); cout << x; if (!QueueEmpty(Q1) || !QueueEmpty(Q2))//根据Q1、Q2是否为空判断是否为最后一项 cout << " "; } } return 0; }