排列组合代码(不同元素)

来源:互联网 发布:阿里云存储服务 个人 编辑:程序博客网 时间:2024/06/17 20:06
一、测试函数
只针对不同元素。
int main(int argc, _TCHAR* argv[]){vector<vector<int>> groups;// 组合/*for (int i = 0; i < 5; i++){combination(5, i, groups);}*/// 排列 递归//permutation2(5, groups);// 排列 非递归permutation(5, groups);for (int i = 0; i < groups.size(); i++){vector<int> &group = groups[i];for (int j = 0; j < group.size(); j++){cout << group[j] + 1 << " ";}cout << '\n';}cout << endl;return 0;}


二、组合
1、数组:{1, 2, 3}
2、组合:
{1}
{2}
{3}
{1, 2}
{1, 3}
{2, 3}
{1, 2, 3}
3、代码:
/* * 排列组合 * 从N个元素中选取M个元素组合 */void combination(int maxLen, int len, vector<vector<int>> &groups){if (len > maxLen || len < 0 || maxLen < 0) return;// 初始化group,保存最初组合0, 1, 2, 3...vector<int> group(len);for (int i = 0; i < group.size(); i++) group[i] = i;// index指向第N - 1个元素开始,当该元素值到最大时,--indexint index = group.size() - 1;while (true){groups.push_back(group);// 元素值增加,index指向最后一个“值未达到最大”的元素bool change = false;while (++group[index] > maxLen - len + index){if (!change) change = true;if (--index < 0) break;}// 所有元素值都达到最大if (index < 0) break;// 若index指向改变,将index后面的元素初始化if (change){for (int i = index + 1; i < group.size(); i++){group[i] = group[index] + (i - index);}index = group.size() - 1;}}}


三、排列
数组:{1, 2, 3}
排列: N = 3
{1, 2, 3}
{1, 3, 2}
{2, 1 ,3}
{2, 3, 1}
{3, 1, 2}
{3, 2, 1}

A、递归
void permutation2(int len, vector<vector<int>> &groups){if (len < 0) return;vector<int> group(len);for (int i = 0; i < group.size(); i++) group[i] = i;permutationRecursion(0, len, group, groups);}/* * 全排序 递归 */void permutationRecursion(int begin, int end, vector<int> &group, vector<vector<int>> &groups){if (begin < end){for (int i = begin; i < end; i++){swap(group[begin], group[i]);permutationRecursion(begin + 1, end, group, groups);swap(group[begin], group[i]);}}else{groups.push_back(group);}}void swap(int &x, int &y){int t = x;x = y;y = t;}


B、非递归(数组为元素个数为N的递增数组)
src 是交换元素, dst是被交换元素(src后面第一个比src值大的元素),swap后是需要的结果 groups.push_back()
[N - 3][N - 2][N - 1]123src = N - 2, dst = N - 1, src < dst-> swap(src, dst)-> src >= N - 2-> src = src132src = N - 2, dst = N - 2, src >= dst-> v(src) > v(src - 1)-> reverse(src, N - 1)-> --src123src = N - 3, dst = N - 2, src < dst-> swap(src, dst)-> src < N - 2-> src = N - 2213src = N - 2, dst = N - 1, src < dst-> swap(src, dst)-> src >= N - 2-> src = src231src = N - 2, dst = N - 2, src >= dst-> v(src) > v(src - 1)-> reverse(src, N - 1)-> --src213src = N - 3, dst = N - 1, src < dst-> swap(src, dst)-> src < N - 2-> src = N - 2312src = N - 2, dst = N - 1, src < dst-> swap(src, dst)-> src >= N - 2-> src = src321src = N - 2, dst = N - 2, src >= dst-> v(src) <= v(src - 1)-> --src321src = N - 1, dst = N - 1, src >= dst-> src <= 0-> finish


/* * 全排列 非递归 * 将数组初始化为从小到大递增的状态(0, 1, 2, 3...), * 通过交换使数组的 M->N 部分从递增变成递减({0, 1, 2, 3} -> {0, 1, 3, 2} -> {0, 3, 2, 1} -> {3, 2, 1 ,0}) */void permutation(int len, vector<vector<int>> &groups){if (len < 0) return;// 初始化group,保存最初组合0, 1, 2, 3...vector<int> group(len);for (int i = 0; i < group.size(); i++) group[i] = i;groups.push_back(group);if (group.size() == 1) return;// 每次都从第N - 2个元素开始交换int src = len - 2, dst = 0;int groupMax = group[len - 1];while (true){// 初始化dst,找到src后面第一个比src元素值大的元素dst,使元素大的始终在元素小的前面dst = src;for (int i = src; i < len; i++){if (group[i] > group[src]){dst = i;break;}}if (dst > src)// 找到元素值大的dst,进行交换{swap(group[src], group[dst]);if (src < len - 2)// 每次都从 N - 2 开始交换{src = len - 2;}groups.push_back(group);}else{if (src <= 0) break;// 所有元素交换完,使数组 0 -> N - 1 为递减状态// 数组 src -> N - 1 为递减状态,若 src - 1 比 src 小,将 src -> N - 1 变成递增状态,准备将 src - 1 加入递减数组部分if (group[src] > group[src - 1]){// reversefor (int i = src; i < len; i++){if (i >= len - 1 - (i - src)) break;swap(group[i], group[len - 1 - (i - src)]);}}--src;}}}

原创粉丝点击