问题引出:对于一个序列,如果需要知道其全排列有多少种方案,我们可以很快地用数学知识求得全排列后的子排列方案数目,但是如果需要全部罗列出来那些全排列的结果,那么怎么实现呢?
问题分析:如果给出一个序列,如何枚举出其全排后的子序列?下面通过分析序列“1234”,给出其全排列。
- 首先我们排列出第一个数,如果我们第一次选择1,那么后面的步骤则是全排列“234”;如果是2,那么后面的步骤则是全排列“134”;如果是3,那么后面的步骤则是全排列“214”;如果是4,那么后面的步骤则是全排列“231”。(此处隐晦地指出每一次的如果之前的序列都是“1234”,所以实现的时候当本次全排列结束后,需要将序列恢复至原序列的顺序)
- 排好第一个数后,后面的部分很容易知道使用相同的方法来实现,因此本算法使用递归比较容易实现。
sort.h
#pragma once #include <iostream> #include <stdio.h> namespace sos { namespace math { size_t Factorial(size_t n); } template<typename T> void Swap(T& a, T&b) { T t = a; a = b; b = t; } namespace sort { template<typename T> void FullArray(T* pData, size_t nLen, T* pp=NULL) { T* pRst = pp==NULL? pData:pp; if (nLen == 1) { static size_t nCount = 0; printf("%-8d %s\n", ++nCount, pRst); } for (size_t i = 0; i < nLen; i++) { Swap(pData[0], pData[i]); FullArray(pData + 1, nLen - 1, pRst); Swap(pData[0], pData[i]); } } } }
sort.cpp#include "sort.h" size_t sos::math::Factorial(size_t n) { size_t nRst = 1; while (n > 1) { nRst *= n--; } return nRst; }
main.cpp#include "sort.h" #include <stdio.h> int main() { char p[]="1234"; size_t nLen = sizeof(p) / sizeof(p[0]) - 1; sos::sort::FullArray(p, nLen); printf("get %d subsort\n", sos::math::Factorial(nLen)); return 0; }
运行结果: