• 用程序实现全排列(一)


    问题描述:

    给定一个整数n,按字典序打印出1-n的所有全排列

    问题解答:

    1.用C++里的next_permutation函数

    函数定义如下:

    template<class BidirectionalIterator>
    bool next_permutation(
          BidirectionalIterator _First, 
          BidirectionalIterator _Last
    );
    template<class BidirectionalIterator, class BinaryPredicate>
    bool next_permutation(
          BidirectionalIterator _First, 
          BidirectionalIterator _Last,
          BinaryPredicate _Comp
     );

    函数实现的原理:

    从序列的最后一个元素开始向前扫描,直到找到两个位置上相邻的元素*i,*j(i,j为下标,j = i+1)且*i<*j,再从尾端找一个元素*k,*i<*k,将*i与*k交换,并将*j及之后的元素全部倒置

    证明:

    设给定序列为a1a2...aiai+1ai+2...an,且ai,ai+1为逆序扫描第一个找到的正序,则有ai < ai+1 > ai+2 > ai+3 > ... > an,

    ①假设ai > ak (∀k∈{i+2,...n}),那么直接交换ai与ai+1,设所得序列为a1'a2'...ai'ai+1'ai+2' ... an',那么a1'=a1...ai-1'=ai,ai' = ai+1,ai+1'=ai,ai+2'=ai+2,...,an'=an

    再将ai+1'及之后的元素逆置一下,就可以得到ai+1'及之后字符的集合组成的串的最小字典序排列

    为什么这种是最小的呢?

    首先,如果改变ai之前的字符任意使得字典序变得更大,那么显然要比上述方法得到的字符串a1'...an'字典序要大;

    又ai+1及之后的串已经是完全逆序,所以只改变这部分得到的字符串字典序不会更大;

    ②假设存在k∈{i+2..n},使得ai<ak,证明类似

    ps:注意边界条件:当字符串已经为完全逆序(达到字典序最大)时,没有next_permutation

    函数代码:

    template<class BidirectionalIterator>
    bool next_permutation(
          BidirectionalIterator first, 
          BidirectionalIterator last
    )
    {
        if(first == last)
            return false; //空序列
    
        BidirectionalIterator i = first;
        ++i;
        if(i == last)
            return false;  //一个元素,没有下一个序列了
        
        i = last;
        --i;
    
        for(;;) {
            BidirectionalIterator ii = i;
            --i;
            if(*i < *ii) {
                BidirectionalIterator j = lase;
                while(!(*i < *--j));
    
                iter_swap(i, j);
                reverse(ii, last);
                return true;
            }
            
            if(i == first) {
                reverse(first, last);  //全逆向,即为最小字典序列,如cba变为abc
                return false;
            }
        }
    
    }
    

    使用:

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<string.h>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    int main()
    {
        int Array[5] = {1,2,3,4,5};
        for(int i = 0; i < 5; ++i)
        {
            printf("%d	",Array[i]);
        }
        printf("
    ");
        while(next_permutation(Array,Array + 5))
        {
            for(int i = 0; i < 5; ++i)
            {
                printf("%d	",Array[i]);
            }
            printf("
    ");
        }
        return 0;
    }    
  • 相关阅读:
    用 WP7开发包 安装 WP7程序(XAP文件)
    在Windows 2003,XP上安装Windows Phone 7开发工具
    AutoResetEvent实现单并发控制
    .net源码研究(1)HashTable
    聚簇索引(Clustered Index)和非聚簇索引 (Non Clustered Index)
    信号量(semaphore)支持 多并发(n>=1)同步锁
    AtlasControlToolkit应用点滴(一)
    依赖注入dependency injection
    AtlasControlToolkit.CascadingDropDownNameValue自定义用法
    Thread.Join
  • 原文地址:https://www.cnblogs.com/warmfrog/p/3645733.html
Copyright © 2020-2023  润新知