2013-11-28 52 views
0

我想寫一個程序在Java中使用遞歸解壓縮RLE語句,但我不斷得到堆棧溢出錯誤,我不知道爲什麼。遞歸Java RLE解壓縮方法[stackoverflow錯誤]

這裏是我寫迄今:

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中,並且該數字會遞減並替換字符串開始處的數字,並將新字符串[與原始第一個字符編號 - 1]解壓縮。

+0

字符串有多長? Java不支持無限遞歸;遞歸算法只有在不太複雜時纔有效。 – user2357112

+0

不知道堆棧溢出,但每次遞歸調用'decompress'時,遞歸例程都會創建一個** new **'newString'。例程的新調用將**不附加到舊調用使用的相同'newString'。你的遞歸方法可能需要把'newString'作爲它自身傳遞的參數,然後在第一次調用遞歸例程之前,外部的非遞歸例程將需要初始化它。 – ajb

+0

你有沒有嘗試在調試器中逐句通過你的代碼?這和幾個很好的'System.out.println'記錄調用將幫助你找出爲什麼你的遞歸沒有達到基本情況並導致錯誤... – Krease

回答

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",則該方法會一直使用相同的字符串繼續調用自身。聲明cchar應該解決該問題。另外,請注意replaceFirst表示要搜索與第一個參數匹配的模式,並用第二個參數替換它。你可能會倒退。另外,請參閱我上面關於newString的評論。

編輯:回答您的評論:使用StringBuffer是好的。你不能做的是每個decompress都創建一個new StringBuffer,因爲那時每次都會調用decompress一個新的StringBuffer就會被創建出來,這不是你想要的。如果decompress需要StringBuffer newString參數,每個decompress自稱爲它傳遞newString作爲參數時,那麼每decompress通話將指向相同StringBuffer,因爲它是一個對象的引用。

,我想你暗示了另一種方法,由於decompress返回String,則每次decompress調用它本身可以使用函數的結果(現在你的代碼只是把它扔了),也許串聯該函數返回新的字符串。我認爲你可以使這種方法奏效,但我沒有徹底研究它。

+0

謝謝,我修復了它,並會發布更新的代碼。你可以進一步擴展newString和遞歸例程嗎?我會怎麼做呢?我可以改變它,讓字符串緩衝區是一個正常的字符串,我連接它。 – CameronCarter

+0

@ user3003741看我的編輯。 – ajb