Quantcast
Channel: Save Your Knowledge
Viewing all articles
Browse latest Browse all 9

Deep recursion in Java

$
0
0

Recursion is a very elegant way to write some kind of algorithms. With few code lines we can implement complex solutions.
We know that, on each call on a recursive method, we add a new record with all local variables of that method in execution stack. Max stack’s size is wired to max recursion’s depth. If, for example, each call on a recursive method add a 20kb record to stack, and max recursion depth is 100, max stack’s size will be 20*100 = 2000kb.This is not a problem. But what about 10000 as max recursion depth? 20*10000 = 200.000kb = 200MB. This probably bring to a Stack Overflow exception. A so large recursion depth can be provided by a coding error but also by a large input.

Few days ago i wrote an algorithm for Flood Fiil .
This is the code


	public void countClick(int row, int col,boolean deep){
		
		
		if (row>=M || col>=N || col<0 || row<0)
			return;
		
				if (matrix[row][col]==0){
					try {
						if (!deep)count++;
						matrix[row][col] = -1;
						countClick(row,col+1,true);
						countClick(row+1,col+1,true);
						countClick(row+1,col,true);
						countClick(row+1,col-1,true);
						countClick(row,col-1,true);
						countClick(row-1,col-1,true);
						countClick(row-1,col,true);
						countClick(row-1,col+1,true);
					
					} catch (Exception e) {
						System.out.println(row+" "+col);
						e.printStackTrace();
					}
					
				}
				if (!deep){
					col++;
					if (col >= N){
						row++;
						col=0;
					}
					countClick(row,col,false);
				}
			
	
	}

The algorithm walk through a binary matrix. On finding a 0 value, it recursively call the algorithm on the 8 contiguous cells (starting from the left one and proceeding in clockwise order) changing their value to 1 and counting all 0 contiguous area.
On big matrix input this algorithm throws a Stack Overflow Exception due to deep recursion.
JDK default stack size is 512 Kb. You can increase this value with -Xss VM argument. For example -Xss10m will increase stack size to 10 Mb.

You can ALWAYS write a recursive algorithm as a iterative one. In this example the key of recursion is (row,col) pair. To make this algorithm iterative i used a Stack object to store (row,col) pairs of visited matrix’s cells. On discovering of a 0 value i add (row,col) to stack,then, in clockwise order, i check if contiguous cells are also 0 value. If so i add this cell to stack and iterate process. If there aren’t 0 values i pop out the (row,col) pair, iterating this process until stack is not empty.

	public void countClick(){
		Stack<int[]> stack = new Stack<int[]>();
		int[] coord = new int[2];
		
		for (int row = 0; row < M ; row++){
			for (int col = 0; col < N; col++){
				if (matrix[row][col] == 0){
					count++;
					coord[0] = row;
					coord[1] = col;
					stack.add(coord);
					matrix[row][col] = -1;
					while (!stack.isEmpty()){
						int tmpRow = stack.peek()[0];
						int tmpCol = stack.peek()[1];
						if (!(tmpRow>=M || tmpCol+1>=N || tmpCol+1<0 || tmpRow<0)&&(matrix[tmpRow][tmpCol+1]==0)){
							stack.add(new int[]{tmpRow,tmpCol+1});
							matrix[tmpRow][tmpCol+1] = -1;
						}
						else if (!(tmpRow+1>=M || tmpCol+1>=N || tmpCol+1<0 || tmpRow+1<0)&&(matrix[tmpRow+1][tmpCol+1]==0)){
							stack.add(new int[]{tmpRow+1,tmpCol+1});
							matrix[tmpRow+1][tmpCol+1] = -1;
							
						}else if(!(tmpRow+1>=M || tmpCol>=N || tmpCol<0 || tmpRow+1<0)&& (matrix[tmpRow+1][tmpCol]==0)){
							stack.add(new int[]{tmpRow+1,tmpCol});
							matrix[tmpRow+1][tmpCol] = -1;
							
						}else if (!(tmpRow+1>=M || tmpCol-1>=N || tmpCol-1<0 || tmpRow+1<0)&&(matrix[tmpRow+1][tmpCol-1]==0)){
							stack.add(new int[]{tmpRow+1,tmpCol-1});
							matrix[tmpRow+1][tmpCol-1] = -1;
							
						}else if (!(tmpRow>=M || tmpCol-1>=N || tmpCol-1<0 || tmpRow<0)&&(matrix[tmpRow][tmpCol-1]==0)){
							stack.add(new int[]{tmpRow,tmpCol-1});
							matrix[tmpRow][tmpCol-1] = -1;
							
						}else if (!(tmpRow-1>=M || tmpCol-1>=N || tmpCol-1<0 || tmpRow-1<0)&&(matrix[tmpRow-1][tmpCol-1]==0)){
							stack.add(new int[]{tmpRow-1,tmpCol-1});
							matrix[tmpRow-1][tmpCol-1] = -1;
							
						}else if (!(tmpRow-1>=M || tmpCol>=N || tmpCol<0 || tmpRow-1<0)&&(matrix[tmpRow-1][tmpCol]==0)){
							stack.add(new int[]{tmpRow-1,tmpCol});
							matrix[tmpRow-1][tmpCol] = -1;
							
						}else if (!(tmpRow-1>=M || tmpCol+1>=N || tmpCol+1<0 || tmpRow-1<0)&&(matrix[tmpRow-1][tmpCol+1]==0)){
							stack.add(new int[]{tmpRow-1,tmpCol+1});
							matrix[tmpRow-1][tmpCol+1] = -1;
						}else
							stack.pop();
						
				
					}
					
				}
			}
		}
	
	}

Iterative algorithm is not elegant like recursive one but doesn’t throw Stack Overflow Exception.



Viewing all articles
Browse latest Browse all 9

Trending Articles