Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用堆栈从算术表达式中删除不必要/重复的括号_Java_Data Structures_Stack - Fatal编程技术网

Java 使用堆栈从算术表达式中删除不必要/重复的括号

Java 使用堆栈从算术表达式中删除不必要/重复的括号,java,data-structures,stack,Java,Data Structures,Stack,编写一个在表达式中查找重复括号的程序。 例如: (( a + b ) + (( c + d ))) = a + b + c + d (( a + b ) * (( c + d ))) = (a + b) * (c + d) 我知道的一种方法包括以下两个步骤: 将给定的中缀表达式转换为后缀表达式 将后缀转换回中缀 我不想做从一个表示转换到另一个表示的整个过程,然后再转换回来 我想使用堆栈完成此操作,但只需一次。可能吗 请建议一个算法或共享代码。没有对其进行编程,但可能是这样的: 将运算值设为+/

编写一个在表达式中查找重复括号的程序。 例如:

(( a + b ) + (( c + d ))) = a + b + c + d
(( a + b ) * (( c + d ))) = (a + b) * (c + d)
我知道的一种方法包括以下两个步骤:

  • 将给定的中缀表达式转换为后缀表达式
  • 将后缀转换回中缀
  • 我不想做从一个表示转换到另一个表示的整个过程,然后再转换回来

    我想使用堆栈完成此操作,但只需一次。可能吗


    请建议一个算法或共享代码。

    没有对其进行编程,但可能是这样的:

    将运算值设为+/-1 将运算*&/的值设为2 给出操作)(值2(与*相同)

    当两个步骤之间没有变化时,您就完成了

    希望这有帮助。。 如果你有解决办法,请告诉我。 如果这没有帮助,也请让我知道:)

    问候语

    您可以使用。这隐式地使用函数调用堆栈,而不是显式地使用Java堆栈。可按如下方式实施:

    public class Main {
    
        public static void main(String[] args) {
            System.out.println(new Parser("(( a + b ) + (( c + d )))").parse());
            System.out.println(new Parser("(( a + b ) * (( c + d )))").parse());
        }
    }
    
    public class Parser {
        private final static char EOF = ';';
        private String input;
        private int currPos;
    
        public Parser(String input) {
            this.input = input + EOF; // mark the end
            this.currPos = -1;
        }
    
        public String parse() throws IllegalArgumentException {
            nextToken();
            Result result = expression();
            if(currToken() != EOF) {
                throw new IllegalArgumentException("Found unexpected character '" + currToken() + "' at position " + currPos);
            }
            return result.getText();
        }
    
        // "expression()" handles "term" or "term + term" or "term - term"
        private Result expression() throws IllegalArgumentException {
            Result leftArg = term();
    
            char operator = currToken();
            if (operator != '+' && operator != '-') {
                return leftArg; // EXIT
            }
            nextToken();
    
            Result rightArg = term();
    
            if(operator == '-' && (rightArg.getOp() == '-' || rightArg.getOp() == '+')) {
                rightArg = encloseInParentheses(rightArg);
            }
    
            return new Result(leftArg.getText() + " " + operator + " " + rightArg.getText(), operator);
        }
    
        // "term()" handles "factor" or "factor * factor" or "factor / factor"
        private Result term() throws IllegalArgumentException {
            Result leftArg = factor();
    
            char operator = currToken();
            if (operator != '*' && operator != '/') {
                return leftArg; // EXIT
            }
            nextToken();
    
            Result rightArg = factor();
    
            if(leftArg.getOp() == '+' || leftArg.getOp() == '-') {
                leftArg = encloseInParentheses(leftArg);
            }
            if(rightArg.getOp() == '+' || rightArg.getOp() == '-' || (operator == '/' && (rightArg.getOp() == '/' || rightArg.getOp() == '*'))) {
                rightArg = encloseInParentheses(rightArg);
            }
    
            return new Result(leftArg.getText() + " " + operator + " " + rightArg.getText(), operator);
        }
    
        // "factor()" handles a "paren" or a "variable"
        private Result factor() throws IllegalArgumentException {
            Result result;
            if(currToken() == '(') {
                result = paren();
            } else if(Character.isLetter(currToken())) {
                result = variable();
            } else {
                throw new IllegalArgumentException("Expected variable or '(', found '" + currToken() + "' at position " + currPos);
            }
            return result;
        }
    
        // "paren()" handles an "expression" enclosed in parentheses
        // Called with currToken an opening parenthesis
        private Result paren() throws IllegalArgumentException {
            nextToken();
            Result result = expression();
            if(currToken() != ')') {
                throw new IllegalArgumentException("Expected ')', found '" + currToken() + "' at position " + currPos);
            }
            nextToken();
            return result;
        }
    
        // "variable()" handles a variable
        // Called with currToken a variable
        private Result variable() throws IllegalArgumentException {
            Result result = new Result(Character.toString(currToken()), ' ');
            nextToken();
            return result;
        }
    
        private char currToken() {
            return input.charAt(currPos);
        }
    
        private void nextToken() {
            if(currPos >= input.length() - 1) {
                throw new IllegalArgumentException("Unexpected end of input");
            }
            do {
                ++currPos;
            }
            while(currToken() != EOF && currToken() == ' ');
        }
    
        private static Result encloseInParentheses(Result result) {
            return new Result("(" + result.getText() + ")", result.getOp());
        }
    
        private static class Result {
            private final String text;
            private final char op;
    
            private Result(String text, char op) {
                this.text = text;
                this.op = op;
            }
    
            public String getText() {
                return text;
            }
    
            public char getOp() {
                return op;
            }
        }
    }
    
    如果要使用显式堆栈,可以使用类似于
    结果
    内部类的堆栈将算法从递归转换为迭代。 事实上,Java编译器/JVM将每个递归算法转换为基于堆栈的算法,将局部变量放入堆栈中


    但是递归体面的解析器很容易被人阅读,因此我更喜欢上面介绍的解决方案。

    如果您只关心重复的括号(正如问题似乎暗示的那样),而不是那些由于运算符优先级而认为必要的括号(如其他答案似乎暗示的那样)您确实可以使用堆栈跟踪遇到的括号,并确定每对括号的任何非空白非括号字符都很重要,这使您可以使用堆栈进行更简单的迭代遍历:

    public class BracketFinder {
    
        public List<BracketPair> findUnnecessaryBrackets(String input) {
            List<BracketPair> unneccessaryBrackets = new LinkedList<BracketPair>();
            Deque<BracketPair> bracketStack = new LinkedBlockingDeque<BracketPair>();
    
            for (int cursor = 0; cursor < input.length(); cursor++ ) {
                if (input.charAt(cursor) == '(') {
                    BracketPair pair = new BracketPair(cursor);
                    bracketStack.addLast(pair);
                } else if (input.charAt(cursor) == ')') {
                    BracketPair lastBracketPair = bracketStack.removeLast();
                    lastBracketPair.end = cursor;
                    if (!lastBracketPair.isNecessary) {
                        unneccessaryBrackets.add(lastBracketPair);
                    }
                } else if (input.charAt(cursor) != ' ') {
                    if (!bracketStack.isEmpty()) {
                        bracketStack.getLast().isNecessary = true;
                    }
                }
            }
    
            return unneccessaryBrackets;
        }
    
        class BracketPair {
            public int start = -1;
            public int end = -1;
            public boolean isNecessary = false;
    
            public BracketPair(int startIndex) {
                this.start = startIndex;
            }
        }
    }
    
    公共类BracketFinder{
    公共列表FindUnnecessary括号(字符串输入){
    List unnecsessarybolds=newlinkedlist();
    Deque bracketStack=newlinkedblockingdeque();
    对于(int cursor=0;cursor
    您可以使用以下内容来测试它

        public static void main(String... args) {
            List<BracketPair> results = new BracketFinder().findUnnecessaryBrackets("(( a + b ) + (( c + d ))) = a + b + c + d");
            for (BracketPair result : results) {
                System.out.println("Unneccessary brackets at indices " + result.start + "," + result.end);
            }
        }
    
    publicstaticvoidmain(字符串…参数){
    List results=new-BracketFinder().finduneccessary括号(((a+b)+((c+d))=a+b+c+d);
    for(括号对结果:结果){
    System.out.println(“索引“+result.start+”、“+result.end”处不必要的括号);
    }
    }
    
    一次完成即可。其思想是围绕每个()块查找上一个/下一个操作,并应用关联性规则。这是一张小桌子,在需要()时有是/否标记

            // (a + b) + c NO
            // (a + b) - c NO
            // (a + b) / c YES
            // (a + b) * c YES
    
            // (a / b) + c NO
            // (a / b) - c NO
            // (a / b) / c NO
            // (a / b) * c NO
    
            // a + (b + c) NO
            // a - (b + c) YES
            // a / (b + c) YES
            // a * (b + c) YES
    
            // a + (b / c) NO
            // a - (b / c) NO
            // a / (b / c) YES
            // a * (b / c) NO
    
    
            // (a) ((a))   NO
    

    这里是C++代码(我不确定它是否没有丢失一些案例——它只是一个想法):


    我个人认为至少有两种方法:

    • 使用一棵树
    • 使用

    可以从输入表达式创建树。创建树后,可以将其展平,而不需要无用的括号

    波兰符号

    • ((a+b)+((c+d))
      将变成
      (+(+ab)(+cd))
    • ((a+b)*((c+d))
      将变成
      (*(+ab)(+cd))
    从这里,您可以比较每个操作数和因子,看看它们在求解算术方程时是否具有相同的优先级


    我会和这棵树一起去。

    有可能。。。具体取决于您如何定义“单次传递”。单次传递的意思是遍历表达式一次。您希望支持哪些操作?只有*-+/可以吗?测试表达式太简单了。我不确定这是否能一次完成。例如,
    ((a+b/c)+((d+e))/(c)+(f+g)
    由于缺少右括号而导致错误。我认为您必须在一次过程中进行验证,然后在下一次过程中进行简化。但是,我可能错了。您还必须考虑分配属性之类的问题吗?
            // (a + b) + c NO
            // (a + b) - c NO
            // (a + b) / c YES
            // (a + b) * c YES
    
            // (a / b) + c NO
            // (a / b) - c NO
            // (a / b) / c NO
            // (a / b) * c NO
    
            // a + (b + c) NO
            // a - (b + c) YES
            // a / (b + c) YES
            // a * (b + c) YES
    
            // a + (b / c) NO
            // a - (b / c) NO
            // a / (b / c) YES
            // a * (b / c) NO
    
    
            // (a) ((a))   NO
    
    string clear(string expression)
    {
        std::stack<int> openers;
        std::stack<int> closers;
        std::stack<bool> isJustClosed;
        std::stack<char> prevOperations;
        std::stack<bool> isComposite;
        std::stack<int> toDelete;
    
    
        prevOperations.push(' ');
        isJustClosed.push(false);
        isComposite.push(false);
    
        string result = expression + "@";
        for (int i = 0; i < result.length(); i++)
        {
            char ch = result[i];
    
            if ((ch == '*') || (ch == '/') || (ch == '+') || (ch == '-') || (ch == '(') || (ch == ')') || (ch == '@'))
                if (isJustClosed.size() > 0)
                    if (isJustClosed.top() == true) {
    
                        // pop all and decide!
                        int opener = openers.top(); openers.pop();
                        int closer = closers.top(); closers.pop();
                        char prev = prevOperations.top(); prevOperations.pop();
                        char prevOperationBefore = prevOperations.top();
                        isJustClosed.pop(); //isJustClosed.push(false);
                        bool isComp = isComposite.top(); isComposite.pop();
    
                        bool ok = true;
                        if (prev == ' ')
                            ok = false;
                        else
                        {
                            ok = false;
                            if (((isComp) || (prev == '+') || (prev == '-')) && (ch == '/')) ok = true;
                            if (((isComp) || (prev == '+') || (prev == '-')) && (ch == '*')) ok = true;
    
                            if (((isComp) || (prev == '+') || (prev == '-')) && (prevOperationBefore == '-')) ok = true;
                            if (prevOperationBefore == '/') ok = true;
                            if (((isComp) || (prev == '+') || (prev == '-')) && (prevOperationBefore == '*')) ok = true;
                        }
    
    
                        if (!ok)
                        {
                            toDelete.push(opener);
                            toDelete.push(closer);
                        }
                    }
    
            if (ch == '(') {
                openers.push(i);
                prevOperations.push(' ');
                isJustClosed.push(false);
                isComposite.push(false);
            }
    
            if (ch == ')') {
                closers.push(i);
                isJustClosed.top() = true;
            }
    
            if ((ch == '*') || (ch == '/') || (ch == '+') || (ch == '-')) {
                if (!isComposite.top())
                {
                    char prev = prevOperations.top();
                    if ((ch == '+') || (ch == '-'))
                        if ((prev == '*') || (prev == '/'))
                            isComposite.top() = true;
                    if ((ch == '*') || (ch == '/'))
                        if ((prev == '+') || (prev == '-'))
                            isComposite.top() = true;
                }
                prevOperations.top() = ch;
                isJustClosed.top() = false;
            }
    
    
        }
    
        while (toDelete.size() > 0)
        {
            int pos = toDelete.top();
            toDelete.pop();
            result[pos] = ' ';
        }
        result.erase(result.size() - 1, 1);
    
        return result;
    }
    
    void test()
        {
            LOG << clear("((a + (a + b))) - ((c)*(c) + d) * (b + d)") << NL;
            LOG << clear("a + (a + b) - ((c) + d) * (b + d)") << NL;
            LOG << clear("(a/b)*(c/d)") << NL;
            LOG << clear("(a/b)*((((c)/d)))") << NL;
            LOG << clear("((a + b) - (c - d))") << NL;
            LOG << clear("((a + b)*((c - d)))+c/d*((a*b))") << NL;
            LOG << clear("a+a*b*(a/b)") << NL;
            LOG << clear("a+a*b*(a+b)") << NL;
        }
    
      a +  a + b    - ( c * c  + d) *  b + d 
     a +  a + b  - ( c  + d) *  b + d 
    a/b * c/d 
    a/b *    c /d   
     a + b  - (c - d) 
    (a + b)*  c - d   +c/d*  a*b  
    a+a*b* a/b 
    a+a*b*(a+b)