C语言中如何将带重复的9选3全排列存储为二维数组?
修正带重复的10选3全排列存储代码及优化建议
我正在编写生成带重复的10选3全排列的程序,以下代码可正常打印排列结果:
#include <stdio.h> int main() { for (int i = 0; i <= 9; i++) { for (int j = 0; j <= 9; j++) { for (int k = 0; k <= 9; k++) { printf("%d,%d,%d\n", i, j, k); } } } return 0; }
但我希望将每个含3个元素的排列存储到一个二维数组中而非直接打印,尝试编写的以下代码无法正常运行:
int main() { int permutas[511][2]; for (int i = 0; i <= 9; i++) { for (int j = 0; j <= 9; j++) { for (int k = 0; k <= 9; k++) { for (int q = 0; q < 512; q++) { permutas[q][0] = i; permutas[q][1] = j; permutas[q][2] = k; } } } } return 0; }
不知如何修正该代码,同时希望获取代码优化的相关建议。
错误分析
你的代码存在两个核心问题:
- 数组定义错误:
- 带重复的10选3全排列总数是
10*10*10=1000组,你定义的数组大小[511][2]完全不符合需求:行数仅512个(索引0到511),远小于实际需要的1000;列数为2,无法存储每组的3个元素,正确的数组定义应为[1000][3]。
- 带重复的10选3全排列总数是
- 循环逻辑错误:
- 内层的
q循环会在每一组i,j,k生成时覆盖数组的所有位置,最终所有元素都会被最后一组9,9,9覆盖。正确做法是用一个计数器变量,每生成一组排列就存入数组对应索引位置,再将计数器自增。
- 内层的
修正后的代码
#include <stdio.h> #define TOTAL_PERMUTATIONS 1000 // 10^3=1000,总排列数 #define PERMUTATION_LENGTH 3 // 每组排列的元素个数 int main() { // 定义足够大小的二维数组存储所有排列 int permutas[TOTAL_PERMUTATIONS][PERMUTATION_LENGTH]; // 计数器,记录当前要存储的数组索引 int count = 0; for (int i = 0; i <= 9; i++) { for (int j = 0; j <= 9; j++) { for (int k = 0; k <= 9; k++) { // 将当前排列存入数组对应位置 permutas[count][0] = i; permutas[count][1] = j; permutas[count][2] = k; // 计数器自增,准备存储下一组 count++; } } } // 可选:打印验证结果是否正确 for (int idx = 0; idx < TOTAL_PERMUTATIONS; idx++) { printf("%d,%d,%d\n", permutas[idx][0], permutas[idx][1], permutas[idx][2]); } return 0; }
代码优化建议
- 用宏定义常量:像示例中那样把总排列数、每组元素长度定义为宏,后续修改数字范围或排列长度时,只需修改宏定义即可,避免多处修改出错。
- 动态分配内存:如果排列总数很大(比如10选10),栈内存可能不足,此时可以用
malloc动态分配内存,使用完毕后记得释放:int** permutas = malloc(TOTAL_PERMUTATIONS * sizeof(int*)); for (int i = 0; i < TOTAL_PERMUTATIONS; i++) { permutas[i] = malloc(PERMUTATION_LENGTH * sizeof(int)); } // 使用完成后释放内存 for (int i = 0; i < TOTAL_PERMUTATIONS; i++) { free(permutas[i]); } free(permutas); - 封装成独立函数:将生成排列的逻辑封装成函数,方便复用和维护,比如:
void generatePermutations(int** result, int numChoices, int length) { int count = 0; // 这里针对长度为3的情况,若要支持可变长度可改用递归 for (int i = 0; i < numChoices; i++) { for (int j = 0; j < numChoices; j++) { for (int k = 0; k < numChoices; k++) { result[count][0] = i; result[count][1] = j; result[count][2] = k; count++; } } } } - 支持可变长度排列:如果需要生成任意长度的带重复全排列,建议用递归实现,避免嵌套循环的局限性(比如长度为n时需要n层循环)。
内容的提问来源于stack exchange,提问作者Matin Gomez-Pablos
相关产品推荐
相关产品推荐

