2017-08-16 74 views
1

我想在Java中進行遞歸,傳遞對象參數。事情是這樣的:現在在遞歸中傳遞對象參數有效嗎?

int recursion(Object object) 
{ 
    //do a little bit modification to the object 
    int i1= recursion(modified_object_1); 
    //do a little bit modification to the object 
    int i2= recursion(modified_object_2); 
    //do a little bit modification to the object 
    int i3= recursion(modified_object_3); 
    return max(i1, i2, i3); 
} 

,因爲對象是通過引用傳遞,我要克隆的對象參數的3倍和克隆的對象傳遞給下一個遞歸。但是,這可能是非常低效的,因爲我正在進行數萬次遞歸,而且對象結構複雜。除了克隆對象之外,還有更有效的方法嗎?

謝謝〜

+0

如果您需要*數萬次遞歸*,請在對象定義中設置遞歸循環。或者詳細說明你想要實現什麼以及對象**的一些修改是什麼 – nullpointer

+0

你可能想要考慮廢棄動態編程迭代方法的遞歸方法,類似於人們經常使用的經典的斐波那契程序介紹類 –

+0

只是一個修正,你通過** value **傳遞對象,通過**引用**傳遞對象(也就是將它傳遞給內存中的地址)是最有效的方法。儘管如此,它不可能在Java –

回答

3

首先關於通過價值和參考(OP看起來很清楚,但評論者似乎困惑)有點清晰。 Java對象在傳遞給函數時不會自動克隆 - 對象的引用是按值傳遞的 - 在函數中更改對象將更改調用上下文中的對象。

因此,OP正確計劃運行他的算法,他需要首先克隆對象,然後使用克隆副本向下傳遞遞歸函數鏈。

然而有一個其他的可以在某些情況下可以輕鬆實現可能性:

int recursion(Object object) 
{ 
    //do a little bit modification to the object 
    int i1= recursion(object); 
    //undo the modification to the object 
    //do a little bit modification to the object 
    int i2= recursion(object); 
    //undo the modification to the object 
    //do a little bit modification to the object 
    int i3= recursion(object); 
    //undo the modification to the object 
    return max(i1, i2, i3); 
} 

在情況下,這是可能的(例如搜索遊戲決策樹時選擇一個可能的移動時),它可以更有效率的。

請注意,上次撤銷更改需要否則堆棧中較高的對象將出錯。

1

我不認爲你能避免複製這些對象

我的建議是建立一個預功能,從你爲了建立一些需要這些對象的一切提取一種「儘可能小的對象」,以便在遞歸中儘可能複製儘可能少的字段。

最好的情況是,如果你可以提取原始類型,並使用它們進行遞歸。無論如何,更具體的幫助你應該發佈更多的細節(例如你的對象/修改)

-1

在java中,你不能通過引用傳遞參數,只是通過值。在你的情況下,可能的解決方法是將對象定義爲方法所在類的屬性。例如:

class RecursionClass { 
    private Object object; 

    public void setObject(Object object) { 
     this.object = object; 
    } 

    int recursion() { 
     if(object == null) 
      throw new Exception("Set the object first!"); 

     // define modified objects base on object 


     //do a little bit modification to the object 
     int i1= recursion(modified_object_1); 
     //do a little bit modification to the object 
     int i2= recursion(modified_object_2); 
     //do a little bit modification to the object 
     int i3= recursion(modified_object_3); 
     return max(i1, i2, i3); 
    } 
} 
3

考慮使用不可變對象。遞歸算法在堆棧共享正在被修改的對象時變得特別難以考慮。

裝飾模式可以幫助提高效率和內存使用率。例如,如果你改變一個字段:

class UserWithAgeChanged implements User { 

     private User delegate; 
     private int age; 

     public UserWithAgeChanged(User user, int newAge) { 
      this.delegate = user; 
      this.age = newAge; 
     } 

     @Override 
     public String getName() { 
      return delegate.getName(); 
     } 

     // similar methods for all delegated fields 

     @Override 
     public String getAge() { 
      return age; 
     } 
} 

(有庫,幫助你做這種事情 - 比如Immutables library

現在你可以做一些類似的遞歸:

// silly functionality, but you get the point 
    void recurse(User user) { 
     if(user.getAge() == 44) { 
      return user; 
     } else { 
      recurse(new UserWithAgeChanged(user, user.getAge() + 1); 
     } 
    } 

這將創建一個代表鏈,大多數是微小的對象,最後有更大的「根」User對象。在一個更復雜的算法中,最終會得到一個不可變對象的網絡,但不會有太多的複製或克隆正在進行 - 而是會有很多委託。