字符串的全排列非递归实现算法

题目类似剑指offer的第28题,这里在粘贴一下:题目:输入一个字符串,打印出该字符串中字符放入所有排列。例如输入字符串abc,则打印出字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。

递归的实现算法:http://blog.csdn.net/moses1213/article/details/51055692

这里用非递归的算法实现:

假设有字符串p1 p2…pj-1pj pj+1…pk-1 pk pk+1…pn ,对字符串进行快速排序,得到所有排列中的最小值,然后寻找下一个排列,下一个排列比当前值大,而且是所有排列中比当前值大的最小排列。直到排列已是最大值,不再寻找下一个排列,此时从最小到最大全部实现,即为字符串的全排列。下面是下一个排列的算法步骤:

(1)从排列的尾部(最右边)开始, 找出第一个比右边相邻数字小的索引j ( j 从首部开始计算), 即j = max{i | pi < pi+1};

(2)在pj 右边的数字中, 找出所有比pj 大的数字中最小的数字的索引k, 即k= max{i | pi > pj};由于pj 右边的数字是从右至左递增的, 因此k 是所有大于pj 的数字中索引最大的;

(3) 交换pj 与pk;

(4) 将pj+1...pk-1, pj, pk+1...pn 翻转得到p的下一个排列p′

算法的证明见:http://www.doc88.com/p-6438124960748.html

#include <iostream>
#include <cstring>
using namespace std;

void Swap(char* a, char* b)
{
    char temp = *a;
    *a = *b;
    *b = temp;
}


void Reverse(char* p1, char* p2)
{
    while(p1 < p2)
        Swap(p1++, p2--);
}


//非递归版本实现
bool NextPermutation(char* pStr)
{
    char* pEnd = pStr + strlen(pStr) - 1;
    char* pSwap = pEnd;
    char* index;
    //寻找替换数
    for(index = pEnd - 1; index >= pStr; --index)
    {
        if(*index < *(index + 1))
        {
            pSwap = index;
            break;
        }
    }
    //pSwap没更新,即不存在这样的替换数,表明已是最大值
    if(pSwap == pEnd)
    <span style="white-space:pre">	</span>return false;
    
    //寻找比*pSwap大的最小数
    char* pMinLarger = pSwap + 1;
    for(index = pMinLarger + 1; index <= pEnd; ++index)
    {
        if(*index > *pSwap && *index <= *pMinLarger)
            pMinLarger = index;
    }
    Swap(pSwap, pMinLarger);
    Reverse(pSwap + 1, pEnd);
    
    return true;
}


int cmp(const void *a,const void *b)  
{  
    return int(*(char *)a - *(char *)b);  
} 


int main(void)  
{  
    char str[] = "13223";
    qsort(str , strlen(str),sizeof(char),cmp);
    do
        cout << str << endl;
    while(NextPermutation(str));
    
    return 0;
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值