Java 编写此递归函数的另一种方法?

Java 编写此递归函数的另一种方法?,java,recursion,stack-overflow,Java,Recursion,Stack Overflow,我有一个颜色网格(在2D ArrayList中)。我需要能够计算特定颜色块中共享相同颜色的单元数(它们必须在4条边上相邻)。我可以很容易地递归地完成这项工作,但问题是有些图像会溢出堆栈,因为颜色块太大了 下面是递归函数: private int getBlockCount(PietCodel codel) { if (codel.getValue() != PietCodel.DEFAULT && codel.getValue() != PietCodel.CHECKE

我有一个颜色网格(在2D ArrayList中)。我需要能够计算特定颜色块中共享相同颜色的单元数(它们必须在4条边上相邻)。我可以很容易地递归地完成这项工作,但问题是有些图像会溢出堆栈,因为颜色块太大了

下面是递归函数:

private int getBlockCount(PietCodel codel) {

    if (codel.getValue() != PietCodel.DEFAULT && codel.getValue() != PietCodel.CHECKED) {
        return codel.getValue();
    }

    ArrayList<PietCodel> list = blockCountHelper(codel);
    list.add(codel);

    // Use the array of codels in the block, and
    // use the size to for each value in the array.
    int result = list.size();
    for (PietCodel item : list) item.setValue(result);

    System.out.println("Block count: " + result);

    return result;
}

private ArrayList<PietCodel> blockCountHelper(PietCodel codel) {
    ArrayList<PietCodel> result = new ArrayList<>();
    codel.setValue(PietCodel.CHECKED);
    int col = codel.getCol();
    int row = codel.getRow();

    // Right
    PietCodel ajac = get(col + 1, row);
    if (ajac != null && codel.equals(ajac.getColor()) && ajac.getValue() == PietCodel.DEFAULT) {
        ArrayList<PietCodel> nextCodels = blockCountHelper(ajac);
        result.add(ajac);
        result.addAll(nextCodels);
    }

    // Down
    ajac = get(col, row + 1);
    if (ajac != null && codel.equals(ajac.getColor()) && ajac.getValue() == PietCodel.DEFAULT) {
        ArrayList<PietCodel> nextCodels = blockCountHelper(ajac);
        result.add(ajac);
        result.addAll(nextCodels);
    }

    // Left
    ajac = get(col - 1, row);
    if (ajac != null && codel.equals(ajac.getColor()) && ajac.getValue() == PietCodel.DEFAULT) {
        ArrayList<PietCodel> nextCodels = blockCountHelper(ajac);
        result.add(ajac);
        result.addAll(nextCodels);
    }

    // Up
    ajac = get(col, row - 1);
    if (ajac != null && codel.equals(ajac.getColor()) && ajac.getValue() == PietCodel.DEFAULT) {
        ArrayList<PietCodel> nextCodels = blockCountHelper(ajac);
        result.add(ajac);
        result.addAll(nextCodels);
    }

    return result;
}
private int getBlockCount(PietCodel){
if(codel.getValue()!=PietCodel.DEFAULT&&codel.getValue()!=PietCodel.CHECKED){
返回codel.getValue();
}
ArrayList list=blockCountHelper(codel);
列表。添加(codel);
//使用块中的代码数组,然后
//使用数组中每个值的大小。
int result=list.size();
对于(PietModel项:列表)项。设置值(结果);
System.out.println(“块计数:+结果”);
返回结果;
}
专用ArrayList blockCountHelper(PietCodel){
ArrayList结果=新建ArrayList();
代码设置值(PIETCOEL.CHECKED);
int col=codel.getCol();
int row=codel.getRow();
//对
PietCodel ajac=get(列+1,行);
if(ajac!=null&&codel.equals(ajac.getColor())&&ajac.getValue()==PietCodel.DEFAULT){
ArrayList nextCodels=blockCountHelper(ajac);
结果:添加(ajac);
结果:addAll(nextCodels);
}
//向下
ajac=get(列,行+1);
if(ajac!=null&&codel.equals(ajac.getColor())&&ajac.getValue()==PietCodel.DEFAULT){
ArrayList nextCodels=blockCountHelper(ajac);
结果:添加(ajac);
结果:addAll(nextCodels);
}
//左
ajac=get(列-1,行);
if(ajac!=null&&codel.equals(ajac.getColor())&&ajac.getValue()==PietCodel.DEFAULT){
ArrayList nextCodels=blockCountHelper(ajac);
结果:添加(ajac);
结果:addAll(nextCodels);
}
//向上
ajac=get(列,第1行);
if(ajac!=null&&codel.equals(ajac.getColor())&&ajac.getValue()==PietCodel.DEFAULT){
ArrayList nextCodels=blockCountHelper(ajac);
结果:添加(ajac);
结果:addAll(nextCodels);
}
返回结果;
}

关于循环之类的替代方法有什么想法吗?

摆脱递归的标准方法是使用
Stack
数据结构,因为递归本质上是一种堆栈操作。但在您的具体情况下,您可以使用广度优先搜索。您可以使用队列来实现它:

int rows = 10;
int cols = 10;
PietCodel codels[][] = new PietCodel[rows][cols];
boolean used[][] = new boolean[rows][cols];
private void test() {
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < rows; ++j) {
            int color = (int) (Math.random() * 3);

            PietCodel codel = new PietCodel(i, j, color);

            codels[i][j] = codel;
            System.out.print(color + " ");
        }
        System.out.println();
    }
    System.out.println();

    System.out.println(getBlockCount(get(0, 0)));
}

private int getBlockCount(PietCodel codel) {
    used = new boolean[rows][cols];

    Queue<PietCodel> q = new LinkedList<>();
    q.add(codel);
    used[codel.getRow()][codel.getCol()] = true;

    int color = codel.getColor();
    int count = 0;
    while (!q.isEmpty()) {
        PietCodel ajacent = q.poll();
        int col = ajacent.getCol();
        int row = ajacent.getRow();
        ++count;

        addColored(q, col + 1, row, color);
        addColored(q, col - 1, row, color);
        addColored(q, col, row + 1, color);
        addColored(q, col, row - 1, color);
    }

    return count;
}

private PietCodel get(int col, int row) {
    return col < 0 || col >= cols || row < 0 || row >= rows ? null : codels[row][col];
}

private void addColored(Queue<PietCodel> q, int col, int row, int color) {
    if (col < 0 || col >= cols || row < 0 || row >= rows) {
        return;
    }

    PietCodel codel = codels[row][col];
    if (codel.getColor() != color || used[row][col]) {
        return;
    }

    used[row][col] = true;
    q.add(codel);
}

static class PietCodel {
    static final int DEFAULT = 0;
    static final int CHECKED = -1;
    static final int USED = -2;
    final int row;
    final int col;
    final int color;
    int value;

    public PietCodel(int row, int col, int color) {
        this.col = col;
        this.row = row;
        this.color = color;
    }

    public int getCol() {
        return col;
    }

    public int getRow() {
        return row;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public int getColor() {
        return color;
    }

    public boolean same(PietCodel ajac) {
        return color == ajac.getColor();
    }
}
int行=10;
int cols=10;
PietCodel[][]=新PietCodel[行][cols];
使用的布尔值[][]=新的布尔值[行][cols];
专用无效测试(){
对于(int i=0;i=cols | | row<0 | | row>=rows?null:codels[row][col];
}
私有void addColored(队列q、整数列、整数行、整数颜色){
如果(列<0 | |列>=cols | |行<0 | |行>=行){
返回;
}
PietCodel=codels[row][col];
if(codel.getColor()!=color | used[row][col]){
返回;
}
已用[行][列]=真;
q、 添加(codel);
}
静态类PietCodel{
静态最终整数默认值=0;
静态最终整数检查=-1;
使用的静态最终int=-2;
最后一行;
最终整数列;
最终int颜色;
int值;
公共拼图模型(整数行、整数列、整数颜色){
this.col=col;
this.row=行;
这个颜色=颜色;
}
公共int getCol(){
返回列;
}
public int getRow(){
返回行;
}
public int getValue(){
返回值;
}
公共无效设置值(int值){
这个值=值;
}
public int getColor(){
返回颜色;
}
公共布尔值相同(PietCodel ajac){
返回颜色==ajac.getColor();
}
}
这个想法是在应用程序代码中明确“堆栈/队列”。请注意,这并没有比递归方法使用更少的内存,它只是 通过利用堆,有更多的内存可供使用。下面的代码是一个示例。请注意,您可以调用
queue.addFirst
queue.addLast
,这将 不会改变最终结果,但会给你不同的董事会遍历,这是你可能关心或不关心的事情

private ArrayList<PietCodel> blockCountHelper(PietCodel codel) {
    ArrayList<PietCodel> accumulator = new ArrayList<>();
    LinkedList<PietCodel> queue = new LinkedList<>();
    queue.add(codel);

    while (!queue.isEmpty()) {
            PietCodel ajac = queue.remove();
            if (ajac != null && codel.equals(ajac.getColor()) .... ) {
                accumulator.add(ajac);
            }
            if ( get(col + 1, row) != null ) {queue.addFirst(get(col + 1, row));}
            if ( get(col , row + 1) != null ) {queue.addFirst(get(col, row + 1));}
            if ( get(col - 1, row) != null ) {queue.addFirst(get(col - 1, row));}
            if ( get(col , row - 1) != null ) {queue.addFirst(get(col, row- 1));}
    }
    return accumulator;
}
private ArrayList blockCountHelper(PietCodel){
ArrayList累加器=新的ArrayList();
LinkedList队列=新建LinkedList();
queue.add(codel);
而(!queue.isEmpty()){
pietodel ajac=queue.remove();
如果(ajac!=null&&codel.equals(ajac.getColor())…){
累加器。添加(ajac);
}
if(get(col+1,row)!=null){queue.addFirst(get(col+1,row));}
if(get(col,row+1)!=null){queue.addFirst(get(col,row+1));}
if(get(col-1,row)!=null){queue.addFirst(get(col-1,row));}
if(get(col,row-1)!=null){queue.addFirst(get(col,row-1));}
}
回流蓄能器;
}
不要试图翻译t