1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
"""
Search algorithms.
"""
__authors__ = """Eben Kenah\nAric Hagberg (hagberg@lanl.gov)"""
# Copyright (C) 2004-2008 by
# Aric Hagberg <hagberg@lanl.gov>
# Dan Schult <dschult@colgate.edu>
# Pieter Swart <swart@lanl.gov>
# All rights reserved.
# BSD license.
__all__ = ['dfs_preorder', 'dfs_postorder',
'dfs_predecessor', 'dfs_successor', 'dfs_tree']
import networkx
def dfs_preorder(G,source=None,reverse_graph=False):
"""Return list of nodes connected to source in depth-first-search preorder.
Traverse the graph G with depth-first-search from source.
Non-recursive algorithm.
"""
if source is None:
nlist=G.nodes() # process entire graph
else:
nlist=[source] # only process component with source
if reverse_graph:
try:
neighbors=G.predecessors_iter
except:
neighbors=G.neighbors_iter
else:
neighbors=G.neighbors_iter
seen={} # nodes seen
pre=[] # list of nodes in a DFS preorder
for source in nlist:
if source in seen: continue
queue=[source] # use as LIFO queue
while queue:
v=queue[-1]
if v not in seen:
pre.append(v)
seen[v]=True
done=1
for w in neighbors(v):
if w not in seen:
queue.append(w)
done=0
break
if done==1:
queue.pop()
return pre
def dfs_postorder(G,source=None,reverse_graph=False):
"""
Return list of nodes connected to source in depth-first-search postorder.
Traverse the graph G with depth-first-search from source.
Non-recursive algorithm.
"""
if source is None:
nlist=G.nodes() # process entire graph
else:
nlist=[source] # only process component with source
if reverse_graph==True:
try:
neighbors=G.predecessors_iter
except:
neighbors=G.neighbors_iter
else:
neighbors=G.neighbors_iter
seen={} # nodes seen
post=[] # list of nodes in a DFS postorder
for source in nlist:
if source in seen: continue
queue=[source] # use as LIFO queue
while queue:
v=queue[-1]
if v not in seen:
seen[v]=True
done=1
for w in neighbors(v):
if w not in seen:
queue.append(w)
done=0
break
if done==1:
post.append(v)
queue.pop()
return post
def dfs_tree(G,source=None,reverse_graph=False):
"""Return directed graph (tree) of depth-first-search with root at source.
If the graph is disconnected, return a disconnected graph (forest).
"""
succ=dfs_successor(G,source=source,reverse_graph=reverse_graph)
return networkx.DiGraph(succ)
def dfs_predecessor(G,source=None,reverse_graph=False):
"""
Return predecessors of depth-first-search with root at source.
"""
if source is None:
nlist=G.nodes() # process entire graph
else:
nlist=[source] # only process component with source
if reverse_graph==True:
try:
neighbors=G.predecessors_iter
except:
neighbors=G.neighbors_iter
else:
neighbors=G.neighbors_iter
seen={} # nodes seen
pred={}
for source in nlist:
if source in seen: continue
queue=[source] # use as LIFO queue
pred[source]=[]
while queue:
v=queue[-1]
if v not in seen:
seen[v]=True
done=1
for w in neighbors(v):
if w not in seen:
queue.append(w)
pred[w]=[v] # Each node has at most one predecessor
done=0
break
if done==1:
queue.pop()
return pred
def dfs_successor(G,source=None,reverse_graph=False):
"""
Return succesors of depth-first-search with root at source.
"""
if source is None:
nlist=G.nodes() # process entire graph
else:
nlist=[source] # only process component with source
if reverse_graph==True:
try:
neighbors=G.predecessors_iter
except:
neighbors=G.neighbors_iter
else:
neighbors=G.neighbors_iter
seen={} # nodes seen
succ={}
for source in nlist:
if source in seen: continue
queue=[source] # use as LIFO queue
while queue:
v=queue[-1]
if v not in seen:
seen[v]=True
succ[v]=[]
done=1
for w in neighbors(v):
if w not in seen:
queue.append(w)
succ[v].append(w)
done=0
break
if done==1:
queue.pop()
return succ
|