java 后缀算法的中缀,我编写的while语句在应该调用时没有被调用

alen0pnh  于 2023-01-04  发布在  Java
关注(0)|答案(2)|浏览(132)
private Scanner sc = new Scanner(System.in);
private String expression;
private String exp[];
private ArrayList<String> post_fix = new ArrayList<>();
Stack<String> ope = new Stack<String>();
    public Model()
    {
        expression = sc.nextLine();
        
    }
    
    public void split()
    {
        
        //splitting the entered expression to array of operators alone and array of the numbers then create Arraylist to combine the operators and numbers together as if it is a string expression  but as an array
        String num[]= this.expression.split("[/+/*/-]");
        String preop[]= this.expression.split("[0-9]+");; // this will give [empty, operator, operator...] therefore we will create another array to fill in the ops excluding empty
        
        ArrayList<String> op = new ArrayList<>();//I used arraylist because easier
        for(int i = 1; i<preop.length;i++)
        {
            op.add(preop[i]);
        }
        
        //putting the operands and the operators together in the same array
                
        ArrayList<String> exp = new ArrayList<>();
       
        
        for(int i = 0; i <num.length;i++)
        {
            exp.add(num[i]);
        }
        int count = 0;
        for(int i = 0; i <op.size();i++)
        { //fill the arraylist with numbers then add the operators to it by using number (index of the operator +1 +count)
            exp.add(i+1+count, op.get(i)); //This is why arraylist was used in order to let values to be placed in between 
            count++;
            //i+1+count is used because index of the operator is in between two numbers meaning it is after the first index in num array so i+1 and because array keeps increasing, we do +count for the other operators to be placed in
        }
        
        this.exp = new String[exp.size()]; // we change the arraylist exp to instance array for faster operations later on
        System.out.print("Test to check if expression is converted into array as intented: ");
        for(int i = 0; i<this.exp.length;i++)
        {
            this.exp[i] = exp.get(i);
            System.out.print(this.exp[i]);
        }
        System.out.println();
      
    }
    
    public void postfix()
    {
    
        for(int i = 0; i < exp.length; i++)
        {
            if(i%2 == 0)//since operands are observed to always have even index in the array
            {
                post_fix.add(exp[i]);
                System.out.println(post_fix);
            }
            else 
            {
                boolean x = !ope.empty();
                System.out.println("Test of !ope.empty: " + x);
                while(!ope.empty()&& HasHigherPrecedence(ope.peek(), this.exp[i]))
                {
                    post_fix.add(ope.peek());
                    ope.pop();
                    
                    
                }
                ope.push(exp[i]);
                System.out.println("stack_top: "+ ope.peek());
            }
            
    
        }
        while(!ope.empty())
        {
            
            post_fix.add(ope.peek());
            ope.pop();
        }
        System.out.println("Output: " +post_fix);
    
        
    }
    
    public String getPost_fix()
    {
        String temp = "";
        for(int i =0; i < exp.length;i++)
        {
            temp = temp + post_fix.get(i);
        }
    
        return temp;
    }
    
    public double evaluate() 
    {
        return 0;
    }
    
    private boolean HasHigherPrecedence(String op1, String op2)
    {
        //op1 is operator 1 at the top of the stack thus associativity highest
        int a_op1 = 1;
        int a_op2 = 0;
        
        int p_op1 = 0;
        int p_op2= 0;
        //the precedence will be measured with numbers
        String operators[]= {"","+","-","*","/"};
        int precedence[] = {0,1,1,2,2}; //the reason for blank operator and 0 precedence is because the stack initially will be empty
        for(int i = 0; i< operators.length;i++)
        {
            if(op1.equals(operators[i]))
            {
                p_op1=precedence[i];
            }
        }
        for(int i = 0; i< operators.length;i++)
        {
            if(op2.equals(operators[i]))
            {
                p_op2=precedence[i];
            }
        }
        
        boolean higher_ornot = false;
        
        if(p_op1 > p_op2)
        {
            higher_ornot = false;
        }
        else if(p_op1 < p_op1)
        {
            higher_ornot = true;
        }
        else if(p_op1== p_op2)
        {
        System.out.println(op1+": "+p_op1);
        System.out.println(op2+": "+p_op2);
            higher_ornot = false; //since associativity of op1 will be higher --> thus higher precedence
        }
        
        return higher_ornot;
    }
    
}

我试图将用户的中缀数学表达式转换为数组中的后缀表达式,该表达式将被求值,但在求值之前,我在后缀方法中遇到了问题
while(!op.empty()&&具有较高优先级(op.peek(),this.exp[i]))
当条件应该为真时,当它比较栈顶时,没有调用这一特定行,栈顶是 * 和-,* 具有更高的优先级,由于栈不为空,因此它应该返回真,因此调用函数。我测试了其他区域是否有任何错误,但我测试的所有内容都是正确的,我真的不知道如何修复。
我真的毫无头绪,即使经过1个半小时的盯着,并试图跟踪代码
我希望输出为[3,2,4,*,+,3,-],这是技术上将在稍后进行计算的后缀表达式

tp5buhyn

tp5buhyn1#

原因在于第二条件HasHigherPrecedence在所有情况下都为假,因此即使堆栈非空,整个条件也被评估为假

aamkag61

aamkag612#

我从简化代码开始,你可以使用一个Map来存储运算符的优先级:

private static final Map<String,Integer> PRECEDENCE = new HashMap<>();
static {
    PRECEDENCE.put("+", 1);
    PRECEDENCE.put("-", 1);
    PRECEDENCE.put("*", 2);
    PRECEDENCE.put("/", 2);
}

这允许您测试字符串是否为有效运算符:

private static boolean isOperator(String s) {
    return PRECEDENCE.containsKey(s);
}

以及比较两个运算符的优先级:

private static boolean hasHigherPrecedence(String op1, String op2) {
    return PRECEDENCE.get(op1) > PRECEDENCE.get(op2);
}

在开始的时候,我不需要复杂的拆分和循环,我只需要解析输入表达式,同时进行后缀转换,我需要一个变量pos来保存当前位置,以及方法readOperandreadOperator

private int pos;

/* ... */

private String readOperand() {
    int mark = pos;
    while (pos < expression.length() && Character.isDigit(expression.charAt(pos))) {
        ++pos;
    }
    return pos > mark ? expression.substring(mark, pos) : null;
}

private String readOperator() {
    if (pos < expression.length() && isOperator(expression.substring(pos, pos+1))) {
        return expression.substring(pos, ++pos);
    }
    return null;
}

postfix方法变为:

public void postfix() {
    String operand = readOperand();
    while (operand != null) {
        postfix.add(operand);
        String op = readOperator();
        if (op == null) {
            break;
        }
        while (!ope.isEmpty() && !hasHigherPrecedence(op, ope.peek())) {
            postfix.add(ope.pop());
        }
        ope.add(op);
        operand = readOperand();
    }
    while (!ope.empty()) {
        postfix.add(ope.pop());
    }
    System.out.println("Output: " + postfix);
}

请注意

!hasHigherPrecedence(op, ope.peek())

相当于:

PRECEDENCE.get(ope.peek()) >= PRECEDENCE.get(op)

所以如果堆栈顶部的操作符的优先级大于或等于当前操作符的优先级,那么它将被移动到后缀数组中。

相关问题