2010-09-25 4 views
0
void print_combinations(const std::string &str) 
{ 
     int i, j, k; 
     int len = str.length(); 

     for (i = 0; i < len - 2; i++) 
     { 
       for (j = i + 1; j < len - 1; j++) 
       { 
         for (k = j + 1; k < len; k++) 
           // show combination 
           cout << str.at(i) << str.at(j) << str.at(k) << endl; 

       } 
     } 
} 

Эта функция выполняет то, что я хочу, но хочу сделать ее рекурсивной, чтобы она могла создавать комбинации произвольной длины.Как сделать эту функцию рекурсивной

+0

произвольной длины? но вы уже делаете: int len ​​= str.length(); – vulkanino

+0

Я считаю, что он означает произвольную длину подстрок. В этом случае это три, но он хочет, чтобы это было произвольным. – JoshD

+0

Да, это правильно. –

ответ

1

Вот попробовать:

#include <iostream> 
#include <string.h> // for strlen 
#include <stdlib.h> // for atoi 
#include <sstream> 
void expand_combinations(const char *remaining_string, std::ostringstream& i, int remain_depth) 
{ 
    if(remain_depth==0) 
    { 
     std::cout << i.str() << std::endl; 
     return; 
    } 

    for(int k=0; k < strlen(remaining_string); ++k) 
    { 
     std::ostringstream l; 
     l << i.str(); 
     l << remaining_string[k]; 
     expand_combinations(remaining_string+k+1, l, remain_depth - 1); 
    } 
    return; 
} 
int main(int argc, char **argv) 
{ 
    std::ostringstream i; 
    if(argc<3) return 1; 
    expand_combinations(argv[1], i, atoi(argv[2])); 
    return 0; 
} 

Выход ./test фьорд 3:

fjo 
fjr 
fjd 
for 
fod 
frd 
jor 
jod 
jrd 
ord 
+1

Собственно, это довольно неэффективно. Создаются множество объектов string и ostringstream. – sellibitze

+0

Я согласен, что это так. Один массив размером 3, динамически созданный, может хранить буквы и передаваться по адресу. – Benoit

3

an STL algorithm to get permutations, который вы могли бы использовать для этого. Создайте вектор ints (not bools, the evil) и предоставите кучу из них (в вашем примере три из них), за которым следует достаточное количество нулей, чтобы равняться длине строки. Затем используйте алгоритм перестановки для прохождения всех перестановок этого вектора. Использование каждого из этих перестановок, распечатать строки символов, которые соответствуют те, в векторе:

for (int i = 0; i < string.length(); i++) 
{ 
    if (v[i]) cout << string.at(i); 
} 
cout << endl; 
next_permutation(v.begin(), v.end()); 
+0

+1 Хороший и простой. – sellibitze

1

Это мое решение (мне нужно было что-то червяк до для тяжелого дня :)

#include <iostream> 
#include <string> 

void print_combinations(const std::string &str) 
{ 
     int i, j, k; 
     int len = str.length(); 

     for (i = 0; i < len - 2; i++) 
     { 
       for (j = i + 1; j < len - 1; j++) 
       { 
         for (k = j + 1; k < len; k++) 
           std::cout << str.at(i) << str.at(j) << str.at(k) << std::endl; 

       } 
     } 
} 

void print_rec(const std::string &str, int currLevel, int totalLevel, int startPos, std::string tempString) 
{ 
    if (currLevel == totalLevel) 
    { 
     std::cout << tempString << std::endl; 
     return; 
    } 

    for (unsigned int i = startPos; i < str.length() - totalLevel + currLevel + 1; i++) 
    { 
     tempString.push_back(str.at(i)); 
     print_rec(str, currLevel + 1, totalLevel, i + 1, tempString); 
     // tempString.pop_back(); 
     tempString.erase(tempString.length() -1, tempString.length()); 
    } 
} 

int main() 
{ 
    print_combinations("testing"); 
    std::cout << std::endl << "====================" << std::endl << std::endl; 
    std::string tempString = ""; 
    print_rec("testing", 0, 3, 0, tempString); 
} 

выход:

tes 
tet 
tei 
ten 
teg 
tst 
tsi 
tsn 
tsg 
tti 
ttn 
ttg 
tin 
tig 
tng 
est 
esi 
esn 
esg 
eti 
etn 
etg 
ein 
eig 
eng 
sti 
stn 
stg 
sin 
sig 
sng 
tin 
tig 
tng 
ing 

==================== 

tes 
tet 
tei 
ten 
teg 
tst 
tsi 
tsn 
tsg 
tti 
ttn 
ttg 
tin 
tig 
tng 
est 
esi 
esn 
esg 
eti 
etn 
etg 
ein 
eig 
eng 
sti 
stn 
stg 
sin 
sig 
sng 
tin 
tig 
tng 
ing 
+0

Когда я пытаюсь запустить это, он говорит, что строка не имеет члена, называемого «pop_back». –

+0

hm, это странно, у меня есть pop_back в моем контейнере строк. В любом случае вы можете использовать tempString.erase (tempString.length() -1, tempString.length()); Я редактировал свое решение. Надеюсь, он работает сейчас. – Klark

1

Ваш вопрос чувствует себя немного как вопрос домашнее задание из-за чего я только предлагаю подход:

void print_combinations_internal(
    std::string const& str, 
    std::string & prefix, 
    int start_at, 
    int remaining_levels) 
{ 
    if (remaining_levels<=0) { 
     cout << prefix << '\n'; 
    } else { 
     ... 
     loop/recursive call 
     ... 
    } 
} 

void print_combinations(const std::string &str, int length) 
{ 
    std::string temp; // initially empty 
    print_combinations_internal(str,temp,0,length); 
} 
+0

Это не вопрос домашней работы. –

+0

@awakeFromNib: Тем не менее, этот ответ должен помочь вам начать работу. Где весело копировать решение? – sellibitze

Смежные вопросы