您的位置:首页 > 其它

图的BFS遍历中标记已访问的节点操作影响效率

2015-03-30 11:42 267 查看
在做leetCode 130 Surrounded Regions时一直TLE,但是对照自己的代码更别人的代码也“几乎”相同,最后终于找到问题所在,就是在图的BFS过程中,什么时候对已经访问的节点做标记(这些语句安排在哪里)是会严重影响效率的!

两段代码如下:

void bfsBoundry1(vector<vector<char>> &board, int i, int j)
{
int m = board.size();
int n = board[0].size();
queue<pair<int, int>> que;
que.push({i, j});
while(!que.empty())
{
auto coor_0 = que.front();
que.pop();
board[coor_0.first][coor_0.second] = 'B';  //标记为已经访问的节点
vector<pair<int, int>> coors;
if(coor_0.first-1 >= 0)
coors.push_back({coor_0.first-1, coor_0.second});
if(coor_0.first+1 < m)
coors.push_back({coor_0.first+1, coor_0.second});
if(coor_0.second-1 >= 0)
coors.push_back({coor_0.first, coor_0.second-1});
if(coor_0.second+1 < n)
coors.push_back({coor_0.first, coor_0.second+1});
for(auto a : coors)
{
if(board[a.first][a.second] == 'O')
que.push(a);
}
}
}


void bfsBoundry2(vector<vector<char>> &board, int i, int j)
{
int m = board.size();
int n = board[0].size();
queue<pair<int, int>> que;
que.push({i, j});
board[i][j] = 'B';  //标记为已经访问的节点
while(!que.empty())
{
auto coor_0 = que.front();
que.pop();
vector<pair<int, int>> coors;
if(coor_0.first-1 >= 0)
coors.push_back({coor_0.first-1, coor_0.second});
if(coor_0.first+1 < m)
coors.push_back({coor_0.first+1, coor_0.second});
if(coor_0.second-1 >= 0)
coors.push_back({coor_0.first, coor_0.second-1});
if(coor_0.second+1 < n)
coors.push_back({coor_0.first, coor_0.second+1});
for(auto a : coors)
{
if(board[a.first][a.second] == 'O')
{
que.push(a);
board[a.first][a.second] = 'B';  //标记为已经访问的节点
}
}
}
}


上面两段代码的功能完全一致,就是以某个点开始,进行上下左右的行走,如果走得通(‘O’),则访问,访问之后标记为‘B’。不同之处就在于在什么时候标记已经走过的节点。bfsBoundry1的效率比bfsBoundry2的效率会低很多。原因是1在把节点放到队列时不标记为访问,而出队列时标记为访问;2与此相反。1的问题在于从某个节点开始可能有多条可选择的路径,而这多条路径的下一条路径可能会重叠。如果不在把节点放到队列时及时标记为已访问节点,那么他们可能在后续的访问中向队列中加入重复的节点,导致效率下降!

比如有如下图:

1 2

3 4

使用“bfsBoundry1算法时:

在访问1时,会把2、3放到队列中,此时2、3并没有标记为访问;

当把2出队列时,2标记为访问,此时会把4加入到队列中,4没有标记为访问;

当把3出队列时,3标记为访问,由于4没有标记为访问,所以此时又会把4放到队列中!

使用bfsBoundry2算法不会有上面的问题!

所以,记住一点,当使用BFS对图进行遍历时,一定要在把节点放到队列时,及时将该节点设置为“访问”过状态!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐