【问题标题】:How can I convert a recursive function into iterative function in java?如何在java中将递归函数转换为迭代函数?
【发布时间】:2012-01-29 17:39:09
【问题描述】:

我正在使用以下代码来解析小型 xml 文件,并且它运行成功。但是当我解析巨大的数据文件时,我得到一个堆栈溢出错误。因此,我决定将这种方法转换为迭代样式。最初在编写此方法时,我创建了逻辑并成功编写了它,但是当转换为迭代样式时,我完全迷失了方向,并且没有得到所需的输出。这是我的递归代码:

private void xmlParsing(Node node,int indent) throws IOException {
    if (node.hasChildNodes()) {
        Node firstChild=node.getFirstChild();
        xmlParsing(firstChild,indent+1);
    } else {
        System.out.println(node.getNodeName()+":"+node.getNodeValue()+":"+indent);
    }
    Node nextNode=node.getNextSibling();
    if (nextNode!=null) {
        xmlParsing(nextNode,indent);
    }
}

有人可以帮我把它转换成迭代函数,在单个函数下执行这个逻辑吗?我希望我已经提出了明确的要求。

我的完整代码:

package sample;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class NewTestClass {

    private Document doc = null;

    public NewTestClass() {
        BufferedWriter br=null;
        try {
            doc = parserXML(new File("debug.xml"));

            br=new BufferedWriter(new FileWriter("xmldata.txt"));
            xmlParsing(doc, 0,br);
        } catch(Exception error) {
            error.printStackTrace();
        } finally {
            try {
                br.flush();
                br.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    private void xmlParsing(Node node,int indent,BufferedWriter br) throws IOException {
        if (node.hasChildNodes()) {
            Node firstChild=node.getFirstChild();
            xmlParsing(firstChild,indent+1,br);
        } else {

            br.write(node.getNodeName()+":"+node.getNodeValue()+":"+indent);
            br.newLine();
        }
        Node nextNode=node.getNextSibling();
        if (nextNode!=null) {
            xmlParsing(nextNode,indent,br);
        }
    }

    public Document parserXML(File file) throws SAXException, IOException, ParserConfigurationException
    {
        return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(file);
    }

    public static void main(String[] args)
    {
        new NewTestClass();
    }
}

我最初的错误:

Exception in thread "main" java.lang.StackOverflowError
    at com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.getNodeValueString(Unknown Source)
    at com.sun.org.apache.xerces.internal.dom.DeferredDocumentImpl.getNodeValueString(Unknown Source)
    at com.sun.org.apache.xerces.internal.dom.DeferredTextImpl.synchronizeData(Unknown Source)
    at com.sun.org.apache.xerces.internal.dom.CharacterDataImpl.getNodeValue(Unknown Source)

【问题讨论】:

  • 你需要一个集合来存储所有的嵌套状态。
  • @PeterLawrey:不一定。我很确定,StackOverflowError 的出现是因为兄弟姐妹的递归,它可以很容易地转换为迭代......

标签: java xml dom recursion iteration


【解决方案1】:

你的问题是你也为兄弟姐妹递归,而不仅仅是孩子。子递归完全可以,但在您的情况下,递归与文档中(扁平)节点(不仅是元素)的数量一样深。

改为这样做:

private void xmlParsing(Node node, int indent) throws IOException {

    // iterate for siblings
    while (node != null) {

        // recurse for children
        if (node.hasChildNodes()) {
            Node firstChild = node.getFirstChild();
            xmlParsing(firstChild, indent + 1);
        } else {
            // do the leaf node action
        }

        node = node.getNextSibling();
    }
}

【讨论】:

    【解决方案2】:

    我认为你有大量的标签嵌套。您可以发布您的示例 xml 文件吗?

    如果我理解正确,您正在尝试将 xml 转换为具有特定格式的文本文件。如果这是要求,我建议您使用 XSL 和 XML 进行翻译。它非常简单,也很灵活。

    您可以在http://speakingjava.blogspot.com/2011/07/how-to-use-xml-and-xsl-in-java.html找到示例

    【讨论】:

    • 在这种情况下,迁移到 XSL 可能有点矫枉过正,因为算法中有一个简单的误解:兄弟姐妹的递归(而不是兄弟姐妹的迭代)
    • @Pragalathan,Lukas 是对的..我需要做一些简单的事情..XSL 是新知识..我认为这对我来说没有必要..无论如何,谢谢你的建议..
    猜你喜欢
    • 2020-08-08
    • 2015-05-30
    • 1970-01-01
    • 2021-11-03
    相关资源
    最近更新 更多