2013-09-28 35 views
0

我寫這個短程序隨機選擇m個元素的子集出{1,...,N}的 -如何種子遞歸C++函數

std::set<int> randSubSet(int n, int m){ 
    // generates a random subset of m elements from {1,...,n} uniformly 

    if (m>n) //check inputs validity 
    throw std::invalid_argument("m is larger then n."); 

    std::set<int> res{}; //initialize result set 

    if (m==n){ //easy case - the full set 
    for(int i = 1 ; i<n ; ++i) 
     res.insert(i); 
    } 

    std::mt19937 eng; 
    std::uniform_int_distribution<> uni(1,n); 

    if (m == 0){ // recursion base case 

     return res; 
    } 
    else { 
     res = randSubSet(n-1,m-1); 
     int i = uni(eng); 
     if (res.find(i) == res.end()) // if i isn't in S add it 
      res.insert(i); 
     else 
      res.insert(n); //else add n 

    } 
    return res; 
} 

由於主機不接種我總是得到相同的答案。我該如何種植這種仙人掌? (因爲每個電話都有自己的引擎)

我可以避免使用全局變量的問題,我想知道是否有更好的解決方案。謝謝!

+1

使用一個靜態變量,並將其初始化爲'0'。每次輸入函數時,檢查它是否爲'0'。如果是,請將PRNG播種,並將值更改爲「1」。如果不是,則什麼都不要做。 –

+0

使用一個靜態變量。 – atoMerz

回答

2

您可以將隨機引擎作爲參數傳遞給該函數,以便在每個遞歸步驟中使用相同的引擎。你的功能的簽名將變成std::set<int> randSubSet(int n, int m, std::mt19937& eng)。然後您需要傳遞一個隨機引擎才能使用該函數,因此您可以創建一個不需要隨機引擎的重載,並使用默認的隨機引擎調用您的函數(構建方式與您現在使用的方法相同)。

0

「種子」的遞歸函數的簡單方法是將其包含在一個非遞歸函數中:您只需編寫一個非遞歸函數來完成設置,然後調用遞歸函數來完成這項工作。

另一個可能有意義的方法是使用默認的init=true參數:在遞歸函數內部,您自稱通過init=false