我对McDowell下面的代码提出了几个问题来实现paintFill函数(类似于图像编辑程序)。
1-为什么我们使用排序屏幕[y] [x]而不是屏幕[x] [y]?作者说这是图形问题的特征,但为什么呢?
2-作者将这种方法与深度优先方法进行了比较,并表示它可以非常快速地溢出堆栈。另一种方法是实现广度优先搜索的变体。它不是一个bfs方法吗?因为对于每个像素,我们首先为相邻像素着色,然后向外看它们?如果没有,bfs方法的想法是什么,为什么它也不会溢出呢?
enum Color{
Black, White, Red, Yellow, Green
}
boolean paintFill(Color[][] screen, int x, int y, Color ocolor, Color ncolor){
if (x < 0 || x >= screen[0].length||
y < 0 || y >= screen.length){
return false;
}
if (screen[y][x] == ocolor){
screen[y][x] = ncolor;
paintFill(screen, x-1, y, ocolor, ncolor);
paintFill(screen, x+1, y, ocolor, ncolor);
paintFill(screen, x, y-1, ocolor, ncolor);
paintFill(screen, x, y+1, ocolor, ncolor);
}
return true;
}
boolean paintFill(Color[][] screen, int x, int y, Color ncolor){
if (screen[y][x] == ncolor){
return false;
}
return paintFill(screen, x, y, screen[y][x], ncolor);
}
答案 0 :(得分:1)
1-为什么我们使用排序屏幕[y] [x]而不是屏幕[x] [y]?作者说这是图形问题的特征,但为什么呢?
我猜y
代表垂直轴上的位置。在这种情况下,您不能使用screen[x][y]
,因为第一个维度是与垂直轴相关的维度。因此,必须使用y
索引。
2-作者将这种方法与深度优先方法进行了比较,并表示它可以非常快速地溢出堆栈。另一种方法是实现广度优先搜索的变体。这不是一个bfs方法吗?因为对于每个像素,我们首先为相邻像素着色,然后向外看它们?如果没有,bfs方法的想法是什么,为什么它也不会溢出呢?
它不是BFS
,因为您的调用是递归深度优先调用。这意味着你没有为所有相邻的像素着色,你通过递归调用为一个像素(在你的情况下是左边的一个)着色:
paintFill(screen, x-1, y, ocolor, ncolor);
然后你为这个左边的邻居上色(由于同一种递归调用),然后是那个左边的邻居,依此类推,直到你到达屏幕边缘没有左边邻居的像素。然后你回溯到你着色的最后一个像素,并从那里做第二次递归调用:
paintFill(screen, x+1, y, ocolor, ncolor);
着色右邻居(自从你来自右边后可能已经着色,所以在这种情况下这将快速返回)。这种情况一直持续到所有事情都被着色为止。
正如你所看到的,它首先是深度,因为你向某个方向移动,直到你出于某种原因不再向那个方向移动。对于广度优先,您必须使用FIFO队列:在队列中插入一个像素位置并为其着色。然后在队列中有元素时重复:从队列中删除第一个元素,为其邻居着色并将其邻居插入队列中。
这将避免递归调用,并且会产生类似于在地板上放下一罐油漆时所发生的效果:颜色将从一个点均匀向外扩展。
深度优先看起来类似于如果你试图在一个限制条件下给一张纸着色,你应该只改变你的手移动的方向,如果不这样做会导致你破坏纸张的边界。目前的算法是DFS。
答案 1 :(得分:1)
图像格式和屏幕设备使用水平扫描线,因此是水平线的垂直阵列。所以[y][x]
。参见模拟电视信号,BMP格式。
DFS的可视化将是雷击,而BFS将在培养皿中培养细菌菌落。由于任何搜索都没有指向,DFS有许多部分候选路径,它们在任何方向上卷曲,因此更长。 BFS更自然。就像你要保持生长的外轮廓一样。在另一个视图中:BFS增长受外边界限制,而DFS以非常不受限制的卷曲路径开始。这些路径较长,可能在指数上效率较低。最大路径长度B * W将是递归深度。在C中,可以定义一个小堆栈,但堆栈溢出似乎有点过头了。