|
2 | 2 | Contains all the algorithms associated with graph
|
3 | 3 | data structure.
|
4 | 4 | """
|
5 |
| -from collections import deque as Queue |
| 5 | +from collections import deque |
6 | 6 | from concurrent.futures import ThreadPoolExecutor
|
7 | 7 | from pydatastructs.utils import GraphEdge
|
8 | 8 | from pydatastructs.utils.misc_util import _comp
|
|
16 | 16 | 'breadth_first_search_parallel',
|
17 | 17 | 'minimum_spanning_tree',
|
18 | 18 | 'minimum_spanning_tree_parallel',
|
19 |
| - 'strongly_connected_components' |
| 19 | + 'strongly_connected_components', |
| 20 | + 'depth_first_search' |
20 | 21 | ]
|
21 | 22 |
|
| 23 | +Stack = Queue = deque |
| 24 | + |
22 | 25 | def breadth_first_search(
|
23 | 26 | graph, source_node, operation, *args, **kwargs):
|
24 | 27 | """
|
@@ -548,3 +551,89 @@ def strongly_connected_components(graph, algorithm):
|
548 | 551 | "isn't implemented for finding strongly connected components."
|
549 | 552 | %(algorithm, graph._impl))
|
550 | 553 | return getattr(algorithms, func)(graph)
|
| 554 | + |
| 555 | +def depth_first_search( |
| 556 | + graph, source_node, operation, *args, **kwargs): |
| 557 | + """ |
| 558 | + Implementation of depth first search (DFS) |
| 559 | + algorithm. |
| 560 | +
|
| 561 | + Parameters |
| 562 | + ========== |
| 563 | +
|
| 564 | + graph: Graph |
| 565 | + The graph on which DFS is to be performed. |
| 566 | + source_node: str |
| 567 | + The name of the source node from where the DFS is |
| 568 | + to be initiated. |
| 569 | + operation: function |
| 570 | + The function which is to be applied |
| 571 | + on every node when it is visited. |
| 572 | + The prototype which is to be followed is, |
| 573 | + `function_name(curr_node, next_node, |
| 574 | + arg_1, arg_2, . . ., arg_n)`. |
| 575 | + Here, the first two arguments denote, the |
| 576 | + current node and the node next to current node. |
| 577 | + The rest of the arguments are optional and you can |
| 578 | + provide your own stuff there. |
| 579 | +
|
| 580 | + Note |
| 581 | + ==== |
| 582 | +
|
| 583 | + You should pass all the arguments which you are going |
| 584 | + to use in the prototype of your `operation` after |
| 585 | + passing the operation function. |
| 586 | +
|
| 587 | + Examples |
| 588 | + ======== |
| 589 | +
|
| 590 | + >>> from pydatastructs import Graph, AdjacencyListGraphNode |
| 591 | + >>> V1 = AdjacencyListGraphNode("V1") |
| 592 | + >>> V2 = AdjacencyListGraphNode("V2") |
| 593 | + >>> V3 = AdjacencyListGraphNode("V3") |
| 594 | + >>> G = Graph(V1, V2, V3) |
| 595 | + >>> from pydatastructs import depth_first_search |
| 596 | + >>> def f(curr_node, next_node, dest_node): |
| 597 | + ... return curr_node != dest_node |
| 598 | + ... |
| 599 | + >>> G.add_edge(V1.name, V2.name) |
| 600 | + >>> G.add_edge(V2.name, V3.name) |
| 601 | + >>> depth_first_search(G, V1.name, f, V3.name) |
| 602 | +
|
| 603 | + References |
| 604 | + ========== |
| 605 | +
|
| 606 | + .. [1] https://en.wikipedia.org/wiki/Depth-first_search |
| 607 | + """ |
| 608 | + import pydatastructs.graphs.algorithms as algorithms |
| 609 | + func = "_depth_first_search_" + graph._impl |
| 610 | + if not hasattr(algorithms, func): |
| 611 | + raise NotImplementedError( |
| 612 | + "Currently depth first search isn't implemented for " |
| 613 | + "%s graphs."%(graph._impl)) |
| 614 | + return getattr(algorithms, func)( |
| 615 | + graph, source_node, operation, *args, **kwargs) |
| 616 | + |
| 617 | +def _depth_first_search_adjacency_list( |
| 618 | + graph, source_node, operation, *args, **kwargs): |
| 619 | + dfs_stack = Stack() |
| 620 | + visited = dict() |
| 621 | + dfs_stack.append(source_node) |
| 622 | + visited[source_node] = True |
| 623 | + while len(dfs_stack) != 0: |
| 624 | + curr_node = dfs_stack.pop() |
| 625 | + next_nodes = graph.neighbors(curr_node) |
| 626 | + if len(next_nodes) != 0: |
| 627 | + for next_node in next_nodes: |
| 628 | + if next_node.name not in visited: |
| 629 | + status = operation(curr_node, next_node.name, *args, **kwargs) |
| 630 | + if not status: |
| 631 | + return None |
| 632 | + dfs_stack.append(next_node.name) |
| 633 | + visited[next_node.name] = True |
| 634 | + else: |
| 635 | + status = operation(curr_node, "", *args, **kwargs) |
| 636 | + if not status: |
| 637 | + return None |
| 638 | + |
| 639 | +_depth_first_search_adjacency_matrix = _depth_first_search_adjacency_list |
0 commit comments