2012-02-29 27 views
10

से अधिक है मेरे पास कैनवास पर कुछ मंडलियों को स्थानांतरित करने के लिए एक पुनरावर्ती कार्य है। Overed सर्कल बढ़ाया गया है (ज़ूम इन) और अन्य सभी सर्किलों को धक्का दिया जाता है। धक्का मंडल अन्य सर्किलों को धक्का देते हैं और तब तक ज़ूमिंग पूर्ण होने तक।जावास्क्रिप्ट रिकर्सन: अधिकतम कॉल स्टैक आकार

मैं एक त्रुटि "अधिकतम कॉल स्टैक आकार से अधिक हो" मिलता है, और मैं इस समस्या समझते हैं, लेकिन मैं सिर्फ यह कैसे हल करने के लिए नहीं पता ... मैं सामान्य रूप में प्रत्यावर्तन की समस्याओं को सुलझाने के लिए तीन संभावित समाधान पाया:

  1. यात्रा करने के लिए
  2. उपयोग memoization
  3. उपयोग setTimeout

प्रत्यावर्तन बदलें लेकिन मुझे लगता है कि मैं उनमें से कोई भी उपयोग कर सकते हैं:

  1. मैं क्योंकि आपरेशन के अज्ञात गिनती की जरूरत की यात्रा लागू नहीं कर सकते
  2. मैं Memoization काफी अच्छी तरह से समझ में नहीं आता है, लेकिन मुझे लगता है कि यह या तो फिट नहीं करता है (या शायद मैं गलत हूँ और किसी ने मुझसे कहा जा सकता था अलग-अलग?)
  3. मैं सेटटाइमआउट का उपयोग नहीं कर सकता, क्योंकि यह इस विशेष एनीमेशन पर फ़ंक्शन कॉल को अवरुद्ध करना चाहिए।

मैं इस समस्या को कैसे ठीक करूं?

// 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); 
     } 
    } 
}; 

उत्तर

5

यह इस अतिप्रवाह को आश्चर्यचकित नहीं करता है क्योंकि एल्गोरिदम स्टैक को बढ़ता है क्योंकि यह पुनरावृत्त होता है लेकिन बाहर निकलने की स्थिति अप्रत्याशित होती है, क्रियाएं कसकर स्थानीयकृत नहीं होती हैं (उनके पास नजदीक मंडलियों पर प्रभाव पड़ता है), इसलिए प्रसंस्करण का समय अराजक होगा ।

मैं एल्गोरिदम पर पुनर्विचार करता हूं। दो निकटतम सर्किलों को ढूंढने पर विचार करें, यदि ये दिए गए थ्रेसहोल्ड के अलावा अलग हैं, तो निरस्त करें। अन्यथा उन्हें थोड़ा अलग करें और दोहराएं।

7

1) मैं क्योंकि जरूरत के संचालन के अज्ञात गिनती की यात्रा को लागू नहीं कर सकते हैं;

ठीक है, मैं अपने कोड को देखा नहीं है, लेकिन रैखिक प्रत्यावर्तन की एक सामान्य परिहार (आप एक रेखीय यहाँ है) इस तरह दिखता है:

while (1 == 1) { 
    if (breakcondition) 
     break; 
    doSomeCode() 
} 

तो आप को पता है की जरूरत नहीं है for - लूप केस में पुनरावृत्तियों की सटीक संख्या।

3

आप एक सतत समाधान बनाने के लिए पता करने के लिए नंबर या संचालन की जरूरत की जरूरत नहीं है। बिंदु जावास्क्रिप्ट स्टैक को अपने आप में से एक के साथ बदलना है। उदाहरण को देखने के लिए यह उत्तर देखें: Link

आप जावास्क्रिप्ट में एक स्टैक के रूप में एक ऐरे ऑब्जेक्ट का उपयोग कर सकते हैं क्योंकि यह push() और pop() का समर्थन करता है।

पुनश्च: जिम के जवाब के रूप में सुझाव दिया, आप आमतौर पर एक एल्गोरिथ्म है कि प्रत्यावर्तन के इस कई स्तरों की जरूरत नहीं है पा सकते हैं।

+2

आपका उत्तर भी सहायक था, लेकिन दुख की बात है कि मैं केवल एक जवाब स्वीकार कर सकता हूं ... धन्यवाद! – fizis

+1

मैंने इस भावना को व्यक्त करने के लिए इसे आपके ऊपर उठाया है। – agm1984

संबंधित मुद्दे