powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / рекурсивная функция делает переполнение кучи.
25 сообщений из 132, страница 1 из 6
рекурсивная функция делает переполнение кучи.
    #39364021
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день , друзья.

Помогите дилетанту .
Не могу разобраться , почему моя рекурсивная функция переполняет кучу.
Тупая реализация классической задачки на обход конем доски. Я правда так и не разобрался пока как закончить её выполнение. Но это не сильно и важно. (на данный момент просто хотелось бы добиться чтобы высветилось хотя бы одно решение, пусть и с зацикливанием)
Пытаюсь даже выводить грубо глубину рекурсии - она теоретически не должна превышать 64 - так и есть.
Однако при длительной работе (а дерево разрастается очень стремительно) высвечивает Java heap space.


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
package horses;
import java.util.concurrent.TimeUnit;
public class horse {
int qty_of_hourse = 65;
int [][] x = new int[9][9];
int [] is = new int[65];
int [] js = new int[65];
long depth = 0;
int i_start=1;
int j_start=1;
int horse_count = 1;
public horse() {
x[i_start][j_start]=1; 
is[1] = i_start;js[1] = j_start;
System.out.println("start");
print_field();
}
public String try_horse(int current_horse) {
String res="good" ;
int [] moving= new int [2];
int mc=1; 
int x1=0;
int y1=0; 
depth++;
System.out.println("Глубина = " + depth);
if (current_horse==2) {x1=i_start; y1=j_start; is[current_horse] = x1;js[current_horse] = y1;}
do {
moving = move_horse(mc,is[current_horse-1],js[current_horse-1]);
if (moving[0]!=0 && moving[1]!=0) { //если можно поставить коня
	x1 = moving[0];
	y1 = moving[1];
x[x1][y1]=current_horse;/*ставим*/
is[current_horse] = x1;
js[current_horse] = y1;
System.out.println("Можно !  Передвигаем коня на "+x1+ " "+y1+", ход №"+current_horse);
print_field();
if (current_horse<=64) { res=try_horse(current_horse+1); }
if (res=="bad") {
	System.out.println("Плохо !  Вынуждены убрать коня с "+is[current_horse]+ " "+js[current_horse]);
	x[is[current_horse]][js[current_horse]]=0;
	is[current_horse]=0;
	js[current_horse]=0;
	res="good";
} 
} 
mc++;
if (mc==9) {res="bad";}
} while (!(res=="bad" || mc==9 )) ;
depth--;
return res;
}
public int [] move_horse(int i1 , int i , int j ) { 
int [] result= new int [2]; 
result[0] = 0 ;
result[1] = 0 ;
int is=0;
int js=0;

System.out.println("Попытка "+ i1 +" из 8. проверим можно ли передвинуть с " +i+ " "+  j);

if (i1==1 && i-2>=1 && j-1>=1 && x[i-2][j-1]==0) {is=i-2 ; js=j-1; result[0] = is ;result[1] = js ; 

} 
if (i1==2 && i-1>=1 && j-2>=1 && x[i-1][j-2]==0) {is=i-1 ; js=j-2; result[0] = is ;result[1] = js ; 

} 
if (i1==3 && i+1<=8 && j-2>=1 && x[i+1][j-2]==0) {is=i+1 ; js=j-2; result[0] = is ;result[1] = js; 

}
if (i1==4 && i+2<=8 && j-1>=1 && x[i+2][j-1]==0) {is=i+2 ; js=j-1; result[0] = is ;result[1] = js; 

}
if (i1==5 && i+2<=8 && j+1<=8 && x[i+2][j+1]==0) {is=i+2 ; js=j+1; result[0] = is ;result[1] = js; 

}
if (i1==6 && i+1<=8 && j+2<=8 && x[i+1][j+2]==0) {is=i+1 ; js=j+2; result[0] = is ;result[1] = js; 

}
if (i1==7 && i-1>=1 && j+2<=8 && x[i-1][j+2]==0) {is=i-1 ; js=j+2; result[0] = is ;result[1] = js; 

}
if (i1==8 && i-2>=1 && j+1<=8 && x[i-2][j+1]==0) {is=i-2 ; js=j+1; result[0] = is ;result[1] = js ; 

}
return result;
}
public void print_field() {
int i1;
int j1;
for (i1 = 1; i1 <= 8; i1++) {
for (j1 = 1; j1 <= 8; j1++) {
if (x[i1][j1]>0) {System.out.print(x[i1][j1]+" ");}
if (x[i1][j1]<0) {System.out.print("B ");}
if (x[i1][j1]==0) {System.out.print("0 ");}
}
System.out.println();
}
System.out.println();
}
}




Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
package horses;

public class main {
	public static void main(String args[]) {
		 horse h = new  horse();
		 
		 h.try_horse(2);

		
	}
}
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364025
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 ** 64 ~ 10 ** 18
Терабайт это 10 ** 12
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364032
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov2 ** 64 ~ 10 ** 18
Терабайт это 10 ** 12

то есть вы хотите сказать, что когда 64 процедуры вызывают последовательно друг друга , то памяти отъедается более терабайта ? :-)
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364035
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я хочу сказать, что есть "рекурсия вглубь" и "рекурсия вширь".

P.S. Мне лень разбираться в попытках решить методом полного перебора задачу, которую (насколько мне изменяет склероз) умные люди давно решили вручную.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364037
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

эта именно тупо вглубь .
что значит решили вручную ? ))))
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364043
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, например, в старом журнале ("Наука и жизнь", если правильно помню) была статья, где в качестве одного из способа запоминания ходов автор придумал стихи, строчки которых были мнемониками шахматных клеток. Журнал - не младше середины-конца восьмидесятых.

P.S. Насколько я помню вполне классическую "Алгоритмы + структуры данных = программы", принципиально разных решений всего двенадцать. Издание начала восьмидесятых.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364048
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя, вру - у Вирта решается задача расстановки восьми ферзей.
Чтобы рекурсия была вглубь требуются две вещи стратегия обхода и запоминание "границы отсечения".
Когда на каждом шаге перебираются все возможные варианты это именно что рекурсия вширь.

P.S. Я бы предложил разбираться с рекурсией на гораздо более простой задаче: лабиринт без циклов, где на каждом шаге можно повернуть или влево или вправо и глубина любого пути не превышает заданного (небольшого) числа шагов.
Начинать с лабиринтов, которые можно нарисовать на листе школьной тетради в клеточку.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364052
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

да, совершенно верно , есть у меня такая . там приведён даже шаблон перемещения по дереву с возвратом. именно им я и воспользовался.


возможно различие решений только лишь в представлении данных .
Но моё решение судя по всему рабочее. дерево обходится в глубину как надо.
Но это всё не суть...

Разбираться в моём коде я никого не прошу. просто хочу для себя разобраться почему происходит переполнение памяти.
максимально в любой период времени работы программы может быть не более 64 вызова процедуры.

одна процедура резервирует грубо говоря:
3 переменных int (96 байт),
один массив (64 байта)
переменная типа String
может в последней проблема ? я толком не понимаю пока эта переменная фиксированной длины или же переменной ?

почему вы насчитали, что памяти должно резервироваться более терабайта
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364053
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovХотя, вру - у Вирта решается задача расстановки восьми ферзей.


нет, не врете. кони тоже решаются в моем издании
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364056
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И ещё: чтобы не путать глубину рекурсии с числом (активных) рекурсивных вызовов - сделайте статическую, которая будет увеличиваться на входе в рекурсивный метод и уменьшаться на выходе. Ну и печатайте значение этой переменной по мере надобности.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364058
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovИ ещё: чтобы не путать глубину рекурсии с числом (активных) рекурсивных вызовов - сделайте статическую, которая будет увеличиваться на входе в рекурсивный метод и уменьшаться на выходе. Ну и печатайте значение этой переменной по мере надобности.


так и делал . за исключением статики
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364059
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

стоп. статическую что вы имеете ввиду ? переменную или метод вызова статический ?
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364060
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

это вы имеете ввиду ?

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
public class horse {
...
static long depth = 0;
...

public String try_horse(int current_horse) {
string result;
depth ++;
     ....
try_horse(current_horse+1) ;
     ....
depth --;

return  result ;
}



у меня переменная depth сейчас считается так же за исключением того , что объявлена она не как static.
честно говоря не чувствую разницы
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364061
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Статика непринципиальна.
Просто вы считаете именно что глубину рекурсии, а считать надо число активных вызовов.
Цепочка вызовов активна до тех пор пока мы или не нашли (очередное) решение или не обнаружили, что эта цепочка ходов решением не является.
Когда вы осознаете, что каждый узел в цепочке вызовов порождает свою цепочку вызовов, вам станет понятнее "куда девается память".
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364072
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

как я понимаю мой алгоритм в любой момент времени хранит только лишь текущую самую глубокую ветку и всю цепочку до неё .
остальные пройденные субдеревья и не приведшие к удаче в данный момент не хранятся. Или нет ?

вот на рисунке мы скажем в данный промежуток времени проделали маршрут 1->7->8->9->12. мы этот маршрут и храним.
пусть даже до этого были маршруты
1->2-> 3-> 4
1->2-> 3-> 5
1->2-> 3-> 6
а так же
1->7->8->9->10->11
но они не привели к решению . ну значит мы по ним и выполнили всюду return-ы , а это значит и память по ним расчистилась. Или же нет ?

а маршрут 1->7->8->9->12 это 5 вызовов. и глубина = 5. или же нет ??
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364080
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. SidorovЦепочка вызовов активна до тех пор пока мы или не нашли (очередное) решение или не обнаружили, что эта цепочка ходов решением не является.


верно и это понятно. но цепочка вызовов не может превышать 64 (число ходов, а значит клеток на шахматной доске).
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364109
Basil A. Sidorov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кстати, об ограничениях ...
Чтобы шестьдесят четвёртым ходом оказаться в точке (0,0), на шестьдесят третьем ходу надо быть или в точке (2,1) или в точке (1,2).
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364111
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Basil A. Sidorov,

блин, да нет же. задача стоит проще: просто обойти абсолютно все клетки , закрасив их.

кстати, я Вам соврал. похоже, что ругается консоль . "io console updater java heap space" я наверно превысил допустимое число вывода на экран . кстати , можно ли выводить не в консоль , а в файл (Eclipse) ? гугл не помог.

а "ругань" превышения допустимых вызовов рекурсивной функции выглядит иначе. достаточно накидать программу n! и поставить в качестве входного параметра скажем громадное число. там со стэком будет ошибка.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364112
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

P.s. стоит задача обойти все клетки конем побывав ровно по одному в каждой
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364421
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
andron81,

=) помню сдавал такую курсовую два раза за обучение :)

Вот пример . тут даже с графикой )


http://5fan.ru/wievjob.php?id=49236
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364430
Atum1
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364472
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1,

спасибо , конечно, интересней самому решить, что я и сделал.

для начальной точки 1,1 выдаёт решения за время меньше минуты.
а вот на точке 1,2 выходит в ступор. дерево разрастается настолько , что и за 40 минут ни одного решения не выдаёт
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364476
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Atum1 http://algolist.manual.ru/maths/combinat/knight.php

хотя интересное правило Варнсдорфа описано.
но я правило такого не знал. поэтому у меня тупой перебор всего дерева. поэтому видимо и долго
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364485
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Лет 10 назад я кодил на С++/Win32 GDI приложение для решения horse problem.

Чтоб рекурсия не заходила в слишком глубокие поиски я разработал правила
построения кориродов (только для прямоугольной доски) чтобы ограничить
для коня следущие несколько N ходов. Для этого я выбирал ширину коридора
(4 клетки) и змейкой заполнял всю доску.

К сожалению сорцы потерял.
...
Рейтинг: 0 / 0
рекурсивная функция делает переполнение кучи.
    #39364488
andron81
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

мне не сильно важна оптимизация пока моего алгоритма. важен сам факт - ищет / не ищет. тем более решение кое-какие находит.
А вообще я пытаюсь разобраться с рекурсией.
...
Рейтинг: 0 / 0
25 сообщений из 132, страница 1 из 6
Форумы / Java [игнор отключен] [закрыт для гостей] / рекурсивная функция делает переполнение кучи.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]