2017-07-13 15 views
7

tôi đang học đệ quy và dưới đây trở lại là một ví dụ mà tôi đang truy tìm thông qua để hiểu rõ hơn về nóĐệ quy - tại sao sử dụng tuyên bố

public static void main(String []args) { 
    new TestRecursion().strRecur("abc"); 
} 

public void strRecur(String s) { 
    if(s.length() < 6) { 
     System.out.println(s); 
     strRecur(s+"*"); 
    } 
} 

Dưới đây là những gì tôi đã hiểu cho đến nay. - Trong cuộc gọi đầu tiên đến strRecur("abc"), phương thức sẽ được thêm vào chồng thực thi. Nó in "abc" trước khi tạm dừng do một cuộc gọi đệ quy với tham số "abc *".

  • Cuộc gọi thứ hai với "abc *", phương thức đẩy strRecur(abc*) vào ngăn xếp và in "abc *" để điều khiển.

  • Cuộc gọi thứ ba với "abc **", phương thức đẩy strRecur(abc**) vào ngăn xếp và in "abc **" để điều khiển.

  • Cuộc gọi thứ tư với "abc ***", phương thức đẩy strRecur(abc***) vào ngăn xếp. Vì điều kiện cơ bản được đáp ứng, phương thức hoàn thành (không in bất kỳ thứ gì) và bật ra khỏi ngăn xếp.

  • Cuộc gọi thứ ba có "abc **" đã hoàn tất và xuất hiện. Vì không có mã đang chờ xử lý nên không có gì xảy ra.

  • Cuộc gọi thứ hai với "abc *" đã hoàn tất và xuất hiện. Vì không có mã đang chờ xử lý nên không có gì xảy ra.

  • Cuộc gọi đầu tiên với "abc" đã hoàn tất và xuất hiện. Vì không có mã đang chờ xử lý nên không có gì xảy ra.

Stack

Prints sau vào giao diện điều khiển -

abc 
abc* 
abc** 

Tôi nghĩ rằng tôi hiểu những gì đang xảy ra ở đây. Bây giờ, tôi muốn thử một biến thể nhỏ của mã này. Thay vì gọi strRecur(s+"*"), tôi muốn làm return strRecur(s+"*")

public class TestRecursion { 

    public static void main(String []args) { 
     new TestRecursion().strRecur("abc"); 
    } 

    public String strRecur(String s) { 
     if(s.length() < 6) { 
      System.out.println(s); 
      return strRecur(s+"*"); 
     } 
     return "Outside If"; 
    } 
} 

kỳ vọng của tôi là, một khi strRecur(abc***) bật ra, đó là đầu ra (abc ***) sẽ được trả lại cho strRecur() tiếp theo trên stack, vì vậy tôi sẽ xem abc **** được in trong bảng điều khiển. Tương tự cho các cuộc gọi đệ quy khác.

Tuy nhiên, đầu ra trong trường hợp này hoàn toàn giống như khi không có câu lệnh trả về. hiểu biết của tôi (trong đó tất nhiên là không đúng) bắt nguồn từ việc thực hiện thừa đệ quy, nơi chúng tôi làm điều gì đó như

return n * fact(n-1); 

đây fact(n-1) được giải quyết với giá trị trả về của n, một khi phương pháp trước đó trên stack hoàn tất. Tại sao không trở lại hành xử theo cùng một cách trong ví dụ này?

+0

[Ví dụ khả thi] (https://ideone.com/GTCArI) trong trường hợp ai đó muốn fiddle. – Michael

+0

Chỉ cần một lời khuyên nhanh chóng: Tôi thấy rằng khi cố gắng hiểu đệ quy nó sẽ giúp nếu bạn in ra các chi tiết của mọi cuộc gọi. Ví dụ bắt đầu phương thức đệ quy của bạn với một cái gì đó như 'System.err.println ("> strRecur s = "+ s);' và trước khi trở về, bạn làm 'System.err.println (" biziclop

Trả lời

8

Kết quả của cả hai phương pháp được tạo bởi các câu lệnh println trong phương pháp đệ quy, đó là lý do tại sao nó giống hệt nhau trong cả hai phương pháp.

Giá trị được trả về bằng phương pháp thứ hai không được in ở bất kỳ đâu, đó là lý do tại sao bạn không nhìn thấy nó được hiển thị.

Nếu bạn in kết quả của phương pháp thứ hai, bạn sẽ thấy nó là "Outside If", vì đó là đầu ra của cuộc gọi đệ quy cuối cùng, sau đó được trả về bởi tất cả các cuộc gọi phương thức khác.

Nếu bạn muốn đầu ra được abc***, bạn nên

return s; 

thay vì

return "Outside If"; 

Mã đầy đủ sẽ là:

public static void main(String[] args) { 
    System.out.println(new TestRecursion().strRecur("abc")); 
} 

public String strRecur(String s) { 
    if(s.length() < 6) { 
     return strRecur(s+"*"); 
    } 
    return s; 
} 
+0

Ngoài ra, và tôi không biết yêu cầu của OP là gì, bạn có thể cần phải thay đổi từ 6 đến 5. Ví dụ đầu tiên của anh ta chỉ được gọi là 'abc **' – Michael

0

Sau đây là cách để làm cho nó trả về giá trị thay vì in nó:

public static void main(String[] args) { 
    String result = StrRecur("abc"); 
    System.out.print(result); 
} 

public static String StrRecur(String s) { 
    if(s.length() < 6) { 
     return s + "\n" + StrRecur(s+"*"); 
    } 
    return ""; 
} 

Điều này giống nhau, nhưng tác dụng phụ chỉ xảy ra ở main.

Các vấn đề liên quan