选择题:
2-1线性表、堆栈、队列的主要区别是什么?(1分)
- 线性表用指针,堆栈和队列用数组
- 堆栈和队列都是插入、删除受到约束的线性表
- 线性表和队列都可以用循环链表实现,但堆栈不能
- 堆栈和队列都不是线性结构,而线性表是
解析:根据定义可以很简单的选出第二个是正确的。
编程题:
7-2 符号配对 (20 分)
请编写程序检查C语言源程序中下列符号是否配对:/*
与*/
、(
与)
、[
与]
、{
与}
。
输入格式:
输入为一个C语言源程序。当读到某一行中只有一个句点.
和一个回车的时候,标志着输入结束。程序中需要检查配对的符号不超过100个。
输出格式:
首先,如果所有符号配对正确,则在第一行中输出YES
,否则输出NO
。然后在第二行中指出第一个不配对的符号:如果缺少左符号,则输出?-右符号
;如果缺少右符号,则输出左符号-?
。
输入样例1:
void test()
{
int i, A[10];
for (i=0; i<10; i++) /*/
A[i] = i;
}
.
输出样例1:
NO
/*-?
输入样例2:
void test()
{
int i, A[10];
for (i=0; i<10; i++) /**/
A[i] = i;
}]
.
输出样例2:
NO
?-]
输入样例3:
void test()
{
int i
double A[10];
for (i=0; i<10; i++) /**/
A[i] = 0.1*i;
}
.
输出样例3:
YES
解析:简单的括号匹配,显然用栈,栈当中存储左边的括号,然后当遇上有括号之后与栈顶的元素进行检查知否匹配即可。
AC代码:
#include <bits/stdc++.h>
using namespace std;
const int ERRORS = -100;
int getcharid(string s)
{
if(s == "/*")
return -1;
if(s == "*/")
return 1;
if(s == "(")
return -2;
if(s == ")")
return 2;
if(s == "[")
return -3;
if(s == "]")
return 3;
if(s == "{")
return -4;
if(s == "}")
return 4;
return ERRORS;
}
string getstring(int id)
{
if(id == -1)
return "/*";
if(id == 1)
return "*/";
if(id == -2)
return "(";
if(id == 2)
return ")";
if(id == -3)
return "[";
if(id == 3)
return "]";
if(id == -4)
return "{";
if(id == 4)
return "}";
}
int main()
{
string s, ans = "";
stack<int> ch;
bool flag = true;
while(getline(cin, s))
{
if(s == ".")
break;
if(ans != "")
continue;
for(int i = 0; i < s.length(); i++)
{
int id;
string temp = "";
temp += s[i];
if(s[i] == '/' || s[i] == '*')
{
if(i == s.length() - 1)
continue;
if(s[i] == '*' && s[i + 1] != '/')
continue;
if(s[i] == '/' && s[i + 1] != '*')
continue;
temp += s[i + 1];
id = getcharid(temp);
if(id == ERRORS)
continue;
else if(id < 0)
ch.push(id);
else if(id > 0)
{
if(ch.empty())
{
ans = temp;
break;
}
if(ch.top() + id == 0)
ch.pop();
else
{
ans = getstring(ch.top());
break;
}
}
i++;
}
else
{
id = getcharid(temp);
if(id == ERRORS)
continue;
if(id < 0)
ch.push(id);
else
{
if(ch.empty())
{
ans = temp;
break;
}
if(ch.top() + id == 0)
ch.pop();
else
{
ans = getstring(ch.top());
break;
}
}
}
}
}
if(ans != "")
{
cout << "NO" << endl;
int id = getcharid(ans);
if(id < 0)
cout << ans << "-?" << endl;
else
cout << "?-" << ans << endl;
}
else
{
if(!ch.empty())
{
cout << "NO" << endl;
cout << getstring(ch.top()) << "-?" << endl;
}
else
cout << "YES" << endl;
}
return 0;
}
7-1 表达式转换 (25 分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+
、-
、*
、\
以及左右括号()
,表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
解析:这也是栈的应用当中的表达式求值,就是将中缀表达式转化为后缀表达式。
我们首先对表达式当中的所有运算负号进行优先级的编号,在栈当中的运算符号是优先级非递减的,也就是当运算符的优先级高于或者是等于栈顶的运算符的优先级或者是这个运算符是左括号我们就将该运算符入栈,如果遇到有括号就将栈当中的运算符出栈,直到遇到左括号为止,如果运算符的优先级比栈顶元素的低,我们就将栈当中运算符出栈直到栈顶的运算符小于该运算符或者是栈为空,然后将该运算符入栈。
AC代码:
#include <bits/stdc++.h>
using namespace std;
bool ischars(char x)
{
return (x == '+' || x == '-');
}
int getprior(char x)
{
if(x == '(')
return 1;
else if(x == '+' || x == '-')
return 2;
else if(x == '/' || x == '*')
return 3;
else if(x == ')')
return 4;
}
bool flag = false;
string s;
int main()
{
stack<char> oper;
cin >> s;
for(int i = 0; i < s.length(); i++)
{
if(isdigit(s[i]))
{
if(!i)
{
cout << s[i];
flag = true;
}
else if(isdigit(s[i - 1]) || s[i - 1] == '.')
cout << s[i];
else
{
if(flag)
cout << " ";
cout << s[i];
flag = true;
}
}
else if(s[i] == '.')
cout << s[i];
else
{
if(ischars(s[i]) && (!i || (!isdigit(s[i - 1]) && s[i - 1] != ')')))
{
if(s[i] == '-' && flag)
cout << " " << s[i];
else if(s[i] == '-' && !flag)
cout << s[i];
}
else if(oper.empty() || s[i] == '(')
oper.push(s[i]);
else if(s[i] == ')')
{
while(!oper.empty() && oper.top() != '(')
{
cout << " " << oper.top();
oper.pop();
}
oper.pop();
}
else if(getprior(s[i]) >= getprior(oper.top()))
oper.push(s[i]);
else if(getprior(s[i]) < getprior(oper.top()))
{
//cout << "||" << endl;
while(!oper.empty() && getprior(oper.top()) >= getprior(s[i]))
{
cout << " " << oper.top();
oper.pop();
}
oper.push(s[i]);
}
}
}
while(!oper.empty())
{
cout << " " << oper.top();
oper.pop();
}
cout << endl;
return 0;
}
注意:这个题当中存在单目运算符,也就是-100,这样的数前面的负号,并且会出现小数或者是多位数。