Java中2d int数组优化的泛洪填充
我正在编写自己的洪水填充实现 我想出了这个密码:Java中2d int数组优化的泛洪填充,java,algorithm,path-finding,flood-fill,Java,Algorithm,Path Finding,Flood Fill,我正在编写自己的洪水填充实现 我想出了这个密码: public static void fillArea(int x, int y, int original, int fill, int[][] arr) { Stack<int[]> q = new Stack<int[]>(); int[] w = new int[2]; //to the west int[] e = new int[2]; //to the ea
public static void fillArea(int x, int y, int original, int fill, int[][] arr) {
Stack<int[]> q = new Stack<int[]>();
int[] w = new int[2]; //to the west
int[] e = new int[2]; //to the east
if (arr[x][y] != original) {
return;
}
q.push(new int[]{x, y});
while (!q.isEmpty()) {
int[] pos = (int[]) q.pop();
int i = pos[0];
int j = pos[1];
if (arr[i][j] == original) {
e[0] = i;
e[1] = j;
w[0] = i;
w[1] = j;
}
while (w[1] > 0 && arr[w[0]][w[1] - 1] == original) { // to the west
w[1] -= 1;
}
while (e[1] < arr[0].length - 1 && arr[e[0]][e[1] + 1] == original) { // to the east
e[1] += 1;
}
for (int a = w[1]; a <= e[1]; a++) { // for every point between west and east
arr[w[0]][a] = fill;
if (w[0] > 0 && arr[w[0] - 1][a] == original) { //check if we can go north
q.push(new int[]{(w[0] - 1), a});
}
if (w[0] < arr.length - 1 && arr[w[0] + 1][a] == original) {//check if we can go south
q.push(new int[]{(w[0] + 1), a});
}
}
}
return;
}
这是实施:
我使用的是Stack
而不是Queue
,因为Stack
似乎快得多,或者我的代码有问题
问题是:速度非常慢。关于性能,我能做些什么吗?我可以用内存换取性能,但本机递归会让我产生堆栈溢出。好的,我们开始:)。 我用数组模拟堆栈,我希望这会快得多。我没有完全遵循伪代码,但它是有效的,我认为它应该是快速的
public static void main(String[] args) {
int testArray[][] = new int[10][10];
for (int i = 0; i < 10; i++) {
testArray[i][i] = 1;
testArray[9-i][i] = 1;
}
testArray[4][7] = 1;
System.out.println("Array before");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(testArray[j][i] + " ");
}
System.out.println("");
}
fillArea(6,8,0,7,testArray);
System.out.println("Array after");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(testArray[j][i] + " ");
}
System.out.println("");
}
}
public static void fillArea(int x, int y, int original, int fill, int[][] arr) {
int maxX = arr.length - 1;
int maxY = arr[0].length - 1;
int[][] stack = new int[(maxX+1)*(maxY+1)][2];
int index = 0;
stack[0][0] = x;
stack[0][1] = y;
arr[x][y] = fill;
while (index >= 0){
x = stack[index][0];
y = stack[index][1];
index--;
if ((x > 0) && (arr[x-1][y] == original)){
arr[x-1][y] = fill;
index++;
stack[index][0] = x-1;
stack[index][1] = y;
}
if ((x < maxX) && (arr[x+1][y] == original)){
arr[x+1][y] = fill;
index++;
stack[index][0] = x+1;
stack[index][1] = y;
}
if ((y > 0) && (arr[x][y-1] == original)){
arr[x][y-1] = fill;
index++;
stack[index][0] = x;
stack[index][1] = y-1;
}
if ((y < maxY) && (arr[x][y+1] == original)){
arr[x][y+1] = fill;
index++;
stack[index][0] = x;
stack[index][1] = y+1;
}
}
}
这个版本甚至更快
public static void floodFill(int y, int x, byte originalvalue, byte newvalue, byte[][] arr) {
Deque queue = new ArrayDeque();
queue.add(new int[]{y, x});
while (!queue.isEmpty()) {
int[] t = (int[]) queue.poll();
y = t[0];
x = t[1];
if (arr[y][x] == originalvalue) {
arr[y][x] = newvalue;
for (int i = 0; i
< 8; i++) {
if (x + dx[i] < arr[0].length && y + dy[i] < arr.length && x + dx[i] > -1 && y + dy[i] > -1 && arr[y + dy[i]][x + dx[i]] == originalvalue) {
queue.add(new int[]{y + dy[i], x + dx[i]});
}
}
}
}
}
public static void floodFill(int y,int x,byte originalvalue,byte newvalue,byte[]arr){
Deque queue=new ArrayDeque();
add(新的int[]{y,x});
而(!queue.isEmpty()){
int[]t=(int[])queue.poll();
y=t[0];
x=t[1];
if(arr[y][x]==原始值){
arr[y][x]=新值;
对于(int i=0;i
<8;i++){
如果(x+dx[i]-1&&y+dy[i]>-1&&arr[y+dy[i]][x+dx[i]==原始值){
add(新的int[]{y+dy[i],x+dx[i]});
}
}
}
}
}
您能描述一下您使用该阵列的具体操作吗?也许可以做得不同。我只是将所有连接的节点更改为给定的点。如果您要求的话,只需进行泛洪填充。我感兴趣的是,是否有更快的实现。我建议,有一种方法可以使用数组而不是堆栈。这将加快程序的速度。也许有一种方法可以同时使用堆栈和递归。好吧,如果我理解正确,所有不等于variableoriginal
的东西都被认为是“墙”,对吗?我必须更改int maxY=arr.length-1;int maxX=arr[0]。长度-1代码>到int maxY=arr[0]。长度-1;int maxX=arr.length-1代码>现在速度快了8倍多。非常感谢。看来你们把堆栈改成了数组。@JohnDow-怎么改的?你换了吗?这是可能的,我在空间想象方面有很大的困难,现在它是正确的。非常感谢。速度在3x-9x之间。你能告诉我如何推导dx[i]和dy[i]吗?
public static void main(String[] args) {
int testArray[][] = new int[10][10];
for (int i = 0; i < 10; i++) {
testArray[i][i] = 1;
testArray[9-i][i] = 1;
}
testArray[4][7] = 1;
System.out.println("Array before");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(testArray[j][i] + " ");
}
System.out.println("");
}
fillArea(6,8,0,7,testArray);
System.out.println("Array after");
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
System.out.print(testArray[j][i] + " ");
}
System.out.println("");
}
}
public static void fillArea(int x, int y, int original, int fill, int[][] arr) {
int maxX = arr.length - 1;
int maxY = arr[0].length - 1;
int[][] stack = new int[(maxX+1)*(maxY+1)][2];
int index = 0;
stack[0][0] = x;
stack[0][1] = y;
arr[x][y] = fill;
while (index >= 0){
x = stack[index][0];
y = stack[index][1];
index--;
if ((x > 0) && (arr[x-1][y] == original)){
arr[x-1][y] = fill;
index++;
stack[index][0] = x-1;
stack[index][1] = y;
}
if ((x < maxX) && (arr[x+1][y] == original)){
arr[x+1][y] = fill;
index++;
stack[index][0] = x+1;
stack[index][1] = y;
}
if ((y > 0) && (arr[x][y-1] == original)){
arr[x][y-1] = fill;
index++;
stack[index][0] = x;
stack[index][1] = y-1;
}
if ((y < maxY) && (arr[x][y+1] == original)){
arr[x][y+1] = fill;
index++;
stack[index][0] = x;
stack[index][1] = y+1;
}
}
}
Array before
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 0 0 1 0 0 0
0 0 1 0 1 0 0 1 0 0
0 1 0 0 0 0 0 0 1 0
1 0 0 0 0 0 0 0 0 1
Array after
1 0 0 0 0 0 0 0 0 1
0 1 0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 1 0 0
0 0 0 1 0 0 1 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 1 7 7 1 0 0 0
0 0 1 7 1 7 7 1 0 0
0 1 7 7 7 7 7 7 1 0
1 7 7 7 7 7 7 7 7 1
public static void floodFill(int y, int x, byte originalvalue, byte newvalue, byte[][] arr) {
Deque queue = new ArrayDeque();
queue.add(new int[]{y, x});
while (!queue.isEmpty()) {
int[] t = (int[]) queue.poll();
y = t[0];
x = t[1];
if (arr[y][x] == originalvalue) {
arr[y][x] = newvalue;
for (int i = 0; i
< 8; i++) {
if (x + dx[i] < arr[0].length && y + dy[i] < arr.length && x + dx[i] > -1 && y + dy[i] > -1 && arr[y + dy[i]][x + dx[i]] == originalvalue) {
queue.add(new int[]{y + dy[i], x + dx[i]});
}
}
}
}
}