簡體   English   中英

使用位掩碼生成排列

[英]Generate permutation using bitmask

我正在使用位掩碼生成字符串的所有排列。

void recurse(string s, int mask,int taken){

    if(taken == n){
        cout << " ";
        return;
    }
    for(int i = 0; i < n; i++){
        if(((1 << i) & mask) == 0){
            cout << s[i];
            recurse(s, (mask|(1 << i)), taken + 1);
        }
    }
}

在這個函數中,n 是字符串的長度。 我正在使用 take 變量跟蹤到目前為止打印了多少個字符。 在我調用的主函數中

recurse(s,0,0);

但這不能正常工作。 對於輸入

紅色

它的輸出是

紅鹿博士 德雷爾博士

我哪里出錯了?


更新// 下面的代碼工作正常。

void recurse(string s, int mask,int taken, string pref){

    if(taken == n){
        cout << pref <<endl; 
        return;
    }
    for(int i = 0; i < n; i++){
        if(((mask >> i) & 1) == 0){
            recurse(s,(mask | (1 << i)),taken + 1, pref + s[i]);
        }
    }
}

其實,提問者自己給出了答案。 (恭喜。)

由於我已經開始擺弄(無法抗拒),我也想提出我的解決方案:

#include <iostream>
#include <string>

using namespace std;

void recurse(
  const string &s, unsigned mask = 0, const string &out = string())
{
  size_t n = s.size();
  if (out.size() == n) cout << ' ' << out;
  for (size_t i = 0; i < n; ++i) {
    unsigned bit = 1 << i;
    if (mask & bit) continue;
    recurse(s, mask | bit, out + s[i]);
  }
}

int main()
{
  string test = "red";
  recurse(test);
  cout << endl;
  return 0;
}

編譯和測試:

 red rde erd edr dre der

recurse()遍歷s所有字符,尋找mask尚未標記為已取的字符。 每個找到的字符都被添加到輸出out 然后,遞歸調用對所有未使用的字符重復它。

自己在ideone上查看示例代碼。

'abc' 的排列樹

您的第一個代碼是訪問該樹的每個節點一次並打印一個字符。 所以它給出了錯誤的輸出。

另一方面,您使用了一些冗余變量。

你應該使用s.size()而不是n

在第二個代碼中taken您應該使用pref.size()而不是pref.size()

這是另一個版本。 它在兩個方面與提問者的代碼不同:

  1. 參數taken可以被省略,並且我們可以使用mask + 1 == (1 << n)而不是。 它基本上檢查,如果位1n-1mask全部為1。 如果是,則遞歸深度為n ,我們打印排列。

  2. 如果字符串的大小很大,則在每次迭代中復制string pref可能會很慢。 我們可以改為使用引用。

#include <iostream>
#include <string>

using namespace std;

void recurse(string s, int mask, string &pref);

int n = 3;

int main()
{
    string pref("");
    recurse(string("abc"), 0, pref);
    return 0;
}

void recurse(string s, int mask, string &pref)
{
    if (mask + 1 == (1 << n)) {
        cout << pref << endl;
        return;
    }
    for (int i = 0; i < n; i++) {
        if (((mask >> i) & 1) == 0) {
            pref += s[i];
            recurse(s, (mask | (1 << i)), pref);
            pref.erase(pref.end() - 1);
        }
    }
}

其中n是字符串的大小。 輸出是

abc
acb
bac
bca
cab
cba

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM