static int recurseCombinations(int array[], int arraySize, int combi[], int combiSize, int arrayIdx, int combiEleIdx, int ***combis, int *combiIdx) { // combination with size ‘combiSize‘ is selected if (combiEleIdx == combiSize) { if (*combis != NULL) { (*combis)[*combiIdx] = (int *)malloc(sizeof(int) * combiSize); for (int i = 0; i < combiSize; i++) { // printf("%d ", combi[i]); (*combis)[*combiIdx][i] = combi[i]; } // printf("\n"); *combiIdx = *combiIdx + 1; } return 1; } int combisCnt = 0; for (int i = arrayIdx; i < arraySize - (combiSize - combiEleIdx) + 1; i++) { combi[combiEleIdx] = array[i]; combisCnt += recurseCombinations(array, arraySize, combi, combiSize, i + 1, combiEleIdx + 1, combis, combiIdx); } return combisCnt; } CombinationResults *combinations(int array[], int arraySize, int combiSize) { int **combis = NULL; int combiCnt = 0; int combiIdx = 0; int arrayIdx = 0; int combiEleIdx = 0; int *combi = (int *)calloc(combiSize, sizeof(int)); combiCnt = recurseCombinations(array, arraySize, combi, combiSize, arrayIdx, combiEleIdx, &combis, &combiIdx); // printf("count of combinations: %d\n", combiCnt); combis = (int **)calloc(combiCnt, sizeof(int *)); combiCnt = recurseCombinations(array, arraySize, combi, combiSize, arrayIdx, combiEleIdx, &combis, &combiIdx); free(combi); return combinationResults_init(combis, combiSize, combiCnt); } static void _test_Combinations() { int array[] = {0, 1, 2, 3, 4, 5}; int arraySize = sizeof(array) / sizeof(int); for (int i = 1; i <= 6; i++) { CombinationResults *cr = combinations(array, arraySize, i); combinationResults_print(cr); combinationResults_destroy(cr); } }
里面的 "CombinationResults" 是一个用于存储组合结果的一个数据结构,仅仅是用于包装结果的,不必过分关注。
另外,由于C语言不支持其他语言里的List,所以我把这个求组合的过程做了两遍,第一遍算有多少个组合,第二遍再把结果存进去 .... 不过之前在其他论坛上看到 “如果你真的需要在C里用List,就别再用C了”啊哈哈
递归法输出一个不包含重复元素的数组的全部组合(简单直观的枚举,没有用DFS之类的。因为并不需要)
原文:https://www.cnblogs.com/atoshdustosh/p/14603440.html