2017-05-18 5 views
0

私は重み付けされた米国地図を作成しています。私は郵便番号を3桁のジップゾーンに分割しました。私は1000回反復するforループを使って、各3桁のジップゾーンにランダムな色を付けます。これは毎回問題なしで機能します。私のループカウントが310以上になると、私の現在の問題が起こっています.310未満のものは完全にループします。初期カウントを上げると再帰的コードを少なくすることができるので、これは私には意味をなさない。私はそれを介して少ないデータをプッシュすると、私のスタックはあふれているのですか?

forループを呼び出すコード:

private void GUI() 
{  
    JFrame frame = new JFrame(); 
    frame.setLayout(new MigLayout()); 

    try 
    { 
     mapImg = ImageIO.read(new File("Res/Zipzone map of the US.png")); 
    } 
    catch (IOException e) 
    { 
     e.printStackTrace(); 
    } 
    g = mapImg.createGraphics(); 

    for(int i = 311; i < 1001; i++) 
    { 
     Random rand = new Random(); 
     String count = ""; 
     int red = rand.nextInt(220) + 25; 
     int green = rand.nextInt(220) + 25; 
     int blue = rand.nextInt(220) + 25; 
     if(i < 100) 
     { 
      count = "0" + i; 
     } 
     else 
     { 
      count = i + ""; 
     } 
     if(i <= 512) 
     { 
      ApplyColor(count, new Color(red, blue, green)); 
     } 
     else if(i > 909) 
     { 
      ApplyColor3(count, new Color(red, blue, green)); 
     } 
     else 
     { 
      ApplyColor2(count, new Color(red, blue, green)); 
     } 
    } 

    frame.add(new JLabel("", new ImageIcon(GetScaledImage(new ImageIcon(mapImg).getImage(), 1400, 875)), JLabel.CENTER), "GROW, PUSH"); 
    frame.setTitle("US Map"); 
    frame.setSize(1500,900); 
    frame.setLocationRelativeTo(null); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.setVisible(true); 
} 

適用色関数の小さな例:

private void ApplyColor(String zip, Color color) 
{ 
    int x; 
    int y; 
    if(zip.equals("010")) 
    { 
     try 
     { 
      x = 3339; 
      y = 672; 
      FloodFill(x, y, new Color(mapImg.getRGB(x, y)), color); 
      x = 3361; 
      y = 681; 
      FloodFill(x, y, new Color(mapImg.getRGB(x, y)), color); 
     } 
     catch(AWTException e) 
     { 
      e.printStackTrace(); 
     } 
    } 
} 

そしてFLOODFILL機能:

public void FloodFill(int x, int y, Color targetColor, Color replacementColor) throws AWTException 
{ 
    if(new Color(mapImg.getRGB(x, y)).equals(replacementColor)) 
    { 
     return; 
    } 

    g.setColor(replacementColor); 
    g.fillRect(x, y, 1, 1); 

    if(new Color(mapImg.getRGB(x-1, y)).equals(targetColor)) 
    { 
     FloodFill(x-1, y, targetColor, replacementColor); 
    } 

    if(new Color(mapImg.getRGB(x+1, y)).equals(targetColor)) 
    { 
     FloodFill(x+1, y, targetColor, replacementColor); 
    } 

    if(new Color(mapImg.getRGB(x, y-1)).equals(targetColor)) 
    { 
     FloodFill(x, y-1, targetColor, replacementColor); 
    } 

    if(new Color(mapImg.getRGB(x, y+1)).equals(targetColor)) 
    { 
     FloodFill(x, y+1, targetColor, replacementColor); 
    } 
} 

すべてのヘルプは次のようになりますが大いに感謝します。

答えて

2

310から始めるとこのエラーが発生する理由はわかりません。コードのうち「郵便番号」と呼ばれるものを扱う部分があまりにも奇妙であり、いずれにしても、それが意味をなさないので、サイトの他の訪問者には恩恵を与えません。

私が起きていると思われることは、310以上で始めると、郵便番号の配列が再帰的なflood-fillアルゴリズムではない場合より多くのペインティングが必要になるということです。

あなたの再帰的なflood-fillアルゴリズムを私たちにもたらします。

これは、フラッド・フィルを行う正しい方法ではありません。

これは学問分野では正しいと思われるかもしれませんが、現実世界では考えられないかもしれません。

あなたのアルゴリズムが長いピクセルの塗りつぶしを与えられている場合は、それらのすべての1つのアルゴリズムで繰り返されます。あなたの初期化コードでは、フレームの幅を1500に設定し、他の場所では3000を超える座標を使用していることがわかります。これは、実際にアルゴリズムを塗りつぶすピクセルが長く伸びていることを意味します。それはそれがたくさん繰り返すことを意味します。そのため、スタックオーバーフローの例外が発生します。

問題を修正するには、再帰的なflood-fillアルゴリズムを再帰的に実行しないようにする必要があります。たとえば、ピクセルを左に移動するたびに再帰する代わりに、ペイントするピクセルがある限り左にループし、上のピクセルとペイントされた各ピクセルの下のピクセルだけを繰り返し表示します。同じことが、右のピクセルを訪問する場合にも当てはまります。これは、アルゴリズムの再帰の深さを桁違いに減らす簡単な方法です。

ピクセル単位でfillRect()を実行する代わりに、1つの行にペイントする必要があるピクセルがすべてわかったら、1回の描画呼び出しですべてのピクセルをペイントできるため、パフォーマンスが向上します。ここでは、より良い性能を発揮することについて、私たちは話しています。

スタックオーバーフローの問題を解決するには不十分な場合は、アルゴリズムを実際に呼び出す代わりにスタックデータ構造を使用するアルゴリズムに置き換えることを検討してください。再帰的アルゴリズムをスタック型データ構造を使用する非再帰型に変換することは、あなたが探し出すことができ、多くの解決策を見つけることができるものです。

+0

ああ、もう1つ:あなたのxまたはyが画像の大きさを超えているかどうかを確認するためのチェックは何もしていません。それを処理するためのトリック、つまり 'targetColor'と決して等しくない画像の端に塗りつぶされた境界があることを願っています。 –

+0

非常に詳細なアドバイスをありがとうございます。私は洪水の充填に関するもう少し研究を行い、私のためにはるかに優れたキューシステムを考え出すことができました。 – Ardel

関連する問題