堆栈,堆和递归

时间:2014-08-05 09:00:53

标签: java recursion heap-memory stack-memory

在可以使用递归(堆栈中的存储状态)和对象创建(堆中的新对象)的场景中。

问题

在对象创建和递归之间进行选择时应该考虑哪些参数?

我的研究得出以下结论(需要验证这个

  1. 当内存较少时:使用递归
  2. 可读性:使用对象创建
  3. 范围:

    • 我关注内存和速度,优先考虑速度。
    • 我关注可量化的事实和证据,如果可能而不是意见。

    示例(在模式匹配算法中)

    相关(代码审核se):https://codereview.stackexchange.com/questions/59052/simple-wildcard-pattern-matcher-in-java-follow-up

    使用递归和状态重置:

    public class SimpleMatch {
    
        //state enums
        private static enum State {
    
            JUST_STARTED, NORMAL, EAGER, END
        }
    
        //constants
        private static final char MATCH_ALL = '*';
        private static final char MATCH_ONE = '?';
    
        private final int ptnOutBound; // pattern out bound
        private final int strOutBound; // string out bound
        private final String pattern; // pattern
        private final String matchString; // string to match
    
        private int ptnPosition; // position of pattern
        private int strPosition; // position of string
        private State state = State.JUST_STARTED; // state
        private boolean matchFound = false; // is match
    
        public SimpleMatch(String pattern, String matchStr) {
    
            if (pattern == null || matchStr == null) {
                throw new IllegalArgumentException(
                        "Pattern and String must not be null");
            }
    
            this.pattern = pattern;
            this.matchString = matchStr;
            int pl = pattern.length();
            int sl = matchStr.length();
            if (pl == 0 || sl == 0) {
                throw new IllegalArgumentException(
                        "Pattern and String must have at least one character");
            }
            ptnOutBound = pl - 1;
            strOutBound = sl - 1;
            ptnPosition = 0;
            strPosition = 0;
    
        }
    
        private void calcState() {
            //calculate state
            if (state == State.END) {
                return;
            }
    
            if (!patternCheckBound() || !matchStrCheckBound()) {
                state = State.END;
            } else if (patternChar() == MATCH_ALL) {
                if (!patternNextCheckBound()) {
                    state = State.END;
                    matchFound = true;
                } else {
                    state = State.EAGER;
                }
            } else {
                state = State.NORMAL;
            }
        }
    
        private void eat() {
            //eat a character
            if (state == State.END) {
                return;
            }
    
            matchFound = false;
    
            if (state == State.EAGER) {
    
                int curStrPosition = strPosition;
                int curPtnPosition = ptnPosition;
                strPosition++;
                ptnPosition++;
                if (match()) {
                    state = State.END;
                    matchFound = true;
                    return;
                } else {
                    strPosition = curStrPosition;
                    ptnPosition = curPtnPosition;
                    state = State.EAGER;
                }
                strPosition++;
            } else if (state == State.NORMAL) {
                if (matchOne()) {
                    strPosition++;
                    ptnPosition++;
                    matchFound = true;
                } else {
                    state = State.END;
                }
            }
        }
    
        private boolean matchOne() {
            // match one
            char pc = patternChar();
            return (pc == MATCH_ONE || pc == matchStrChar());
        }
    
        private char patternChar() {
            // pattern current char
            return pattern.charAt(ptnPosition);
        }
    
        private char matchStrChar() {
            // str current char
            return matchString.charAt(strPosition);
        }
    
        private boolean patternCheckBound() {
            //pattern position bound check
            return ptnPosition <= ptnOutBound;
        }
    
        private boolean patternNextCheckBound() {
            //pattern next position bound check
            return (ptnPosition + 1) <= ptnOutBound;
        }
    
        private boolean matchStrCheckBound() {
            //string bound check
            return strPosition <= strOutBound;
        }
    
        /**
    * Match and return result
    *
    * @return true if match
    */
    
        public boolean match() {
            if (ptnOutBound > strOutBound) {
                return false;
            }
            while (state != State.END) {
                calcState();
                eat();
            }
            return matchFound;
        }
    
    
    }
    

    使用新对象创建:

    public class SimplePattern {
    
        //constants
        private static final char MATCH_ALL = '*';
        private static final char MATCH_ONE = '?';
    
        private final CharSequence pattern;
        private final int ptnPosition;
    
        public SimplePattern(CharSequence pattern) {
            this(pattern, 0);
        }
    
        private SimplePattern(CharSequence pattern, int ptnPosition) {
            if (pattern == null) {
                throw new IllegalArgumentException("Pattern must not be null");
            }
    
            this.pattern = pattern;
            this.ptnPosition = ptnPosition;
        }
    
        /**
         * Match and return result
         *
         * @return true if match
         */
        public boolean match(CharSequence string) {
            return this.match(string, 0);
        }
    
        public boolean match(CharSequence string, int startPosition) {
            if (ptnPosition == this.pattern.length()) {
                return startPosition == string.length();
            }
            if (startPosition >= string.length()) {
                return false;
            }
            SimplePattern nextPattern = new SimplePattern(pattern, ptnPosition + 1);
            char patternChar = this.pattern.charAt(this.ptnPosition);
            switch (patternChar) {
              case MATCH_ONE:
                return nextPattern.match(string, startPosition + 1);
              case MATCH_ALL:
                for (int i = startPosition + 1; i <= string.length(); i++) {
                    if (nextPattern.match(string, i)) {
                        return true;
                    }
                }
                return false;
              default:
                return string.charAt(startPosition) == patternChar &&
                       nextPattern.match(string, startPosition + 1);
            }
        }
    
    }
    

2 个答案:

答案 0 :(得分:4)

我认为对象创建与Recursion没有任何关系。如果你的意思是循环,那么我的意思是:

  

当可读性很重要且时间很少实现时:递归

     

当性能很重要且迭代很多时(特别是在   像Java这样没有尾递归的语言):循环

答案 1 :(得分:1)

Java并没有特别好地进行递归。除非递归显然是最佳选择,否则假设迭代或使用新流将是最有效或更自然的选择。