简体   繁体   English

堆栈,堆和递归

[英]Stack, Heap And Recursion

In a scenario where one can use recursion (store state in stack) and object creation (new object in heap). 在可以使用递归(堆栈中存储状态)和对象创建(堆中新对象)的情况下。

Question

What parameters should one consider when choosing between the object creation and recursion ? 在对象创建和递归之间进行选择时应考虑哪些参数?

My research lead to following conclusions ( Need to verify this ) 我的研究得出以下结论( 需要对此进行验证

  1. When Less Memory is Available : Use recursion 当可用内存较少时:使用递归
  2. Readability : Use object creation 可读性:使用对象创建

Scope: 范围:

  • I'm concerned about memory and speed with priority to speed. 我关心的是内存和速度,优先考虑速度。
  • I'm concerned about quantifiable facts and proofs if possible and not opinions. 如果可能的话,我担心可量化的事实和证据,而不是意见。

Example (in a pattern matching algorithm) 示例(在模式匹配算法中)

related (code review se): https://codereview.stackexchange.com/questions/59052/simple-wildcard-pattern-matcher-in-java-follow-up 相关(代码审查本身): https : //codereview.stackexchange.com/questions/59052/simple-wildcard-pattern-matcher-in-java-follow-up

Using recursion and state reset: 使用递归和状态重置:

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;
    }


}

Using new object creation: 使用新的对象创建:

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);
        }
    }

}

I do not think object creation has any relation to Recursion. 我认为对象创建与递归没有任何关系。 If you meant looping then my take: 如果您要循环播放,那么我认为:

When readability matters and time is scarce to implement: Recursion 当可读性很重要且缺乏实施时间时:递归

When performance matters and iterations are many (especially in language like Java where there is no tail recursion): Loop 当性能很重要且迭代次数很多时(尤其是像Java这样没有尾递归的语言):循环

Java doesn't do recursion particularly well. Java不能很好地进行递归。 Unless recursion is obviously the best choice, assume iteration or using the new Stream will be the most efficient, or a more natural choice. 除非显然递归是最佳选择,否则假定迭代或使用新Stream将是最有效或更自然的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM