[转载]图的宽度优先遍历
转载自:http://book.51cto.com/art/201012/236668.htm
1.2 宽度优先爬虫和带偏好的爬虫
1.1节介绍了如何获取单个网页内容。在实际项目中,则使用爬虫程序遍历互联网,把网络中相关的网页全部抓取过来,这也体现了爬虫程序"爬"的概念。爬虫程序是如何遍历互联网,把网页全部抓取下来的呢?互联网可以看成一个超级大的"图",而每个页面可以看作是一个"节点"。页面中的链接可以看成是图的"有向边"。因此,能够通过图的遍历的方式对互联网这个超级大"图"进行访问。图的遍历通常可分为宽度优先遍历和深度优先遍历两种方式。但是深度优先遍历可能会在深度上过"深"地遍历或者陷入"黑洞",大多数爬虫都不采用这种方式。另一方面,在爬取的时候,有时候也不能完全按照宽度优先遍历的方式,而是给待遍历的网页赋予一定的优先级,根据这个优先级进行遍历,这种方法称为带偏好的遍历。本小节会分别介绍宽度优先遍历和带偏好的遍历。
1.2.1 图的宽度优先遍历
下面先来看看图的宽度优先遍历过程。图的宽度优先遍历(BFS)算法是一个分层搜索的过程,和树的层序遍历算法相同。在图中选中一个节点,作为起始节点,然后按照层次遍历的方式,一层一层地进行访问。
图的宽度优先遍历需要一个队列作为保存当前节点的子节点的数据结构。具体的算法如下所示:
(1) 顶点V入队列。
(2) 当队列非空时继续执行,否则算法为空。
(3) 出队列,获得队头节点V,访问顶点V并标记V已经被访问。
(4) 查找顶点V的第一个邻接顶点col。
(5) 若V的邻接顶点col未被访问过,则col进队列。
(6) 继续查找V的其他邻接顶点col,转到步骤(5),若V的所有邻接顶点都已经被访问过,则转到步骤(2)。
下面,我们以图示的方式介绍宽度优先遍历的过程,如图1.3所示。
图1.3 宽度优先遍历过程 |
选择A作为种子节点,则宽度优先遍历的过程,如表1.2所示。
表1.2 宽度优先遍历过程
操 作 |
队列中的元素 |
初始 |
空 |
A入队列 |
A |
A出队列 |
空 |
BCDEF入队列 |
BCDEF |
B出队列 |
CDEF |
C出队列 |
DEF |
D出队列 |
EF |
E出队列 |
F |
H入队列 |
FH |
F出队列 |
H |
G入队列 |
HG |
H出队列 |
G |
I入队列 |
GI |
G出队列 |
I |
I出队列 |
空 |
在表1.2所示的遍历过程中,出队列的节点顺序既是图的宽度优先遍历的访问顺序。由此可以看出,图1.3所示的宽度优先遍历的访问顺序为
A->B->C->D->E->F->H->G->I
本节讲述了宽度优先遍历的理论基础,把互联网看成一个"超图",则对这张图也可以采用宽度优先遍历的方式进行访问。下面将着重讲解如何对互联网进行宽度优先遍历。