【cpp】 STL排列组合方法next_permutation 以及 prev_permutation
- 首先排列组合要解决的是什么问题?
高中的时候我们就学过排列组合,{0,1,2,3,4,5,6,7,8,9}, 这些数字每次拿出3个,一共可以拿出多少种组合?
用C3↑10↓ 这种来计算一共有 (10 * 9 * 8) / (3 * 2 * 1) = 120 种拿法 - 在实际的项目中应用
这次项目需要一些设备做一个编码处理 : 把国标编码转换为 16位选4位,这四位是-1或者1,其他12位为0,的数组,所有的可能的组合方式计算下来:
四位-1或者1 的组合一共有 五种组合方式,再搭配上12位0
{-1,-1,-1,-1} 和 12位 0 组合方式:1820
{-1,1,-1,-1} 和 12位 0 组合方式:1820 * c1↑4↓ = 7280
{-1,-1,1,1} 和 12位 0 组合方式:1820 * c2↑4↓ = 10920
{-1,1,1,1} 和 12位 0 组合方式:1820 * c1↑4↓ = 7280
{1,1,1,1} 和 12位 0 组合方式:1820
一共是 29120中组合方式,也就是说可以用{0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1}这样的数组,这样就可以编码 29120种设备
再说回stl的全排列函数next_permutation 以及 prev_permutation
std::vector<float> vec{ 0,1,2,3,4,5 };
do {
for(auto &iter: vec ){
std::cout << iter << " ";
}
std::cout << std::endl;
} while (next_permutation(vec.begin(), vec.begin() + 6));
如果使用上面的代码你会发现{ 0,1,2,3,4,5 } 和 { 5,2,1,3,4,0 },计算出来的排列数是不一样的,使用prev_permutation 和next_permutation 两种,结果也是不同的,这是为什么呢?
原因分析:
next_permutation 这个函数是返回所有 大于当前排列{ 5,2,1,3,4,0 }的所有排列方式,也就是说 { 5,1,2,3,4,0 } 是比{ 5,2,1,3,4,0 } 这种排列要小的,所以不会被返回 { 5,1,2,3,4,0 }这种排列方式
prev_permutation 这个函数是返回所有 小于当前排列{ 5,2,1,3,4,0 }的所有排列方式,也就是说 { 5,3,1,2,4,0 } 是比{ 5,2,1,3,4,0 } 这种排列要大的,所以不会被返回 { 5,3,1,2,4,0 } 这种排列方式
解决办法:
- 要使用next_permutation 的话,我们把{ 5,2,1,3,4,0 } 从小到大排序一下,这样其他所有的排列都比 排序后的{ 0,1,2,3,4,5 }要大,就可以返回所有的了
- 相反的要使用prev_permutation 的话,我们把{ 5,2,1,3,4,0 } 从大到小排序一下,这样其他所有的排列都比 排序后的{ 5,4,3,2,1,0 }要小,就可以返回所有的了
std::vector<float> vec{ 5,2,1,3,4,0 };
std::sort(vec.begin(), vec.end());//默认从小到大排序
do {
for(auto &iter: vec ){
std::cout << iter << " ";
}
std::cout << std::endl;
} while (next_permutation(vec.begin(), vec.begin() + 6));