多重集的全排列

来源:互联网 发布:如何查看本机端口号 编辑:程序博客网 时间:2024/04/29 12:32

C++STL做法:(估计用这个,要被老师批!!!)

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;


int main()
{
    string str;
    cin >> str;
    do
    {
        cout << str<<endl;
        
    }
    while(next_permutation(str.begin(),str.end()));
    return 0;
}

c语言递归做法:

思路:

从右向左找到第一个左边比右边小的数,记录其(左边)位置pos1,再从右向左找到第一个比pos1位置大的数。

 交换pos1 pos2两位置处的数,把pos1后面的字符串都反转即可。。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
//const int N = 100;   //C++里才这样用,混了
#define N 100
char str[N];
void swap(int p1,int p2)
{
    char tmp ;
    tmp = str[p1];
    str[p1] = str[p2];
    str[p2] = tmp;
}
void solve()
{
    int i;
    int pos1,pos2;
    int n = strlen(str);
 ///从右向左找到第一个左边比右边小的数,记录其(左边)位置pos1
    for(i = n-1; i >= 0; i--)
    {
        if(0 == i)
        {
            return ;
        }
        if(str[i] > str[i-1])
        {
            pos1 = i-1;
            break;
        }
    }
    ///从右向左找到第一个比pos1位置大的数
    for(i = n-1; i>= pos1; i--)
    {
        if(str[i] > str[pos1])
        {
            pos2 = i;
            break;
        }
    }


    ///交换pos1 pos2两位置处的数
    swap(pos1,pos2);

  ///把pos1后面的字符串都反转
    for(i = n-1; i > pos1; i--)
    {
        ///因为pos1原来记录的是,从右向左查找,得到的第一个左边比右边小,小的那个数的位置
        swap(i,++pos1);
    }
    for(i = 0; i <= n-1; i++)
    {
        printf("%c",str[i]);
    }
    printf("\n");
    solve(); ///因为str[]数组是全局的,所以直接solve()即可
}
int main()
{
    clock_t  start,end;
    scanf("%s",str);
    start = clock();
    solve();
    end = clock();
    printf("用时: %f (S)\n",(double)(end-start)/CLOCKS_PER_SEC);
    return 0;
}