我有一个递归功能,可以在画布上移动一些圆圈。被遮挡的圆圈被放大(放大),所有其他圆圈被推开。 推动的圆圈推动其他圆圈,依此类推,直到缩放完成。
我收到错误“超出最大调用堆栈大小”,我理解了问题,但我只是不知道如何解决它... 我找到了三种解决递归问题的可能解决方案:
但我认为我不能使用它们:
如何解决此问题?
// Pushes circles aside when some other circle leans on these circles (on zoom in)
var moveCirclesAside = function(circle1, circleToSkip, groupOfMoves) {
var count = circles.length;
for (var i = 0; i < count; i++) {
// Skip the same circle
if (i == circle1.i) {
continue;
}
// Also skip the circle which was intended not to move any further
if (circleToSkip != null && i == circleToSkip.i) {
continue;
}
// Get second circle
var circle2 = circles[i];
// Calculate a distance between two circles
var dx = circle2.x - circle1.x;
var dy = circle2.y - circle1.y;
var distance = Math.sqrt((dx * dx) + (dy * dy));
// If circles already collided need to do some moving...
if (distance <= circle1.r + circle2.r + OD.config.circleSpacing) {
// Get collision angles
var angle = Math.atan2(dy, dx);
var sine = Math.sin(angle);
var cosine = Math.cos(angle);
// Some circle position calculation
var x = OD.config.circleSpacing;
var xb = x + (circle1.r + circle2.r);
var yb = dy * cosine - dx * sine;
// Save each state (move) of any circle to the stack for later rollback of the movement
groupOfMoves.push(copyCircleByVal(circle2));
// Move the circle
circle2.x = circle1.x + (xb * cosine - yb * sine);
circle2.y = circle1.y + (yb * cosine + xb * sine);
// Make sure that circle won't go anywhere out of the canvas
adjustCircleByBoundary(circle2);
// If moved circle leans against some other circles make sure that they are moved accordingly
// And such related moves must be grouped for correct rolback of moves later - so we pass 'groupOfMoves' var
moveCirclesAside(circle2, circle1, groupOfMoves);
}
}
};
答案 0 :(得分:8)
1)由于所需的操作数量未知,我无法实现迭代;
好吧,我没有查看你的代码,但是一般避免线性递归(你在这里有一个线性递归)看起来像这样:
while (1 == 1) {
if (breakcondition)
break;
doSomeCode()
}
因此,您不必知道for
- 循环案例中的确切迭代次数。
答案 1 :(得分:6)
这种溢出并不令人惊讶,因为算法在迭代时会增加堆栈,但退出条件是不可预测的,动作没有紧密定位(它们对附近的圆圈产生连锁效应),因此处理时间将是混乱的。
我会重新考虑这个算法。考虑找到两个最接近的圆圈,如果它们比分开的给定阈值更远,则中止。否则将它们分开并重复一遍。
答案 2 :(得分:4)
您无需知道制作迭代解决方案所需的数量或操作。关键是用你自己的一个替换JavaScript堆栈。请查看此答案以查看如何实施该示例的示例:Link
您可以将Array对象用作JavaScript中的堆栈,因为它支持push()
和pop()
。
答案 3 :(得分:0)
尝试确保递归步骤仅针对大于基本情况。例如,在快速排序中:
function qsort(k){
if(k == []){
return k;
}
if(k.length == 1){
return k;
}
//pick random pivot
var p = Math.floor(Math.random()*k.length);
console.log("pivot is" + p + "\n");
//set left and right iter
var l = 0; var r = k.length - 1;
while( l < r){
console.log('hi\n');
//move l until its element is bigger than pivot
while(k[l] < k[p] && l < k.length) {
l++;
console.log('h1i\n');
}
//move r until its element is smaller than pivot
while(k[r] > k[p] && r >= 0) {r--;
console.log('h2i\n');
}
//swap k[l] with k[r]
var temp = k[l]; k[l] = k[r]; k[r] = temp;
}
if(l == r){
//swap k[l] with k[p]
temp = k[l]; k[l] = k[p]; k[p] = temp;
}
var lk = k.slice(0,p); var rk = k.slice(p,k.length);
console.log(lk);
console.log(rk);
if(lk.length > 1){
lk = qsort(lk);
}
if(rk.length > 1){
rk = qsort(rk);
}
result = lk.concat(rk);
console.log(result);
return result;
}
var k = [23,245,67,34,24];
var result = qsort(k);
console.log(result);
//document.write(result);
如果您使用lk.length > 1
之类的lk != []
代替@Override
public Observable<List<Item>> getResults() {
return getResultsFromDatabase().toObservable().switchIfEmpty(getResultsFromNetwork());
}
@Override
public Observable<List<Item>> getResultsFromNetwork() {
System.out.println("getting results from network");
return api.getData().doOnNext(new Consumer<List<Item>>() {
@Override
public void accept(List<Item> items) throws Exception {
itemDao.insert(items);
}
});
}
@Override
public Maybe<List<Item>> getResultsFromDatabase() {
System.out.println("getting coins from database");
return itemDao.getAllItems();
}
而不是检查,则有时可能会使调用堆栈大小超出错误,有时会根据选择的哪个支点工作