我编写了一个简单的算法,以便当用户输入一个int N时,它将创建一个N×N网格,其中同一行或列中没有重复项。该算法有时会使用较低的数字,但通常会引发分段错误。故障发生在设置网格数组元素的行中的noRowDuplicates函数中。
我不确定为什么会发生这种情况,并希望得到任何帮助。提前谢谢!
// Author: Eric Benjamin
// This problem was solved using recursion. fill() is the recursive function.
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
void fillOptions();
void fill(int arrayPosition);
int inputNum;
int gridSize;
int *grid;
int allOptionsSize = 0;
int *allOptions;
int main() {
cout << "Please enter a number!" << endl;
cin >> inputNum;
gridSize = inputNum * inputNum;
grid = new int[gridSize];
allOptions = new int[inputNum];
for (int i = 0; i < inputNum; i++) {
allOptions[i] = i + 1;
allOptionsSize++;
}
srand((unsigned)time(0));
fill(0);
delete[] grid;
delete[] allOptions;
return 0;
}
bool noColumnDuplicates(int arrPosition, int valueToCheck) {
for (int i = 1; i < inputNum; i++) {
if (arrPosition - (inputNum * i) >= 0) {
if (grid[arrPosition - (inputNum * i)] == valueToCheck) {
return false;
}
}
}
return true;
}
bool noRowDuplicates(int arrPosition, int valueToCheck) {
int rowPosition = arrPosition % inputNum; // 0 to num - 1
if (rowPosition > 0) {
for (int p = 1; p < rowPosition + 1; p++) {
if (grid[arrPosition - p] == valueToCheck) {
return false;
}
}
}
return true;
}
void fill(int arrayPosition) {
if (arrayPosition < gridSize) {
int randomPosition = rand() % allOptionsSize;
grid[arrayPosition] = allOptions[randomPosition];
if (noColumnDuplicates(arrayPosition, grid[arrayPosition])) {
if (noRowDuplicates(arrayPosition, grid[arrayPosition])) {
if (arrayPosition % inputNum == 0) {
cout << endl;
}
cout << grid[arrayPosition] << " ";
fill(arrayPosition + 1);
} else {
fill (arrayPosition);
}
} else {
fill(arrayPosition);
}
}
}
答案 0 :(得分:0)
您对fill()的初始调用将为其参数arrayPosition
传递0。
gridSize
是矩阵/数组的大小。
如果您检查fill()
中的逻辑,则会得出结论:除非arrayPosition
等于或大于gridSize
,否则将对fill()
进行递归调用,arrayPosition
要么相同,要么递增1。
fill()
时arrayPosition < gridSize
的所有逻辑执行路径都会导致fill()
的递归调用。
例如,如果您的数组/矩阵具有一万个值,那么您的fill()
将尝试至少(并且可能多于多个)对其自身进行一万次嵌套递归调用!
这不会结束。当您的代码通过操作系统分配给它分配的最大堆栈空间时,您的代码会遇到分段错误,操作系统拒绝为您的进程分配更多的堆栈空间。
您需要重构逻辑,以避免这种失控的递归。不幸的是,堆栈空间不是无限的。显示的逻辑在C ++中从根本上被打破。您不能依赖编译器来消除尾递归,并避免为每个递归函数调用消耗堆栈空间。
简要回顾一下,嵌套递归可以简单地用while
循环替换。整体算法仍有一些改进空间,但至少这将解决递归问题。