Проблема рекурсии в генерации перестановки в c ++ - PullRequest
2 голосов
/ 24 декабря 2011

у меня есть два n в c ++, и я хочу сгенерировать перестановку чисел в этих векторах таким образом, чтобы для каждой перестановки первого вектора у меня были все перестановки всех других векторов.Скажем, у меня есть два вектора с номером 2 9, а другой вектор будет 5 6. тогда мой результат должен быть ...

  1. 2 9 5 6
  2. 2 9 6 5
  3. 9 2 5 6
  4. 9 2 6 5

означает, что общее количество перестановок, которые я получу, составит всего перми = (# количество перестановок 1-гоvector умножить на число перестановок второго вектора (умножить на число перестановок третьего вектора и т. д.).

Я написал приведенный ниже код и поражен стеком рекурсии ... На самом деле это печать 6времена для случая 2 вектора каждый имеет размер 2 каждый.

mySwap(int *x, int *y){
int temp;
temp = *x;
    *x = *y;
*y = temp;
}

меняет два элемента int

void myPerm(vector<vector<int>> myItems, int start, int end,int     vectorIndex){
int j;
if(start == end){
    for(int k = vectorIndex +1; k < items.size(); ++k){
        myPerm(myItems, 0, myItems[k].size()-1,k);
    }
    for(int z = 0; z < myItems.size(); ++z){
        for(int l = 0; l < myItems[z].size(); ++z){
            std::cout << myItems[z][l];
        }
    }
}
else{
    for(int j = start; j <= end; j++){
        mySwap(&myItems[vectorIndex][start],&myItems[vectorIndex][j]);
        myPerm(myItems,start + 1, end,vectorIndex);
        mySwap(&myItems[vectorIndex][start],&myItems[vectorIndex][j]);

    }   

}
} 

над кодом, который рекурсивно генерирует перестановки ...

int main(){
vector<vector<int>> myItems;
int k = 0;
for(int i =0; i < 2; ++i){
    myItems.push_back(vector<int>);
}
for(int j =0; j < 2; ++j){
    myItems[i].push_back(k++);
}

myPerm(items,0,items[0].size()-1,0);
return;
}

моя основная функция.

Пожалуйста, дайте мне подсказку или решите это для общего случая, так как вышеприведенный код печатает перестановки для шести, которые первоначально должны быть 4 раза.

Спасибо

Ответы [ 3 ]

0 голосов
/ 24 декабря 2011

Для этой проблемы рекурсия может быть полностью исключена с помощью next_permutation.Вот некоторый непроверенный код, который, возможно, более элегантен:

void myPerm(std::vector<std::vector<int>>& myItems)
{
    for (int i = 0; i < myItems.size(); i++)
        std::sort(myItems[i].begin(), myItems[i].end());

    int level;

    do
    {
        printAll(myItems);

        level = myItems.size() - 1;

        while (!next_permutation(myItems[level].begin(), myItems[level].end()))
            level--;
    }
    while (level >= 0);
}

Хорошая особенность next_permutation в том, что он возвращает false, когда он "оборачивает" данный набор, и поэтому набор сортируется и готов к следующемураунд перестановок.

0 голосов
/ 25 декабря 2011

Спасибо за все идеи специально для функции STL next_permutation.Я не знаю раньше.

Я смог написать код, который я хочу правильно ...

Вот мой код

void perm(std::vector<std::vector <int>> &items, int level){
if(level == 0){
for (int i = 0; i < items.size(); i++)
  for (int j = 0; j < items[i].size(); j++)
      std::cout << items[i][j];
std::cout<<std::endl;


    while(next_permutation(items[level].begin(), items[level].end())){
        for (int i = 0; i < items.size(); i++)
          for (int j = 0; j < items[i].size(); j++)
              std::cout << items[i][j];
        std::cout<<std::endl;
    }
}
else{

    if(level > 0)
    perm(items,level-1);
    while(next_permutation(items[level].begin(), items[level].end())){
        if(level > 0)
        perm(items,level-1);
    }

}

}

0 голосов
/ 24 декабря 2011

Учитывая, что это не домашняя работа, вы можете просто использовать алгоритм stl next_permutation вместо того, что у вас есть.

Это код для вашего примера ввода.

int main()
{

    std::vector<int> v1 , v2 , v3;
    v1.push_back( 2 );
    v1.push_back( 9 );
    v2.push_back( 5 );
    v2.push_back( 6 );

    std::sort( v1.begin() , v1.end() );
    std::sort( v2.begin() , v2.end() );

    do 
    {   
        v3 = v2;

        do 
        {
            std::for_each( v1.begin() , v1.end() , [](int x) { std::cout << x << " ";} );
            std::for_each( v3.begin() , v3.end() , [](int x) { std::cout << x << " ";} );
            std::cout << std::endl;
        } 
        while ( std::next_permutation(v3.begin() , v3.end() ) );
    } 
    while ( std::next_permutation(v1.begin() , v1.end() ) );

    return 0;
}

Это делает это для двух векторов ... Я уверен, что вы можете обобщить это дальше.

...