图的遍历可分为广度优先遍历和深度优先遍历
广度优先遍历:先访问一个顶点,然后访问顶点的邻居顶点;
实现:每当一个顶点被访问后,就将其放入队列中,当对头顶点出列时,访问其未被访问的邻接点并令这些邻接顶点入队。
图示例:
图的遍历:
frontVertex |
nextNeighhor |
已访问的顶点 |
vertexQueue |
traversalorder |
|
|
A |
A |
A |
A |
|
|
空 |
|
|
B |
B |
B |
AB |
|
D |
D |
BD |
ABD |
|
E |
E |
BDE |
ABDE |
B |
|
|
DE |
|
D |
|
|
E |
|
|
G |
G |
EG |
ABDEG |
E |
|
|
G |
|
|
F |
F |
GF |
ABDEGF |
|
H |
H |
GFH |
ABDEGFH |
G |
|
|
FH |
|
F |
|
|
H |
|
|
C |
C |
HC |
ABDEGFHC |
H |
|
|
C |
|
|
I |
I |
CI |
ABDEGFHCI |
C |
|
|
I |
|
I |
|
|
空 |
|
遍历过程进出栈描述:
访问A顶点,进入vertexQueue队,A出队访问该顶点可访问的顶点,访问B顶点,B顶点没有可访问顶点,D顶点出队访问其可访问顶点G,E顶点出队,访问E顶点可到达顶点F、H,G出队访问其可访问未被访问过的顶点(G可访问的顶点为H,因为之前已访问过,所以不再访问),F出队访问C顶点,然后H出队访问I顶点,C出队,I出队,队为空,遍历结束。
伪代码描述:
getBreadthFirstTraversal(originVertex){ traversalorder = 得到遍历次序的新队列 vertexQueue = 在访问顶点时用于保存顶点的新队列 标记orginVertex为已访问 traversalorder.enqueue(originVertex) vertexQueue.enqueue(originVertex) while(!vertexQueue.isEmpty()){ frontVertex = vertexQueue.dequeue() while(frontVertex有一个邻居){ nextNeighbor = frontVertex的下一个邻居 if(nextNeighbor未被访问){ 标记nextNeighbor为已访问 traversalorder.enqueue(nextNeighbor) vertexQueue.enqueue(nextNeighbor) } } } }
图的深度优先遍历:初始时将起始顶点入栈,当栈顶中的顶点有未被访问的邻居时,访问它并它的邻居入栈,如果不存在这样的邻居则出栈。
由顶点A遍历过程:
topVertex |
nextNeighbor |
已访问的顶点 |
vertexStack |
traversalorder |
|
|
A |
A |
A |
A |
|
|
A |
|
|
B |
B |
BA |
AB |
B |
|
|
BA |
|
|
E |
E |
EBA |
ABE |
E |
|
|
EBA |
|
|
F |
F |
FEBA |
ABEF |
F |
|
|
FEBA |
|
|
C |
C |
CFEBA |
ABEFC |
C |
|
|
FEBA |
|
F |
|
|
FEBA |
|
|
H |
H |
HFEBA |
ABEFCH |
H |
|
|
HFEBA |
|
|
I |
I |
IHFEBA |
ABEFCHI |
I |
|
|
HFEBA |
|
H |
|
|
FEBA |
|
F |
|
|
EBA |
|
E |
|
|
BA |
|
B |
|
|
A |
|
A |
|
|
A |
|
|
D |
D |
DA |
ABEFCHID |
D |
|
|
DA |
|
|
G |
G |
GDA |
ABEFCHIDG |
G |
|
|
DA |
|
D |
|
|
A |
|
A |
|
|
空 |
ABEFCHIDG |