Cómo escribir una calculadora de cuerdas con elegancia (JAVA)

Calculadora de cuerdas

Coordenadas 2020-4-24
pase-Huawei dos lados El
entrevistador dio una imagen dinámica y me preguntó: ¿Puedes escribir una simple calculadora de cuerdas en veinte minutos?
Piensa un poco: debería estar bien.
Luego, en la confusión de pensar, quiero usar la recursividad, pero también quiero usar la pila. Finalmente, escribí una calculadora con innumerables anomalías de puntero nulo. Después del final, aprendí del dolor y hoy te enseñaré a escribir una calculadora de cuerdas.

Primero, debemos necesitar una función para determinar si un carácter es un número,

 public static boolean isNum(char x){
    
    
        return x>=48 && x<=57;
    }//利用ascall码判断是否为数字

Con él, pasamos al segundo paso, diseñando ideas de algoritmos.
En cuanto a la idea de resolución de problemas de la calculadora de cadenas, solo vi una en Internet, que consiste en usar la expresión infija en polaco para convertir a un sufijo y luego calcular uno por uno. En el proceso de mi entrevista, mi primera reacción fue usar la recursividad para reducir todos los paréntesis, y luego calcular en el orden de multiplicación y división seguido de suma y resta.Hoy mejoraremos ambas ideas.

Idea 1: Expresión polaca
Primero, miramos la siguiente expresión 2 + 3 * (6-2). Esta expresión, que es la expresión que ingresamos, es la expresión infijo en polaco. La convertimos en una expresión de sufijo para obtener Debería ser 2 3 6 2- * +
¿Qué regla encontraste? Eso es poner el operador después del número en el orden de operación. Cuando calculamos, solo necesitamos una pila para ayudar, y podemos calcular el resultado en orden. Arriba.
Algunos amigos dijeron, entiendo la idea, ¿cómo escribirla? Déjame hablar despacio.

El primer paso, necesitamos algunas herramientas auxiliares,
1. Cadena

StringBuilder stringBuilder = new StringBuilder();

Utilice StringBuilder para almacenar la expresión de sufijo convertida.

2. Apilar

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

Usamos la pila para ayudar al almacenamiento.

3. La forma de carácter de la expresión original

char x[] = str.toCharArray();

Convertimos la cadena pasada a la función en una matriz de caracteres, por lo que es conveniente usar la función isNum para juzgar

Entonces ahora la función se ve así

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        retrun null;
        }

A continuación, recorremos toda la matriz de caracteres.

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    

        }
        retrun null;
        }

Ahora piénselo, ¿qué debemos hacer cuando recorremos la matriz?
Hay varias situaciones:
1. El carácter actual es un número
2. El carácter actual es un operador
3. El carácter actual es un corchete

En el caso 1, solo necesitamos agregarlo al resultado, porque en nuestra expresión de sufijo final, los números están ordenados en el orden original.

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
     //该字符为数字,直接加入结果
                stringBuilder.append(x[i]);
                continue;
            }
        }
        retrun null;
        }

Algunos estudiantes dijeron: ¿Qué pasa si hay varios dígitos? Hacemos algunas mejoras

 public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for(int i=0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
     //该字符为数字,直接加入结果
                stringBuilder.append(x[i]);
                if ((i<x.length-1&&!isNum(x[i+1]))||i==x.length-1)){
    
    
                    stringBuilder.append(" ");
                }
                continue;
            }
        }
        retrun null;
        }

En este paso, agregamos el número al resultado y hacemos un juicio. Si el carácter actual ya es el último carácter, agregamos un espacio después de él, o, el siguiente carácter del carácter actual no es un número, entonces también lo agregamos Agrega un espacio después.

En los casos 2 y 3
, la prioridad del símbolo / es mayor que ± durante la operación , por lo que procesamos / primero , y cuando encontramos * /, lo colocamos en la pila auxiliar

 if (x[i]=='*'||x[i]=='/'){
    
    
                stack.push(x[i]);
                continue;
            }

Los paréntesis tienen mayor prioridad que la multiplicación y la división, ¿qué debo hacer?
Teniendo en cuenta las características de la pila, debemos ingresar a la pila cuando nos encontramos con el paréntesis izquierdo, y por el momento pensar que están al mismo nivel que la multiplicación y la división, de la siguiente manera

 if (x[i]=='*'||x[i]=='/'||x[i]=='('){
    
    
                stack.push(x[i]);
                continue;
            }

Después de encontrar el paréntesis izquierdo, seguimos realizando las operaciones lógicas originales hasta que encontremos un paréntesis derecho, que es la regla de coincidencia de paréntesis. En
este momento, debemos operar en la pila y recorrer la pila hasta encontrar el paréntesis derecho correspondiente. Abriendo paréntesis, hemos completado una conversión dentro del paréntesis,

if (x[i]==')'){
    
    
                while (!stack.isEmpty()){
    
    
                    if (stack.peek()=='('){
    
    
                        stack.pop();
                        continue;
                    }
                    stringBuilder.append(stack.pop());
                }
                continue;
            }

Algunos estudiantes pueden pensar que no es muy vívido, simulemos el contenido de la pila,
(3 + 4) antes del paréntesis de cierre,
el contenido de la pila es (+
y el contenido de la cadena es 3 4
luego, después de que sacamos la pila, el contenido de la cadena El contenido se convierte en 3 4 +
y no hay operador entre paréntesis en la pila.
En este momento, hemos completado una conversión de sufijo entre paréntesis.

En este momento, la barra está bien (tachada) -los estudiantes dijeron nuevamente, ¿qué pasa con la suma y la resta?
Cuando nos encontramos con sumas y restas, tenemos que considerar varias situaciones
1. La pila actual está vacía y el símbolo se coloca directamente en la pila
2. La pila actual no está vacía, y el elemento superior de la pila es (, lo que indica que ± es el operador entre paréntesis, nosotros También directamente en la pila,
3. La pila actual no está vacía, el elemento superior de la pila no está (, lo que indica que ± puede estar entre paréntesis, pero el orden de operación actual ± debe colocarse detrás del elemento superior de la pila, después de que sacamos la pila, luego ± poner en la pila

if (x[i]=='+'||x[i]=='-'){
    
    
               while (!stack.isEmpty()&&stack.peek()!='('){
    
    
                   stringBuilder.append(stack.pop());
               }
               stack.push(x[i]);
               continue;
            }

Finalmente, agregamos la declaración de retorno para obtener la expresión de sufijo

return stringBuilder.toString();

La función completa es la siguiente

public static String inorder (String str){
    
    
        Stack<Character> stack = new Stack<>();
        char x[] = str.toCharArray();
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0;i<x.length;i++){
    
    
            if (isNum(x[i])) {
    
    
                stringBuilder.append(x[i]);
                if (((i<x.length-1&&!isNum(x[i+1]))||i==x.length-1)){
    
    
                    stringBuilder.append(" ");
                }
                continue;
            }
            if (x[i]=='*'||x[i]=='('||x[i]=='/'){
    
    
                stack.push(x[i]);
                continue;
            }
            if (x[i]==')'){
    
    
                while (!stack.isEmpty()){
    
    
                    if (stack.peek()=='('){
    
    
                        stack.pop();
                        continue;
                    }
                    stringBuilder.append(stack.pop());
                }
                continue;
            }
            if (x[i]=='+'||x[i]=='-'){
    
    
               while (!stack.isEmpty()&&stack.peek()!='('){
    
    
                   stringBuilder.append(stack.pop());
               }
               stack.push(x[i]);
               continue;
            }

        }
        return stringBuilder.toString();
    }

El siguiente paso es calcular el resultado de la expresión del sufijo. Este paso es muy simple. No lo explicaremos. Solo necesitamos empujar el número en la pila, sacar la pila cuando nos encontramos con el operador y empujar la pila nuevamente después de obtener el resultado del cálculo.
Nota / y-Necesita invertir el orden de los dos números extraídos de la pila para calcular el resultado correcto

public static Integer help(String str){
    
    
        Stack<Integer> num = new Stack<>();
        StringBuilder stringBuilder = new StringBuilder();
        char x[] = str.toCharArray();
        for (int i =0;i<x.length;i++){
    
    
            if (isNum(x[i])){
    
    
                stringBuilder.append(x[i]);
                if (i+1==x.length){
    
    
                    num.push(Integer.parseInt(stringBuilder.toString()));
                }
                if (x[i+1]==' '){
    
    
                    num.push(Integer.parseInt(stringBuilder.toString()));
                    stringBuilder.delete(0,stringBuilder.length());
                    continue;
                }
            }
            if (x[i]=='+'){
    
    
                num.push(num.pop()+num.pop());
            }
            if (x[i]=='-'){
    
    
                int a = num.pop();
                int b = num.pop();
                num.push(b-a);
            }
            if (x[i]=='*'){
    
    
                num.push(num.pop()*num.pop());
            }
            if (x[i]=='/'){
    
    
                int a = num.pop();
                int b = num.pop();
                num.push(b/a);
            }
        }
        return num.pop();
    }

De esta forma, llamamos a dos funciones en la función principal para obtener el resultado final del cálculo.

Vea el segundo artículo para la recursividad.

Supongo que te gusta

Origin blog.csdn.net/qq_45789385/article/details/105733553
Recomendado
Clasificación