Инфиксная и постфиксная нотации — два распространенных способа представления математических выражений. В то время как инфиксная нотация — это знакомая математическая нотация, которую мы используем в повседневной жизни (например, 2 + 3), постфиксная нотация, также известная как обратная польская нотация (RPN), представляет операторы после операндов (например, 2 3 +). В этой статье мы рассмотрим различные методы преобразования инфиксных выражений в постфиксные в Котлине. Итак, приступим!
Метод 1: использование стеков
Один из самых популярных подходов к преобразованию инфикса в постфикс — использование стека. Вот фрагмент кода, демонстрирующий реализацию:
fun infixToPostfix(expression: String): String {
val output = StringBuilder()
val stack = Stack<Char>()
val precedence = mapOf('+' to 1, '-' to 1, '*' to 2, '/' to 2, '^' to 3)
for (char in expression) {
when {
char.isLetterOrDigit() -> output.append(char)
char == '(' -> stack.push(char)
char == ')' -> {
while (!stack.isEmpty() && stack.peek() != '(') {
output.append(stack.pop())
}
stack.pop() // Discard '('
}
else -> {
while (!stack.isEmpty() && precedence[char]!! <= precedence[stack.peek()]!!) {
output.append(stack.pop())
}
stack.push(char)
}
}
}
while (!stack.isEmpty()) {
if (stack.peek() == '(') throw IllegalArgumentException("Invalid expression")
output.append(stack.pop())
}
return output.toString()
}
Метод 2: использование деревьев выражений
Другой подход к преобразованию инфикса в постфикс заключается в построении дерева выражений и последующем обходе его в постфиксном порядке. Вот реализация:
class Node(private val value: Char) {
var left: Node? = null
var right: Node? = null
}
fun infixToPostfix(expression: String): String {
val stack = Stack<Node>()
var root: Node? = null
for (char in expression) {
if (char.isLetterOrDigit()) {
val node = Node(char)
stack.push(node)
} else {
val right = stack.pop()
val left = stack.pop()
val node = Node(char)
node.left = left
node.right = right
stack.push(node)
}
}
root = stack.pop()
val output = StringBuilder()
traversePostorder(root, output)
return output.toString()
}
fun traversePostorder(node: Node?, output: StringBuilder) {
if (node != null) {
traversePostorder(node.left, output)
traversePostorder(node.right, output)
output.append(node.value)
}
}
Метод 3: алгоритм сортировочной станции
Алгоритм сортировочной станции — еще один популярный метод преобразования инфикса в постфикс. Вот фрагмент кода, демонстрирующий его реализацию:
fun infixToPostfix(expression: String): String {
val output = StringBuilder()
val stack = Stack<Char>()
val precedence = mapOf('+' to 1, '-' to 1, '*' to 2, '/' to 2, '^' to 3)
for (char in expression) {
when {
char.isLetterOrDigit() -> output.append(char)
char == '(' -> stack.push(char)
char == ')' -> {
while (!stack.isEmpty() && stack.peek() != '(') {
output.append(stack.pop())
}
stack.pop() // Discard '('
}
else -> {
while (!stack.isEmpty() && precedence[char]!! <= precedence[stack.peek()]!!) {
output.append(stack.pop())
}
stack.push(char)
}
}
}
while (!stack.isEmpty()) {
output.append(stack.pop())
}
return output.toString()
}
В этой статье мы рассмотрели три различных метода преобразования инфиксных выражений в постфиксные в Kotlin. Мы реализовали алгоритмы с использованием стеков, деревьев выражений и алгоритма сортировочной станции. Каждый метод имеет свои преимущества и может быть более подходящим в зависимости от требований вашего проекта. По мере того, как вы познакомитесь с этими приемами, вы сможете без особых усилий обрабатывать сложные выражения. Приятного кодирования!