【问题标题】:Recursive Java RLE Decompression Method [stackoverflow error]递归 Java RLE 解压方法 [stackoverflow 错误]
【发布时间】:2013-11-28 01:40:18
【问题描述】:

我正在尝试用 Java 编写一个使用递归解压缩压缩 RLE 语句的程序,但我不断收到堆栈溢出错误,我不知道为什么。

这是我迄今为止写的:

public class StringRec
{
    public static void main (String args[]){

        System.out.println(decompress("wed4d"));
    }
    //Version 0.1
    public static String decompress(String compressedText)
    {   String cText = compressedText; 
        StringBuffer newString = new StringBuffer();

        int i = 0;

        if (cText==""){return newString.toString();}

        if(!cText.isEmpty()){

            if(Character.isLetter(cText.charAt(i))){
                newString.append(cText.charAt(i));

                cText = cText.substring(1,cText.length());  

                return decompress(cText);
                //remove first letter, return new modified string with removed first letter to decompress.
            }
            if(Character.isDigit(cText.charAt(i))){
                 int c = cText.charAt(i)-'0';

                if (c==0){
                    cText = cText.substring(2,cText.length());}

                    return decompress(cText);   
                    //delete c and the letter after it and send new modified string to decompress.
                    }

                }else {
                    newString.append(cText.charAt(i+1));
                    int c = cText.charAt(i);
                    c--;
                    String num = ""+c;
                    cText = cText.replaceFirst(num, Character.toString(cText.charAt(i)));

                    return decompress(cText);
                    //appends character after number to newString, decrements the number and returns
                    //the new modified string to decompress with the first number decremented by one
                    }
        return newString.toString(); 

    }
}

我的递归基本情况是一个空字符串,如果字符串以一个字母开头,则该字母仅添加到 stringbuffer newString 一次,并且原始字符串的第一个字母从字符串序列中删除,新字符串为通过解压;如果它以零数字开头,则删除字符串的前两个字符并将新字符串传递给解压缩。

如果它是一个大于 0[else] 的数字,那么它前面的字母被添加到 stringbuffer newString 并且数字被递减并替换字符串开头的数字并传递新的字符串 [with the original第一个字符数 - 1] 解压缩。

【问题讨论】:

  • 字符串有多长? Java 不支持无限递归;递归算法只有在递归不太深的情况下才有效。
  • 不知道堆栈溢出,但是每次递归调用decompress,递归例程都会创建一个newnewString。例程的新调用将附加到旧调用使用的相同newString。您的递归方法可能需要将newString 作为参数传递给自身,然后外部非递归例程需要在第一次调用递归例程之前对其进行初始化。
  • 您是否尝试过在调试器中单步执行您的代码?这和一些很好的 System.out.println 记录调用将帮助您找出为什么您的递归没有达到基本情况并导致错误......
  • @user3003741 - 我回滚了您最后的更改,因为它显着改变了问题和格式,并在最后包含了一个新的命名不当的函数。新代码的另一个问题可能应该作为它自己的问题发布。您可能还想考虑StackOverflow chat system 来解决很多来回的问题。

标签: java string recursion stack-overflow compression


【解决方案1】:

我相信无限递归是因为这个原因发生的:

int c = cText.charAt(i);
c--;
String num = ""+c;
cText = cText.replaceFirst(num, Character.toString(cText.charAt(i)));

如果字符是1,那么c 将是65,字符'1' 的ASCII 值。然后num 将被设置为字符串"64",如果你的字符串中没有"64",该方法将不断地用相同的字符串调用自己。将c 声明为char 应该可以解决这个问题。另外,请注意replaceFirst 表示要搜索与第一个参数匹配的模式,并将其替换为第二个。你可能有这个倒退。另外,请参阅我上面关于 newString 的评论。

编辑:回答您的评论:使用 StringBuffer 是可以的。你不能做的是让每个decompress 创建一个new StringBuffer,因为每次调用decompress 时都会创建一个新的StringBuffer,这不是你想要的。如果decompress 采用StringBuffer newString 参数,并且每次decompress 调用它自己时它都将newString 作为参数传递,那么每个decompress 调用将指向相同 StringBuffer,因为它是对对象的引用。

我认为您暗示的另一种方法是,由于 decompress 返回 String,那么每次 decompress 调用它自己时,它都可以使用函数结果(现在您的代码只是把它扔掉),并且可能将该函数结果与其他内容连接起来并返回新字符串。我认为您可以使这种方法奏效,但我还没有彻底研究过。

【讨论】:

  • 谢谢,我已修复它并将发布更新的代码。您能否进一步扩展 newString 和递归例程?我该怎么做呢?我可以改变它,让那个字符串缓冲区成为一个普通的字符串,然后我把它连接起来。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
相关资源
最近更新 更多