非递归全排列实现
<span style="font-size:18px;">#include<iostream>
#include<functional>
#include<algorithm>
#include<iterator>
#include<vector>
#include<string>
#include<bitset>
#include<cassert>
using namespace std;
const int MAX_SIZE = 1000;
/*
寻找下一个排列
假设 某个序列为 d1 d2 d3 ... dn
那么在dn前找第一个 比dn小的元素 那么序列被分为两段 假设为di
d1 d2 d3 ... di ... dn 我们只分析 di-dn 因为前边不会影响结果
那么我们可以肯定的是 d(i+1)-d(n)一定是 一个最大字典序 即按字典排序的递减序列
继而 dn为该序列中最小元素 将di与dn交换(因为从d(i+1)-dn已经没有下一个排列了)
现在得到的新序列 d(i') d(i+1) ... d(n') 那么我们是否可以保证这个序列就是下一个序列呢?
答案是不能 因为此时d(i+1)-d(n')也是一个最大字典序列(d(n')最小)。所以将(i+1)-n
逆序便会使之变为最小 最后得到下一个排列。这其中有进位的思想。
当这个序列不存在这样的逆序对时,说明不存在下一个序列。
这个思想和STL中的思想相似 但是STL中找的是相邻元素在有重复元素存在时 就会找出重复的排列
*/
template<class T>
void Display(const vector<T>& vec)
{
copy(vec.begin(), vec.end(), ostream_iterator<T>(cout, " "));
cout << endl;
}
template<class T, class T1 = T, class Ret = bool>//类模板缺省参数
class Compare :public binary_function<T, T1, Ret>
{
public:
bool operator()(const T& val1, const T1& val2)const
{
switch (m_op)
{
case '<':
return val1 < val2;
break;
case '>':
return val1 > val2;
break;
default:
return false;
}
}
Compare(const char op = '<')
{
m_op = op;
}
private:
char m_op;
};
//当然我们完全可以 不使用函数对象 直接传递一个参数(但是我们是想办法不让函数去做判断
//而是让外部去判断,那样需要修改时直接修改这个组件对象便可,传入less<int>() 或者greater<int>()也是可以的。)
template<class T>
bool GetPermutation(vector<T>& vec, const Compare<T> Com)
{
if (0 == vec.size() || 1 == vec.size())
{
return false;
}
int first = 0;
int last = vec.size() - 1;
int prev = last;
int next = last;
--prev;
while (first != next)
{
next = last;
while (prev != next)
{
if (Com(vec[prev], vec[next]))
{
swap(vec[prev], vec[next]);
reverse(vec.begin() + prev + 1, vec.end());
return true;
}
--next;
}
--prev;
}
return false;
}</span><pre name="code" class="cpp"><span style="font-size:18px;">int main(void)
{</span>
<span style="font-size:18px;">
vector<int> vec = { 1,2,2,3 };
Display(vec);</span>
<span style="font-size:18px;"><span style="white-space:pre"> </span>//可以先进行排序 不想排序就需要调用两个函数
while (GetPermutation(vec, Compare<int>('<')))
{
Display(vec);
}
return 0;
}</span>