c++字符串全排列递归法

网上关于字符串全排列的代码一大堆,总体而言分为递归法和非递归法两种实现。虽然递归法原理简单,代码简洁,但是我观察众多博客来看,没有把代码讲透,只有透过代码才能看清算法的本质。

问题:输入一字符串(要求不存在重复字符),打印出该字符串中字符中字符的所有排列。
例如:输入”abc”,输出结果为abc, acb, bac, bca, cab和cba。

递归思路:看成两步:

1、首先求所有可能出现在第一个位置的字符,可以把第一个字符和后面的字符一次交换;
2、固定第一个字符后,求后面字符的全排列,过程类似第一个字符的取法,即递归调用

也可以这么理解,f(abc) = a + f(bc), f(bc) = b + f(c),

讲了基本的思想,我们还是重点来看代码(这是网上摘抄,非作者本人所写),通过代码就能很好的理解了。

#include<iostream> 
using namespace std;  
#include<assert.h> 

void Permutation(char* sourceStr, char* changeStr)  
{  
    assert(sourceStr && changeStr);//断言,防止越界 

    if(*changeStr== '\0')  
        printf("%s\n",sourceStr);//如果没有可交换字母,已经到末尾,将源字符串输出 
    else  
    {  
    //比如源字符串当前是sourceStr="abc",交换字符串也为changeStr="abc",
    //需要注意的是,函数void Permutation(str,str)传的是指向同一个字符串的指针
        for(char* pCh = changeStr; *pCh != '\0'; pCh++)  
        {  
            swap(*changeStr,*pCh);//交换第一个和后面一个 
            Permutation(sourceStr, changeStr+1);//固定前面的,后面再排列 
            swap(*changeStr,*pCh);//再换回原来的 
        }  
    }
    //一次完整的打印是这样的,首先sourceStr、changeStr都指向"abc",接着swap第一个,结果还是"abc",
//这个时候就会输出'abc'。接着会退回的固定'a','b'和'c'进行交换,这个时候//sourceStr="acb",经过后面全排列后,又会换回来,这样"acb"也就打印出来 
}  

int main(void)  
{  
    char str[] = "abc";  
    Permutation(str,str);  
    return 0;  
}  

自己可以画图,将流程走一遍,或者设置断点调试,就能清楚的看到实现的机制了。

点赞