Skip to content

Commit acb4753

Browse files
refactor: Improve readability and code clarity in InfixToPostfix (TheAlgorithms#6362)
refactor: improve InfixToPostfix Co-authored-by: Deniz Altunkapan <93663085+DenizAltunkapan@users.noreply.github.com>
1 parent 0a4f554 commit acb4753

File tree

2 files changed

+73
-31
lines changed

2 files changed

+73
-31
lines changed

src/main/java/com/thealgorithms/stacks/InfixToPostfix.java

Lines changed: 71 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,54 +4,96 @@
44
import java.util.regex.Matcher;
55
import java.util.regex.Pattern;
66

7+
/**
8+
* Utility class for converting an infix arithmetic expression
9+
* into its equivalent postfix (Reverse Polish Notation) form.
10+
* <p>
11+
* This class provides a static method to perform the conversion,
12+
* validating balanced brackets before processing.
13+
* </p>
14+
*/
715
public final class InfixToPostfix {
16+
817
private InfixToPostfix() {
918
}
1019

11-
public static String infix2PostFix(String infixExpression) throws Exception {
20+
/**
21+
* Converts a given infix expression string to a postfix expression string.
22+
* <p>
23+
* The method first checks if the brackets in the input expression are balanced
24+
* by calling {@code BalancedBrackets.isBalanced} on the filtered brackets.
25+
* If the brackets are not balanced, it throws an IllegalArgumentException.
26+
* </p>
27+
* <p>
28+
* Supported operators are: {@code +, -, *, /, ^}
29+
* and operands can be letters or digits.
30+
* </p>
31+
*
32+
* @param infixExpression the arithmetic expression in infix notation
33+
* @return the equivalent postfix notation expression
34+
* @throws IllegalArgumentException if the brackets in the expression are unbalanced
35+
*/
36+
public static String infix2PostFix(String infixExpression) {
1237
if (!BalancedBrackets.isBalanced(filterBrackets(infixExpression))) {
13-
throw new Exception("invalid expression");
38+
throw new IllegalArgumentException("Invalid expression: unbalanced brackets.");
1439
}
40+
1541
StringBuilder output = new StringBuilder();
16-
Stack<Character> stack = new Stack<>();
17-
for (char element : infixExpression.toCharArray()) {
18-
if (Character.isLetterOrDigit(element)) {
19-
output.append(element);
20-
} else if (element == '(') {
21-
stack.push(element);
22-
} else if (element == ')') {
23-
while (!stack.isEmpty() && stack.peek() != '(') {
24-
output.append(stack.pop());
42+
Stack<Character> operatorStack = new Stack<>();
43+
44+
for (char token : infixExpression.toCharArray()) {
45+
if (Character.isLetterOrDigit(token)) {
46+
// Append operands (letters or digits) directly to output
47+
output.append(token);
48+
} else if (token == '(') {
49+
// Push '(' to stack
50+
operatorStack.push(token);
51+
} else if (token == ')') {
52+
// Pop and append until '(' is found
53+
while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
54+
output.append(operatorStack.pop());
2555
}
26-
stack.pop();
56+
operatorStack.pop(); // Remove '(' from stack
2757
} else {
28-
while (!stack.isEmpty() && precedence(element) <= precedence(stack.peek())) {
29-
output.append(stack.pop());
58+
// Pop operators with higher or equal precedence and append them
59+
while (!operatorStack.isEmpty() && precedence(token) <= precedence(operatorStack.peek())) {
60+
output.append(operatorStack.pop());
3061
}
31-
stack.push(element);
62+
operatorStack.push(token);
3263
}
3364
}
34-
while (!stack.isEmpty()) {
35-
output.append(stack.pop());
65+
66+
// Pop any remaining operators
67+
while (!operatorStack.isEmpty()) {
68+
output.append(operatorStack.pop());
3669
}
70+
3771
return output.toString();
3872
}
3973

74+
/**
75+
* Returns the precedence level of the given operator.
76+
*
77+
* @param operator the operator character (e.g., '+', '-', '*', '/', '^')
78+
* @return the precedence value: higher means higher precedence,
79+
* or -1 if the character is not a recognized operator
80+
*/
4081
private static int precedence(char operator) {
41-
switch (operator) {
42-
case '+':
43-
case '-':
44-
return 0;
45-
case '*':
46-
case '/':
47-
return 1;
48-
case '^':
49-
return 2;
50-
default:
51-
return -1;
52-
}
82+
return switch (operator) {
83+
case '+', '-' -> 0;
84+
case '*', '/' -> 1;
85+
case '^' -> 2;
86+
default -> -1;
87+
};
5388
}
5489

90+
/**
91+
* Extracts only the bracket characters from the input string.
92+
* Supports parentheses (), curly braces {}, square brackets [], and angle brackets &lt;&gt;.
93+
*
94+
* @param input the original expression string
95+
* @return a string containing only bracket characters from the input
96+
*/
5597
private static String filterBrackets(String input) {
5698
Pattern pattern = Pattern.compile("[^(){}\\[\\]<>]");
5799
Matcher matcher = pattern.matcher(input);

src/test/java/com/thealgorithms/stacks/InfixToPostfixTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class InfixToPostfixTest {
1212

1313
@ParameterizedTest
1414
@MethodSource("provideValidExpressions")
15-
void testValidExpressions(String infix, String expectedPostfix) throws Exception {
15+
void testValidExpressions(String infix, String expectedPostfix) {
1616
assertEquals(expectedPostfix, InfixToPostfix.infix2PostFix(infix));
1717
}
1818

@@ -28,6 +28,6 @@ void testInvalidExpressions(String infix, String expectedMessage) {
2828
}
2929

3030
private static Stream<Arguments> provideInvalidExpressions() {
31-
return Stream.of(Arguments.of("((a+b)*c-d", "invalid expression"));
31+
return Stream.of(Arguments.of("((a+b)*c-d", "Invalid expression: unbalanced brackets."));
3232
}
3333
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy