字符串的全排列

说明:转载请注明出处http://blog.csdn.net/yuanwei1314/article/details/40897795

 

题目:

输入一个字符串,打印出该字符串中字符的所有排列。

例如输入字符串abc,则输出由字符a、b、c 所能排列出来的所有字符串

abc、acb、bac、bca、cab 和 cba。

 

思路一:递归求解

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*说明:采用递归求解
  如求"abc",则先固定a,交换bc
  求b,则交换ac,时间复杂度O(n^2)
  优化了含有重复字符串的问题
*/
#define swap(x, y)\
    {\
        char tmp = x;\
        x = y;\
        y = tmp;\
    }
/*检查从begin到end中是否包含end字符串*/
bool isReapet(char* S, int begin, int end)
{
    int i;
    
    for (i=begin; i<end; i++)
    {
        if (S[begin] == S[end])
        {
            return false;
        }
    }
    return true;
}
void getAllPermutation(char* S, int begin, int end)
{
    int i;
    
    /*找到一组输出*/
    if (begin == end)
    {
        printf("%s\n", S);
        return;
    }
    
    for (i=begin; i<end; i++)  /*begin和第i个字符交换得到新序列*/
    {
        if (!isReapet(S, begin, i))  /*如果当前检查的字符在之前已经有过,则不交换*/
        {
            continue;
        }
       swap(S[begin], S[i]);
       getAllPermutation(S, i+1, end);
       swap(S[i], S[begin]);
    }
}
int main()
{
    char s[] = "aac";
    getAllPermutation(s, 0, strlen(s));
    return 0;
}


 

思路二:字典序列求解

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*采用字典排序求解,方法如下:
- 找到排列中最后(最右)一个升序的首位位置i,x = ai
- 找到排列中第i位右边最后一个比ai 大的位置j,y = aj
- 交换x,y
- 把第(i+ 1)位到最后的部分翻转
*/
/*交换high与low之间的字符串*/
void reverse(char* S, int low, int high)
{
    char tmp;
   while (low < high)
   {
       tmp = S[low];
       S[low] = S[high];
       S[high] = tmp;
       low++;
       high--;
   }
}
bool Next_permutation(char *S, int N)
{
    int i;
    int j;
    int end = 0;
    int begin = 0;
    
    /*从后往前找到一个点作为基准点*/
    for (i=N-2; i>=0; i--)
    {
       /*找到一个升序,则可以交换*/
       if (S[i] < S[i+1])
       {
           begin = i;
           break;
       }
    }
    
    /*如果都已经排序完成,则结束整个查找*/
    if (i < 0)
    {
        return false;
    }
    
    /*找到第一个比升序更大的数值*/
    for (j=N-1; j>i; j--)
    {
        if (S[j] > S[begin])
        {
            end = j;
            break;
        }
    }
   // printf("begin %d, end %d\n", begin, end);
    reverse(S, begin, end);
    return true;
}
/*快速排序一次后得到的索引值*/
int partition(char* S, int low, int high)
{
    int tmp = S[low]; /*用low作为枢纽*/
    
    while (low < high)
    {
        while (low<high && S[high]>=tmp)/*将小部移到左端*/
        {
            high--;
        }
        S[low] = S[high];
        while (low<high && S[low]<=tmp)/*将大部移到右端*/
        {
            low++;
        }
        S[high] = S[low];
    }
    S[low] = tmp;
    return low;
}
/*快速排序法*/
void qSort(char* S, int low, int high)
{
    int mid;
    
    if (low < high)
    {
        mid = partition(S, low, high);
        qSort(S, low, mid-1);
        qSort(S, mid+1, high);
    }
}
int main()
{
    char s[] = "333";
    bool res;
    qSort(s, 0, strlen(s)-1);
    do
    {
       printf("%s\n", s);
    }while(Next_permutation(s, strlen(s)));
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值