आप चौड़ाई-प्रथम खोज का मार्ग कैसे खोजते हैं, जैसे कि निम्नलिखित उदाहरण में:
यदि कुंजी खोज रहे हैं 11
, तो 1 से 11 को जोड़ने वाली सबसे छोटी सूची लौटाएं ।
[1, 4, 7, 11]
आप चौड़ाई-प्रथम खोज का मार्ग कैसे खोजते हैं, जैसे कि निम्नलिखित उदाहरण में:
यदि कुंजी खोज रहे हैं 11
, तो 1 से 11 को जोड़ने वाली सबसे छोटी सूची लौटाएं ।
[1, 4, 7, 11]
जवाबों:
आपको पहले http://en.wikipedia.org/wiki/Breadth-first_search को देखना चाहिए ।
नीचे एक त्वरित कार्यान्वयन है, जिसमें मैंने रास्तों की कतार का प्रतिनिधित्व करने के लिए सूची की एक सूची का उपयोग किया था।
# graph is in adjacent list representation
graph = {
'1': ['2', '3', '4'],
'2': ['5', '6'],
'5': ['9', '10'],
'4': ['7', '8'],
'7': ['11', '12']
}
def bfs(graph, start, end):
# maintain a queue of paths
queue = []
# push the first path into the queue
queue.append([start])
while queue:
# get the first path from the queue
path = queue.pop(0)
# get the last node from the path
node = path[-1]
# path found
if node == end:
return path
# enumerate all adjacent nodes, construct a new path and push it into the queue
for adjacent in graph.get(node, []):
new_path = list(path)
new_path.append(adjacent)
queue.append(new_path)
print bfs(graph, '1', '11')
एक अन्य दृष्टिकोण प्रत्येक नोड से उसके माता-पिता तक मानचित्रण बनाए रखना होगा, और जब आसन्न नोड का निरीक्षण किया जाएगा, तो उसके माता-पिता को रिकॉर्ड करें। जब खोज पूरी हो जाती है, तो मूल माता-पिता के अनुसार बैकट्रेस करें।
graph = {
'1': ['2', '3', '4'],
'2': ['5', '6'],
'5': ['9', '10'],
'4': ['7', '8'],
'7': ['11', '12']
}
def backtrace(parent, start, end):
path = [end]
while path[-1] != start:
path.append(parent[path[-1]])
path.reverse()
return path
def bfs(graph, start, end):
parent = {}
queue = []
queue.append(start)
while queue:
node = queue.pop(0)
if node == end:
return backtrace(parent, start, end)
for adjacent in graph.get(node, []):
if node not in queue :
parent[adjacent] = node # <<<<< record its parent
queue.append(adjacent)
print bfs(graph, '1', '11')
उपरोक्त कोड इस धारणा पर आधारित हैं कि कोई चक्र नहीं है।
मुझे qiao का पहला उत्तर बहुत पसंद आया! यहां केवल एक चीज गायब है, जैसा कि दौरा किया गया है।
हमें इसे करने की आवश्यकता क्यों है?
चलो कल्पना करते हैं कि नोड 11 से जुड़ा एक और नोड नंबर 13 है। अब हमारा लक्ष्य नोड 13 को ढूंढना है।
थोड़ी देर चलने के बाद कतार इस तरह दिखाई देगी:
[[1, 2, 6], [1, 3, 10], [1, 4, 7], [1, 4, 8], [1, 2, 5, 9], [1, 2, 5, 10]]
ध्यान दें कि अंत में नोड नंबर 10 के साथ दो मार्ग हैं।
जिसका मतलब है कि नोड नंबर 10 से रास्तों को दो बार जांचा जाएगा। इस मामले में यह इतना बुरा नहीं लगता है क्योंकि नोड नंबर 10 के कोई बच्चे नहीं हैं .. लेकिन यह वास्तव में बुरा हो सकता है (यहां तक कि हम बिना किसी कारण दो बार उस नोड की जांच करेंगे ..)
नोड नंबर 13 में नहीं है उन रास्तों ताकि अंत में नोड नंबर 10 के साथ दूसरे मार्ग पर पहुंचने से पहले कार्यक्रम वापस नहीं आएगा..और हम इसे फिर से जाँचेंगे ..
हम सभी को याद कर रहे हैं, एक बार दौरा किए गए नोड्स को चिह्नित करने और उन्हें फिर से जांचने के लिए नहीं है ..
यह संशोधन के बाद qiao का कोड है:
graph = {
1: [2, 3, 4],
2: [5, 6],
3: [10],
4: [7, 8],
5: [9, 10],
7: [11, 12],
11: [13]
}
def bfs(graph_to_search, start, end):
queue = [[start]]
visited = set()
while queue:
# Gets the first path in the queue
path = queue.pop(0)
# Gets the last node in the path
vertex = path[-1]
# Checks if we got to the end
if vertex == end:
return path
# We check if the current node is already in the visited nodes set in order not to recheck it
elif vertex not in visited:
# enumerate all adjacent nodes, construct a new path and push it into the queue
for current_neighbour in graph_to_search.get(vertex, []):
new_path = list(path)
new_path.append(current_neighbour)
queue.append(new_path)
# Mark the vertex as visited
visited.add(vertex)
print bfs(graph, 1, 13)
कार्यक्रम का आउटपुट होगा:
[1, 4, 7, 11, 13]
बेवजह के बिना रीटेक ।।
collections.deque
लिए उपयोगी हो सकता है स्मृति आंदोलनों। इसके अलावा, पश्चात की स्थिति के लिए, यदि आप डीएफएस करना चाहते हैं तो बस सेट करें जिस स्थिति में चर वास्तव में ए की तरह कार्य करता है । queue
O(n)
path = queue.pop()
queue
stack
बहुत आसान कोड। हर बार जब आप एक नोड की खोज करते हैं तो आप पथ को जोड़ते रहते हैं।
graph = {
'A': set(['B', 'C']),
'B': set(['A', 'D', 'E']),
'C': set(['A', 'F']),
'D': set(['B']),
'E': set(['B', 'F']),
'F': set(['C', 'E'])
}
def retunShortestPath(graph, start, end):
queue = [(start,[start])]
visited = set()
while queue:
vertex, path = queue.pop(0)
visited.add(vertex)
for node in graph[vertex]:
if node == end:
return path + [end]
else:
if node not in visited:
visited.add(node)
queue.append((node, path + [node]))
मैंने सोचा कि मैं इस कोड को मज़े के लिए आज़माऊंगा:
graph = {
'1': ['2', '3', '4'],
'2': ['5', '6'],
'5': ['9', '10'],
'4': ['7', '8'],
'7': ['11', '12']
}
def bfs(graph, forefront, end):
# assumes no cycles
next_forefront = [(node, path + ',' + node) for i, path in forefront if i in graph for node in graph[i]]
for node,path in next_forefront:
if node==end:
return path
else:
return bfs(graph,next_forefront,end)
print bfs(graph,[('1','1')],'11')
# >>>
# 1, 4, 7, 11
यदि आप चक्र चाहते हैं तो आप इसे जोड़ सकते हैं:
for i, j in for_front: # allow cycles, add this code
if i in graph:
del graph[i]
मुझे @Qiao का पहला उत्तर और @ या का जोड़ पसंद है। थोड़े कम प्रसंस्करण के लिए मैं या के उत्तर में जोड़ना चाहूंगा।
में @ या का दौरा रखा नोड का जवाब बहुत अच्छा है। हम प्रोग्राम को जल्द से जल्द बाहर निकलने की अनुमति भी दे सकते हैं जो वर्तमान में है। लूप के लिए कुछ बिंदु पर current_neighbour
इच्छाशक्ति होनी चाहिए end
, और ऐसा होने पर सबसे छोटा रास्ता मिल जाता है और प्रोग्राम वापस आ सकता है।
मैं विधि का पालन के रूप में संशोधित करेगा, लूप के लिए करीब ध्यान दें
graph = {
1: [2, 3, 4],
2: [5, 6],
3: [10],
4: [7, 8],
5: [9, 10],
7: [11, 12],
11: [13]
}
def bfs(graph_to_search, start, end):
queue = [[start]]
visited = set()
while queue:
# Gets the first path in the queue
path = queue.pop(0)
# Gets the last node in the path
vertex = path[-1]
# Checks if we got to the end
if vertex == end:
return path
# We check if the current node is already in the visited nodes set in order not to recheck it
elif vertex not in visited:
# enumerate all adjacent nodes, construct a new path and push it into the queue
for current_neighbour in graph_to_search.get(vertex, []):
new_path = list(path)
new_path.append(current_neighbour)
queue.append(new_path)
#No need to visit other neighbour. Return at once
if current_neighbour == end
return new_path;
# Mark the vertex as visited
visited.add(vertex)
print bfs(graph, 1, 13)
आउटपुट और बाकी सभी चीजें समान होंगी। हालांकि, कोड को प्रोसेस होने में कम समय लगेगा। यह विशेष रूप से बड़े रेखांकन पर उपयोगी है। मुझे उम्मीद है कि यह भविष्य में किसी की मदद करता है।