инфиксная нотация — алгоритм маневрового двора в переполнении стека

Мне нужна функция, которая принимает инфиксную строку (например, «3 + 4 * 9») и преобразует ее в постфикс (например, «4 9 * 3 +»).

Я получил это работает, пока вы не добавите скобки в скобках. Я работал над этим весь день и не могу понять, что я делаю неправильно — может, кто-то со свежим умом это увидит? Я чувствую, что я действительно близко!

Спасибо! Вот код:

    string ExpressionManager::infixToPostfix(string infixExpression)
{
cout << "itop Testing : " << infixExpression << endl;
string posnums = "0123456789";
string posops = "+-*/%(){}[]";
string onlyops = "+-/%*";
string space = " ";
string openbra = "([{";
string closebra = ")]}";
stack <string> nums;
stack <string> ops;
string output = "";

//check to make sure expression is valid

if (!(isBalanced(infixExpression)))
{
cout << "Infix Expression isn't balanced!" << endl;
return "invalid";
}for (int i=0; i<infixExpression.size(); i++)
{
if ((posnums.find(infixExpression[i])!=string::npos) || (posops.find(infixExpression[i])!=string::npos) || (space.find(infixExpression[i])!=string::npos))
{}

else
{
cout << "Invalid character " << infixExpression[i] << " found." << endl;
return "invalid";
}
}int numcount = 0;
int opcount = 0;
//Numbers vs. Operators
for (int i = 0; i < infixExpression.size(); i++)
{
if (posnums.find(infixExpression[i]) != -1)
{

while(infixExpression[i] != ' ')
{
if (i == (infixExpression.size()-1))
break;
i++;
}
numcount++;
}

if (onlyops.find(infixExpression[i]) != -1)
{
opcount++;
}
}if (opcount == (numcount - 1))
{
}
else
{
cout << "Bad operators to numbers ratio!" << endl;
return "invalid";
}

//Get rid of proceeding whitespaces.
int safety = 0;
int net = infixExpression.size();

while (infixExpression[0] == ' ')
{
infixExpression.erase(0,1);
safety++;

if (safety>=net)
break;
}

//cout << "At this point, it is " << postfixExpression << endl;

//the fun part! Set up stacks

for (int i =0; i< infixExpression.size(); i++)
{
cout << "It gets hung up on character " << infixExpression[i] << endl;
if(openbra.find(infixExpression[i]) != -1)
{

string word = "";
word += infixExpression[i];
ops.push(word);

cout << "Pushing onto stack: " << word << endl;
}
else if(closebra.find(infixExpression[i]) != -1)
{
cout << "contents of remaining ops stack: "<< endl;
stack <string> temp;
temp = ops;
for (int j = 0; j < temp.size(); j++)
{
cout << "\t" << temp.top() << endl;
temp.pop();
}

while (openbra.find(ops.top()) == -1)
{output += " " + ops.top();
cout << "Pushing from stack: " << ops.top() << endl;
ops.pop();
}

cout << "Pushing from stack: " << ops.top() << endl;
ops.pop();

}

else if (posnums.find(infixExpression[i]) != -1)
{

string word = "";
while (infixExpression[i] != ' ')
{
word += infixExpression[i];
i++;
if (i== infixExpression.size())
break;
}
output += " " + word;

}

else if (onlyops.find(infixExpression[i]) != -1)
{

if (ops.size() == 0)
{
string word = "";
word += infixExpression[i];
ops.push(word);
}
else
{
int o1p = 0;
int o2p = 0;

if ((infixExpression[i] == '+') || (infixExpression[i] == '-'))
o1p = 0;
else
o1p = 1;

if ((ops.top() == "+") || (ops.top() == "-"))
o2p = 0;
else
o2p = 1;

while ((ops.size() > 0) && (o1p <= o2p))
{
output += " " + ops.top();
cout << "(odd) Pushing from stack: " << ops.top() << endl;

if ((ops.top() == "+") || (ops.top() == "-"))
o2p = 0;
else
o2p = 1;

if (ops.size() > 0)
{
ops.pop();
}
else
{
break;
}
}

string word = "";
word += infixExpression[i];
ops.push(word);
}
}

}

while (output[0] == ' ')
{
output.erase(0,1);
}

return output;
}

3

Решение

Я лично думаю, что вам нужно больше изучать алгоритм маневров

Потому что вы сказали, что вывод похож на «4 9 * 3 +», но то, что я прочитал об алгоритме и работе стека, должно быть (например, «9 4 * 3 +»)

Важная проблема заключается в том, что после классификации числа и операторов вытащите все из стека операторов и вставьте в стек номеров в соответствии с заданными условиями, для которых должен быть выдвинут оператор.

0

Другие решения

Я предлагаю вам перейти прямо на соответствующие страницы вики, которые описывают

  1. Алгоритм маневрового двора
  2. Обратная польская запись

Я реализовал алгоритм Shunting Yard как на Java, так и на C ++, и нашел страницы Wiki отличными и отличным источником помощи. Они достаточно подробны, чтобы позволить вам шаг за шагом реализовать алгоритм на любом языке программирования, который вы предпочитаете.

Еще одно предложение: ознакомьтесь с практическим использованием стеков и очередей, так как они используются повсеместно в этих алгоритмах.

Пожалуйста, посмотрите это запись в блоге для некоторых реализаций упомянутого алгоритма Shunting Yard на C ++ и Java.

Он также содержит дополнительный раздел (в процессе), если вы хотите включить другие математические операторы (sin, cos, log и т. Д.) И более сложные выражения и подвыражения.

0

Вот является (последняя версия) решением. На каком-то этапе он использует алгоритм маневрового двора Дейкстры (в конце traverse() функция-член output_ член содержит форму обратной польской записи input_ выражение, если мы пройдем его правильно).

0
По вопросам рекламы [email protected]