我尝试在阵列中找到簇。例如,我有这样的数组:
0 0 0 0 0
0 2 3 0 1
0 8 5 0 7
7 0 0 0 4
启动程序后,它将打印以下结果:
Cluster 1: <2,3,8,5,7>
Cluster 2: <1,7,4>
我已经创建了递归函数来解决此问题:
void DFS(int x, int y)
{
printf("%d ", g[x][y]);
g[x][y] = 0;
// iterate over neighbours
for(dx=-1; dx<=1; dx++)
for(dy=-1; dy<=1; dy++)
if (g[x+dx][y+dy]) DFS(x+dx, y+dy);
}
for(i=0; i<n; i++)
for(j=0; j<n; j++)
if (g[i][j])
{
DFS(i, j);
printf("\n");
}
但是有一个问题:我需要处理特大数组,因此当递归函数调用其自身约1000次以上时,该程序将出现错误“堆栈溢出”。
因此,我需要在不使用递归函数的情况下重新制作此代码。 我尝试使用列表,cicle等,但无法正常工作。
你能告诉我,我该怎么做?
再次尝试解释:
// random_number_gererator.cpp: определяет точку входа для консольного приложения.
//
#include "stdafx.h"
#include <ctime>
#include <iostream>
#include <fstream>
//Задаем максимально возможный размер стека
#pragma comment(linker, "/STACK:100000000000")
using namespace std;
const int k = 2; //размерность массива
const int N = k * k * k; //количество элементов, которые необходимо сгенерировать
int number0 = 0, number1 = 0;
int generation(float probability); //прототип функции генерации псевдослучайных чисел
int create_array(); //прототип функции создания трехмерного массива
int ***ptrarray = new int **[k]; //указатель на трехмерный массив
ofstream fout("clusters.txt");
int find_and_write_clusters(int X, int Y, int Z); //прототип функции поиска кластеров
int main()
{
setlocale(LC_ALL, "rus"); //установка русской кодировки
int err = create_array(); //вызов функции создания трехмерного массива
//cout << err<<endl;
generation(0.3); //функция генерации и заполнения массива
//После генерации данные заполнились в массив ptrarray[][][]
for (int X = 0; X < k; X++) {
for (int Y = 0; Y < k; Y++) {
for (int Z = 0; Z < k; Z++) {
if (ptrarray[X][Y][Z] == 1) {
find_and_write_clusters(X, Y, Z); //вызываем рекурсивную функцию поиска и записи кластеров
fout << endl;
fout << endl;
}
}
}
}
fout.close();
system("pause");
return 0;
}
int generation(float probability) {
int prob_persent = ceil(probability * 10000); //введенная пользователем вероятность, в процентах до 10 000 (для большей точности)
int T;
if (probability > 1 || probability < 0) return 1;
for (int X = 0; X < k; X++) {
for (int Y = 0; Y < k; Y++) {
for (int Z = 0; Z < k; Z++) {
T = 0 + rand() % 10001;
if (T <= prob_persent) {
ptrarray[X][Y][Z] = 1;
}
else {
ptrarray[X][Y][Z] = 0;
}
}
}
}
for (int X = 0; X < k; X++) {
for (int Y = 0; Y < k; Y++) {
for (int Z = 0; Z < k; Z++) {
cout << ptrarray[X][Y][Z];
}
cout << endl;
}
cout << endl;
}
return 0;
}
int create_array() {
for (int X = 0; X < k; X++) {
ptrarray[X] = new int *[k];
for (int Y = 0; Y < k; Y++) {
ptrarray[X][Y] = new int[k];
}
}
return 0;
}
int find_and_write_clusters(int X, int Y, int Z) {
if (ptrarray[X][Y][Z] == 1) {
//Здесь проверить, есть ли такой элемент в файле
fout << X << ";" << Y << ";" << Z << " ";
//Заменяем текущий элемент на 0, чтобы он больше не обрабатывался
ptrarray[X][Y][Z] = 0;
if (X + 1 < k) find_and_write_clusters(X + 1, Y, Z);
if (Y + 1 < k) find_and_write_clusters(X, Y + 1, Z);
if (Z + 1 < k) find_and_write_clusters(X, Y, Z + 1);
if (X - 1 >= 0) find_and_write_clusters(X - 1, Y, Z);
if (Y - 1 >= 0) find_and_write_clusters(X, Y - 1, Z);
if (Z - 1 >= 0) find_and_write_clusters(X, Y, Z - 1);
}
return 0;
}
这是完整代码。在此程序中,我们的程序生成3D数组,并在其中填充“ 0”和“ 1”数字。 之后,程序使用这种算法找到簇(例如,我们制作了2 * 2 * 2数组:
10
01
11
00
这里我们有2层,总共8个元素(2 * 2 * 2)。
如何查找群集: 我们扫描数组并调用函数find_and_write_clusters。如果元素等于“ 1”,则在相邻元素中调用此函数。等等。
现在,如果您要编译并运行此代码,您将获得包含两行的文件“ clusters.txt”。我会尽力为您绘画
答案 0 :(得分:1)
您的描述So I need to remake this code without usage of recursive functions. I tried to use lists, cicles and so on, but it doesn't work properly.
非常模糊。
如果您通过递归代码的简化示例(例如,固定数组,随机生成确实与问题无关)来开始问题,那就更好了,然后还包含{ 1}}试试。这样我们可以更轻松地帮助您学习。
无论如何,这里是函数的一个版本,它是将递归版本直接转换为将数据存储在堆上的形式。如果doesn't work properly
不适合您的用例,那么您可以使用其他数据结构,但是我认为它可能直到真正大时才可用。
vector
但是您的方法开始时效率很低。您可以使用Two-pass approach
来节省很多复杂性(尽管我猜想对于3D,您需要跨层合并连接的2d标签,但仍比您现在正在做的所有分支和缓存丢失便宜)像您现在所做的那样,不规则地遍历每个标签的数据。
编辑:如果lambda令人困惑,则该代码等效于不带lambda的该版本
int find_and_write_clusters(int X, int Y, int Z) {
struct IState {
int X, Y, Z, step;
};
std::vector<IState> remaining;
auto insertIfOne = [&remaining](int X, int Y, int Z) {
if (ptrarray[X][Y][Z] == 1) {
fout << X << ";" << Y << ";" << Z << " ";
ptrarray[X][Y][Z] = 0;
remaining.emplace_back(IState{ X, Y, Z, 0 });
}
};
insertIfOne(X, Y, Z);
while (!remaining.empty())
{
auto& c = remaining.back();//current
switch (c.step++)
{
case 0:
if (c.X + 1 < k) insertIfOne(c.X + 1, c.Y, c.Z);
break;
case 1:
if (c.Y + 1 < k) insertIfOne(c.X, c.Y + 1, c.Z);
break;
case 2:
if (c.Z + 1 < k) insertIfOne(c.X, c.Y, c.Z + 1);
break;
case 3:
if (c.X - 1 >= 0) insertIfOne(c.X - 1, c.Y, c.Z);
break;
case 4:
if (c.Y - 1 >= 0) insertIfOne(c.X, c.Y - 1, c.Z);
break;
case 5:
if (c.Z - 1 >= 0) insertIfOne(c.X, c.Y, c.Z - 1);
break;
default:
remaining.pop_back();
}
}
return 0;
}
答案 1 :(得分:-7)
每个递归构造都可以用堆栈构造代替,反之亦然。尝试用堆栈数据类型替换递归逻辑。
这是C#,但是此概念适用于所有语言:https://haacked.com/archive/2007/03/04/Replacing_Recursion_With_a_Stack.aspx/