数据结构——栈的应用
1.就近匹配
规则如下:
- 如果是左括号,则入栈;
- 如果是右括号,若栈顶元素是其对应的左括号,则退栈,若不是对应的左括号,则结论为括号不匹配;
- 当表达式结束后,若栈为空,则表明表达式中括号匹配;否则表明表达式中括号不匹配。
#include"linkstrack.cpp"
#include<string>
int match(string &str )
{
LinkStrack<char> ls;
for (int i = 0; i < str.size(); i++)
{
switch (str[i])
{
case '(':
ls.push_linkstrack(str[i]);
break;
case ')':
if (ls.size == 0 || ls.GetTop_linkstrack() != '(')
{
return -1;
}
ls.pop_linkstrack();
break;
case '{':
ls.push_linkstrack(str[i]);
break;
case '}':
if (ls.size == 0 || ls.GetTop_linkstrack() != '{')
{
return -1;
}
ls.pop_linkstrack();
break;
case '[':
ls.push_linkstrack(str[i]);
break;
case ']':
if (ls.size == 0 || ls.GetTop_linkstrack() != '[')
{
return -1;
}
ls.pop_linkstrack();
break;
default:
break;
}
}
if (ls.GetTop_linkstrack() == NULL)
{
return 1;
}
}
int main()
{
string str = { "(){[()][]}[()]" };
int flag=match(str);
if (flag==1)
{
cout << "完美匹配" << endl;
}
if (flag==-1)
{
cout << "不能完全匹配" << endl;
}
system("pause");
return 0;
}
/*---------------单括号------------------*/
//string str = { "2+6*((1+3))-4*(5-2))" };
//LinkStrack<char> ls;
//for (int i = 0; i < str.size(); i++)
//{
// if (str[i] == '(')
// {
// ls.push_linkstrack(str[i]);
// }
// if (str[i] == ')')
// {
// if (ls.GetTop_linkstrack() == '(')
// {
// ls.pop_linkstrack();
// }
// else
// {
// ls.push_linkstrack(str[i]);
// break;
// }
// }
//}
//if (ls.GetTop_linkstrack() == NULL)
//{
// cout << "完美匹配" << endl;
//}
//else
//{
// cout << "不能完全匹配" << endl;
//}
2.中缀转后缀
规则如下:
- 若是’(’,则入栈
- 若是操作数,则将其输出
- 若是操作符,若其优先级比栈顶元素优先级高,则入栈;否则,栈顶元素退栈输出,再与新的栈顶元素进行比较,重复此步骤
- 若是’)’,将栈中元素依次输出知道碰到’(’,然后退栈,消除一对括号
- 当遇到‘=’,开始退栈输出,直到空
#include"linkstrack.cpp"
#include<string>
int text(char c)
{
if (c=='*'||c=='/')
{
return 2;
}
else if(c=='+'||c=='-')
{
return 1;
}
else if(c == '(')
{
return 0;
}
}
void work(string &str)
{
LinkStrack<char> ls;
for (int i = 0; i < str.size(); i++)
{
if (str[i]>='0'&&str[i]<='9'||str[i]=='.')
{
cout << str[i];
}
else if (str[i]=='(')
{
ls.push_linkstrack(str[i]);
}
else if(str[i]=='*'|| str[i] == '/' || str[i] == '+' || str[i] == '-')
{
if (text(str[i])>text(ls.GetTop_linkstrack())||ls.size==0)
{
cout << " ";
ls.push_linkstrack(str[i]);
}
else
{
cout <<" "<< ls.GetTop_linkstrack();
ls.pop_linkstrack();
ls.push_linkstrack(str[i]);
cout << " ";
}
}
else if(str[i] == ')')
{
while (ls.GetTop_linkstrack()!='(')
{
cout << " " << ls.GetTop_linkstrack();
ls.pop_linkstrack();
}
ls.pop_linkstrack();
}
if (str[i] == '=')
{
while (ls.size != 0)
{
cout << " " << ls.GetTop_linkstrack();
ls.pop_linkstrack();
cout << " ";
}
}
}
}
int main()
{
string str = {"12*(6/2-0.5)="};
work(str);
system("pause");
return 0;
}
3.后缀求值
规则如下:
- 若读到操作数,则入栈
- 若是读到运算符,则将栈顶两个元素弹出,后弹出的操作数为被操作数,先弹出的为操作数,将操作的结果入栈
- 若读到空格,则跳过它
- 表达式扫描完毕,栈中剩一个 数,即表达式的结果值。
#include"linkstrack.cpp"
#include<string>
double computer(double &a, double &b,char &c)
{
switch (c)
{
case '+':
return a + b; break;
case '-':
return a - b; break;
case '*':
return a * b; break;
case '/':
return a / b; break;
default:
break;
}
}
//void work0(string &str)
//{
// LinkStrack<int> ls;
// for (int i = 0; i < str.size(); i++)
// {
// if (str[i]>='0'&&str[i]<'10')
// {
// int temp = str[i] - '0';
// ls.push_linkstrack(temp);
// }
// else if(str[i] == '*' || str[i] == '/' || str[i] == '+' || str[i] == '-')
// {
// int a = ls.GetTop_linkstrack();
// ls.pop_linkstrack();
// int b = ls.GetTop_linkstrack();
// ls.pop_linkstrack();
// int result = computer(b,a,str[i]);
// ls.push_linkstrack(result);
// }
// }
// cout << ls.GetTop_linkstrack() << endl;
//}
double spellnum(string &str,int &i)
{
double num1=0,num2=0,num;
int j = 0;
while (str[i]>='0'&&str[i]<'10')
{
num1 = num1 * 10 + str[i++] - '0';
}
if (str[i]=='.')
{
i++;
while (str[i] >= '0'&&str[i] < '10')
{
num2 += (str[i++] - '0')*1.0 / pow(10.0, ++j);
}
}
return num=num1+num2;
}
void work2(string &str)
{
LinkStrack<double> ls;
for (int i = 0; i < str.size(); i++)
{
if (str[i] >= '0'&&str[i] < '10')
{
double top = spellnum(str, i);
ls.push_linkstrack(top);
}
else if (str[i] == '*' || str[i] == '/' || str[i] == '+' || str[i] == '-')
{
double a = ls.GetTop_linkstrack();
ls.pop_linkstrack();
double b = ls.GetTop_linkstrack();
ls.pop_linkstrack();
double result = computer(b, a, str[i]);
ls.push_linkstrack(result);
}
}
cout << ls.GetTop_linkstrack() << endl;
}
int main()
{
string str = { "12 6 2 / 0.5 - *" };
//work1(str);一位数
work2(str);//多位数并包含小数点
system("pause");
return 0;
}
操作数的拼数为重点