算法学习之字符串全排列

   第一种方法字符串全排列,思想上和我们高中学的排列一样,比如123,开始的时候第一个位置有三种选择,第一个选完之后第二个位置就只剩下两种选择,第三个位置,就剩一种,所以一共有n!种排列,所以我们可以用递归的思想去做,递归中做交换

#include <stdio.h>
#include <stdlib.h>
#define MAX  50
void swap(char *a,char *b)
{
    char tmp = *a;
    *a = *b;
    *b = tmp;
}
void permutations(char *str,int pos,int n) //pos表示当前位置,n表示字符串的大小
{
    int i;
    if(pos == n)  //如果到最后,说明一次排列完毕,输出排列结果
    {
        for(i = 0; i <= n; i++)
            printf("%c",str[i]);
            printf("\n");
    }
    else
    {
        for(i = pos; i <= n; i++) //让此位置及以后的所有字符和它交换
        {
            swap(&str[pos],&str[i]);
            permutations(str,pos+1,n); //递归进入下一个位置
            swap(&str[pos],&str[i]); //返回的时候再交换回来
        }
    }
}
int main()
{
    char str[MAX];
    scanf("%s",str);
    permutations(str,0,strlen(str)-1);
    return 0;
}
第二种方法,使用字典序全排列,字典序就是按照从小到大的情况排列,比如有三位数123我们假设是百位 十位 个位
则按照字典序排列的话,输出顺序为 123 132  213 231 312 321 ,也就是说,当前数的下一个数必须比它大,并且和它距离最短,这就是字典序排列。

算法描述:1.先将数组从小到大排序

                2.从后往前扫描,找到ai<ai+1的位置,记下此时的i

                3.从后往前扫描,找到第一个大于ai的数,比如ak

                4.交换ai和ak 此时i+1到n排列是从大到小,所以要逆至,变成从小到大

                5.将ai+1以后的数全部逆置,是为了让,变化后的数和上一个距离最短,把越大的数,放的越后,则变化范围最小,也就是二者想减,值最小

                6.重复,2 3 4 5步骤,直到变成最大那个数为止

#include <stdio.h>
#include <stdlib.h>
#define MAX  50
void reverse(char *str,int i)
{
    int n = strlen(str) - 1;
    while(i < n)
    {
        char tmp = str[i];
        str[i++] = str[n];
        str[n--] = tmp;
    }
}
int permutations(char *str,int n)
{
    int i,j;
    for(i = n-1; i >= 0 && str[i] >= str[i+1]; i--) //找到ai < ai+1的位置
    {

    }
    if(i == -1)
        return 0;
    for(j = n; j >=0 && str[j] <= str[i]; j--) //找到最右边大于ai的数
    {

    }
    char tmp = str[i];//交换i,j
    str[i] = str[j];
    str[j] = tmp;
    reverse(str,i+1);//逆至i后面的数
    return 1;
}
int main()
{
    char str[MAX];
    scanf("%s",str);
    int n = strlen(str) - 1;
    while(permutations(str,n))
        printf("%s\n",str);
    return 0;
}



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值