如何在不使用递归的情况下找到字符串的所有排列?

发布于 2024-08-02 08:28:53 字数 742 浏览 5 评论 0原文

有人可以帮我解决这个问题吗:这是一个查找任意长度字符串的所有排列的程序。需要相同的非递归形式。 (最好是C语言实现)

using namespace std;

string swtch(string topermute, int x, int y)
{
  string newstring = topermute;
  newstring[x] = newstring[y];
  newstring[y] = topermute[x]; //avoids temp variable
  return newstring;
}

void permute(string topermute, int place)
{
  if(place == topermute.length() - 1)
  {
    cout<<topermute<<endl;
  }
  for(int nextchar = place; nextchar < topermute.length(); nextchar++)
  {
    permute(swtch(topermute, place, nextchar),place+1);
  }
}

int main(int argc, char* argv[])
{    
  if(argc!=2)    
  {
    cout<<"Proper input is 'permute string'";
    return 1;
  }
  permute(argv[1], 0);
  return 0;    
}

Can someone help me with this: This is a program to find all the permutations of a string of any length. Need a non-recursive form of the same. ( a C language implementation is preferred)

using namespace std;

string swtch(string topermute, int x, int y)
{
  string newstring = topermute;
  newstring[x] = newstring[y];
  newstring[y] = topermute[x]; //avoids temp variable
  return newstring;
}

void permute(string topermute, int place)
{
  if(place == topermute.length() - 1)
  {
    cout<<topermute<<endl;
  }
  for(int nextchar = place; nextchar < topermute.length(); nextchar++)
  {
    permute(swtch(topermute, place, nextchar),place+1);
  }
}

int main(int argc, char* argv[])
{    
  if(argc!=2)    
  {
    cout<<"Proper input is 'permute string'";
    return 1;
  }
  permute(argv[1], 0);
  return 0;    
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

人疚 2024-08-09 08:28:53

另一种方法是分配一个 n! 的数组。 char 数组并以与手动填充相同的方式填充它们。

如果字符串是“abcd”,则将前 n-1 个字符中的所有“a”字符放在位置 0 中!数组,在位置 1 为下一个 n-1!数组等。然后将前 n-2 个所有“b”字符放在位置 1 中!数组等,前 n-3 个位置 2 中的所有“c”字符!数组等,以及前 n-4 个位置 3 中的所有“d”字符!数组等,在填充数组时,在每种情况下都使用模 n 算术从位置 3 移动到位置 0。

不需要交换,并且您很早就知道是否有足够的内存来存储结果。

Another approach would be to allocate an array of n! char arrays and fill them in the same way that you would by hand.

If the string is "abcd", put all of the "a" chars in position 0 for the first n-1! arrays, in position 1 for the next n-1! arrays, etc. Then put all of the "b" chars in position 1 for the first n-2! arrays, etc, all of the "c" chars in position 2 for the first n-3! arrays, etc, and all of the "d" chars in position 3 for the first n-4! arrays, etc, using modulo n arithmetic in each case to move from position 3 to position 0 as you are filling out the arrays.

No swapping is necessary and you know early on if you have enough memory to store the results or not.

抹茶夏天i‖ 2024-08-09 08:28:53

与您的代码等效的基于堆栈的非递归:

#include <iostream>
#include <string>

struct State
{
    State (std::string topermute_, int place_, int nextchar_, State* next_ = 0)
        : topermute (topermute_)
        , place (place_)
        , nextchar (nextchar_)
        , next (next_)
    {
    }

    std::string topermute;
    int place;
    int nextchar;

    State* next;
};

std::string swtch (std::string topermute, int x, int y)
{
    std::string newstring = topermute;
    newstring[x] = newstring[y];
    newstring[y] = topermute[x]; //avoids temp variable

    return newstring;
}

void permute (std::string topermute, int place = 0)
{
    // Linked list stack.
    State* top = new State (topermute, place, place);

    while (top != 0)
    {
        State* pop = top;
        top = pop->next;

        if (pop->place == pop->topermute.length () - 1)
        {
            std::cout << pop->topermute << std::endl;
        }

        for (int i = pop->place; i < pop->topermute.length (); ++i)
        {
            top = new State (swtch (pop->topermute, pop->place, i), pop->place + 1, i, top);
        }

        delete pop;
    }
}

int main (int argc, char* argv[])
{
    if (argc!=2)    
    {
        std::cout<<"Proper input is 'permute string'";
        return 1;
    }
    else
    {
        permute (argv[1]);
    }

    return 0;
}

我尝试使其类似于 C,并避免使用 c++ STL 容器和成员函数(不过为了简单起见,使用了构造函数)。

请注意,排列是按与原始排列相反的顺序生成的。

我应该补充一点,以这种方式使用堆栈只是模拟递归。

A stack based non-recursive equivalent of your code:

#include <iostream>
#include <string>

struct State
{
    State (std::string topermute_, int place_, int nextchar_, State* next_ = 0)
        : topermute (topermute_)
        , place (place_)
        , nextchar (nextchar_)
        , next (next_)
    {
    }

    std::string topermute;
    int place;
    int nextchar;

    State* next;
};

std::string swtch (std::string topermute, int x, int y)
{
    std::string newstring = topermute;
    newstring[x] = newstring[y];
    newstring[y] = topermute[x]; //avoids temp variable

    return newstring;
}

void permute (std::string topermute, int place = 0)
{
    // Linked list stack.
    State* top = new State (topermute, place, place);

    while (top != 0)
    {
        State* pop = top;
        top = pop->next;

        if (pop->place == pop->topermute.length () - 1)
        {
            std::cout << pop->topermute << std::endl;
        }

        for (int i = pop->place; i < pop->topermute.length (); ++i)
        {
            top = new State (swtch (pop->topermute, pop->place, i), pop->place + 1, i, top);
        }

        delete pop;
    }
}

int main (int argc, char* argv[])
{
    if (argc!=2)    
    {
        std::cout<<"Proper input is 'permute string'";
        return 1;
    }
    else
    {
        permute (argv[1]);
    }

    return 0;
}

I've tried to make it C-like and avoided c++ STL containers and member functions (used a constructor for simplicity though).

Note, the permutations are generated in reverse order to the original.

I should add that using a stack in this way is just simulating recursion.

那些过往 2024-08-09 08:28:53

第一个建议 - 不要按值传递 std:string 参数。使用const引用

string swtch(const string& topermute, int x, int y)
void permute(const string & topermute, int place)

会节省你很多不必要的复制。

对于 C++ 解决方案,algorithm 标头中有函数 std::next_permutationstd::prev_permutation 。所以你可以这样写:

int main(int argc, char* argv[])
{    
  if(argc!=2)    
  {
    cout<<"Proper input is 'permute string'" << endl;
    return 1;
  }
  std::string copy = argv[1];
  // program argument and lexically greater permutations
  do
  {
    std::cout << copy << endl;
  } 
  while (std::next_permutation(copy.begin(), copy.end());

  // lexically smaller permutations of argument
  std::string copy = argv[1];
  while (std::prev_permutation(copy.begin(), copy.end())
  {
    std::cout << copy << endl;
  }
  return 0;    
}

对于 C 解决方案,你必须将变量类型从 std::string 更改为 char * (呃,你必须正确管理内存)。我认为类似的方法(编写

int next_permutation(char * begin, char * end);
int prev_permutation(char * begin, char * end);

与 STL 函数具有相同语义的函数)也可以。您可以找到 std::next_permutation 的源代码及其说明 在这里。我希望你能设法编写一个适用于 char * 的类似代码(顺便说一句,std::next_permutation 可以毫无问题地使用 char *,但你想要 C 解决方案),因为我懒得自己做:-)

First one advice - don't pass std:string arguments by value. Use const references

string swtch(const string& topermute, int x, int y)
void permute(const string & topermute, int place)

It will save you a lot of unnecessary copying.

As for C++ solution, you have functions std::next_permutation and std::prev_permutation in algorithm header. So you can write:

int main(int argc, char* argv[])
{    
  if(argc!=2)    
  {
    cout<<"Proper input is 'permute string'" << endl;
    return 1;
  }
  std::string copy = argv[1];
  // program argument and lexically greater permutations
  do
  {
    std::cout << copy << endl;
  } 
  while (std::next_permutation(copy.begin(), copy.end());

  // lexically smaller permutations of argument
  std::string copy = argv[1];
  while (std::prev_permutation(copy.begin(), copy.end())
  {
    std::cout << copy << endl;
  }
  return 0;    
}

As for C solution, you have to change variables types from std::string to char * (ugh, and you have to manage memory properly). I think similar approach - writing functions

int next_permutation(char * begin, char * end);
int prev_permutation(char * begin, char * end);

with same semantics as STL functions - will do. You can find source code for std::next_permutation with explanation here. I hope you can manage to write a similar code that works on char * (BTW std::next_permutation can work with char * with no problems, but you wanted C solution) as I am to lazy to do it by myself :-)

梦里寻她 2024-08-09 08:28:53

您尝试过使用STL吗?有一种名为 next_permutation 的算法,给定一个范围,每次后续调用都会返回 true,直到遇到所有排列为止。不仅适用于字符串,还适用于任何“序列”类型。

http://www.sgi.com/tech/stl/next_permutation.html

Have you tried using the STL? There is an algorithm called next_permutation which given a range will return true on each subsequent call until all permutations have been encountered. Works not only on strings but on any "sequence" type.

http://www.sgi.com/tech/stl/next_permutation.html

梨涡 2024-08-09 08:28:53

这样就不用递归就解决了问题。唯一的问题是,如果字符串中的字符重复,它将生成重复的输出。

#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<string.h>
int factorial(int n)
{
    int fact=1;
    for(int i=2;i<=n;i++)
        fact*=i;
    return fact;
}
char *str;
void swap(int i,int j)
{
    char temp=str[i];
    str[i]=str[j];
    str[j]=temp;
}
void main()
{
    clrscr();
    int len,fact,count=1;
    cout<<"Enter the string:";
    gets(str);
    len=strlen(str);
    fact=factorial(len);
    for(int i=0;i<fact;i++)
    {
        int j=i%(len-1);
        swap(j,j+1);
        cout<<"\n"<<count++<<". ";
        for(int k=0;k<len;k++)
            cout<<str[k];
    }
    getch();
}

This solves the problem without recursion. The only issue is that it will generate duplicate output in the case where a character is repeated in the string.

#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include<string.h>
int factorial(int n)
{
    int fact=1;
    for(int i=2;i<=n;i++)
        fact*=i;
    return fact;
}
char *str;
void swap(int i,int j)
{
    char temp=str[i];
    str[i]=str[j];
    str[j]=temp;
}
void main()
{
    clrscr();
    int len,fact,count=1;
    cout<<"Enter the string:";
    gets(str);
    len=strlen(str);
    fact=factorial(len);
    for(int i=0;i<fact;i++)
    {
        int j=i%(len-1);
        swap(j,j+1);
        cout<<"\n"<<count++<<". ";
        for(int k=0;k<len;k++)
            cout<<str[k];
    }
    getch();
}
街角迷惘 2024-08-09 08:28:53
#include <iostream>
#include <string>

using namespace std;

void permuteString(string& str, int i)
{
    for (int j = 0; j < i; j++) {
        swap(str[j], str[j+1]);
        cout << str << endl;
    }
}

int factorial(int n)
{
    if (n != 1) return n*factorial(n-1);
}

int main()
{
    string str;

    cout << "Enter string: ";
    cin >> str;

    cout << str.length() << endl;

    int fact = factorial(str.length());

    int a = fact/((str.length()-1));

    for (int i = 0; i < a; i++) {
        permuteString(str, (str.length()-1));
    }   
}
#include <iostream>
#include <string>

using namespace std;

void permuteString(string& str, int i)
{
    for (int j = 0; j < i; j++) {
        swap(str[j], str[j+1]);
        cout << str << endl;
    }
}

int factorial(int n)
{
    if (n != 1) return n*factorial(n-1);
}

int main()
{
    string str;

    cout << "Enter string: ";
    cin >> str;

    cout << str.length() << endl;

    int fact = factorial(str.length());

    int a = fact/((str.length()-1));

    for (int i = 0; i < a; i++) {
        permuteString(str, (str.length()-1));
    }   
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文