Skip to content

Add PrefixToInfix.java new algorithm #5552

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 4, 2024
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,7 @@
* [NextGreaterElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextGreaterElement.java)
* [NextSmallerElement](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/NextSmallerElement.java)
* [PostfixToInfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/PostfixToInfix.java)
* [PrefixToInfix](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/PrefixToInfix.java)
* [StackPostfixNotation](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/stacks/StackPostfixNotation.java)
* strings
* [AhoCorasick](https://github.com/TheAlgorithms/Java/blob/master/src/main/java/com/thealgorithms/strings/AhoCorasick.java)
Expand Down Expand Up @@ -984,6 +985,7 @@
* [NextGreaterElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/NextGreaterElementTest.java)
* [NextSmallerElementTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/NextSmallerElementTest.java)
* [PostfixToInfixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/PostfixToInfixTest.java)
* [PrefixToInfixTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/PrefixToInfixTest.java)
* [StackPostfixNotationTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/stacks/StackPostfixNotationTest.java)
* strings
* [AhoCorasickTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/strings/AhoCorasickTest.java)
Expand Down
69 changes: 69 additions & 0 deletions src/main/java/com/thealgorithms/stacks/PrefixToInfix.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.thealgorithms.stacks;

import java.util.Stack;

/**
* Converts a prefix expression to an infix expression using a stack.
*
* The input prefix expression should consist of
* valid operands (letters or digits) and operators (+, -, *, /, ^).
* Parentheses are not required in the prefix string.
*/
public final class PrefixToInfix {
private PrefixToInfix() {
}

/**
* Determines if a given character is a valid arithmetic operator.
*
* @param token the character to check
* @return true if the character is an operator, false otherwise
*/
public static boolean isOperator(char token) {
return token == '+' || token == '-' || token == '/' || token == '*' || token == '^';
}

/**
* Converts a valid prefix expression to an infix expression.
*
* @param prefix the prefix expression to convert
* @return the equivalent infix expression
* @throws NullPointerException if the prefix expression is null
*/
public static String getPrefixToInfix(String prefix) {
if (prefix == null) {
throw new NullPointerException("Null prefix expression");
}
if (prefix.isEmpty()) {
return "";
}

Stack<String> stack = new Stack<>();

// Iterate over the prefix expression from right to left
for (int i = prefix.length() - 1; i >= 0; i--) {
char token = prefix.charAt(i);

if (isOperator(token)) {
// Pop two operands from stack
String operandA = stack.pop();
String operandB = stack.pop();

// Form the infix expression with parentheses
String infix = "(" + operandA + token + operandB + ")";

// Push the resulting infix expression back onto the stack
stack.push(infix);
} else {
// Push operand onto stack
stack.push(Character.toString(token));
}
}

if (stack.size() != 1) {
throw new ArithmeticException("Malformed prefix expression");
}

return stack.pop(); // final element on the stack is the full infix expression
}
}
44 changes: 44 additions & 0 deletions src/test/java/com/thealgorithms/stacks/PrefixToInfixTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.thealgorithms.stacks;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.stream.Stream;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

class PrefixToInfixTest {

@ParameterizedTest
@MethodSource("provideValidPrefixToInfixTestCases")
void testValidPrefixToInfixConversion(String prefix, String expectedInfix) {
assertEquals(expectedInfix, PrefixToInfix.getPrefixToInfix(prefix));
}

static Stream<Arguments> provideValidPrefixToInfixTestCases() {
return Stream.of(Arguments.of("A", "A"), // Single operand
Arguments.of("+AB", "(A+B)"), // Addition
Arguments.of("*+ABC", "((A+B)*C)"), // Addition and multiplication
Arguments.of("-+A*BCD", "((A+(B*C))-D)"), // Mixed operators
Arguments.of("/-A*BC+DE", "((A-(B*C))/(D+E))"), // Mixed operators
Arguments.of("^+AB*CD", "((A+B)^(C*D))") // Mixed operators
);
}

@Test
void testEmptyPrefixExpression() {
assertEquals("", PrefixToInfix.getPrefixToInfix(""));
}

@Test
void testNullPrefixExpression() {
assertThrows(NullPointerException.class, () -> PrefixToInfix.getPrefixToInfix(null));
}

@Test
void testMalformedPrefixExpression() {
assertThrows(ArithmeticException.class, () -> PrefixToInfix.getPrefixToInfix("+ABC"));
}
}