def breadth_first_search(graph, root=None, filter=null()):
    """
    Breadth-first search.

    @type  graph: graph, digraph
    @param graph: Graph.

    @type  root: node
    @param root: Optional root node (will explore only root's connected component)

    @rtype:  tuple
    @return: A tuple containing a dictionary and a list.
        1. Generated spanning tree
        2. Graph's level-based ordering
    """

    def bfs():
        """
        Breadth-first search subfunction.
        """
        while (queue != []):
            node = queue.pop(0)
            
            for other in graph[node]:
                if (other not in spanning_tree and filter(other, node)):
                    queue.append(other)
                    ordering.append(other)
                    spanning_tree[other] = node
    
    queue = []            # Visiting queue
    spanning_tree = {}    # Spanning tree
    ordering = []
    filter.configure(graph, spanning_tree)
    
    # BFS from one node only
    if (root is not None):
        if (filter(root, None)):
            queue.append(root)
            ordering.append(root)
            spanning_tree[root] = None
            bfs()
        return spanning_tree, ordering

    # Algorithm
    for each in graph:
        if (each not in spanning_tree):
            if (filter(each, None)):
                queue.append(each)
                ordering.append(each)
                spanning_tree[each] = None
                bfs()

    return spanning_tree, ordering
def depth_first_search(graph, root=None, filter=null()):
    """
    Depth-first search.

    @type  graph: graph, digraph
    @param graph: Graph.
    
    @type  root: node
    @param root: Optional root node (will explore only root's connected component)

    @rtype:  tuple
    @return: A tupple containing a dictionary and two lists:
        1. Generated spanning tree
        2. Graph's preordering
        3. Graph's postordering
    """

    def dfs(node):
        """
        Depht-first search subfunction.
        """
        visited[node] = 1
        pre.append(node)
        # Explore recursively the connected component
        for each in graph[node]:
            if (each not in visited and filter(each, node)):
                spanning_tree[each] = node
                dfs(each)
        post.append(node)

    visited = {}            # List for marking visited and non-visited nodes
    spanning_tree = {}      # Spanning tree
    pre = []                # Graph's preordering
    post = []               # Graph's postordering
    filter.configure(graph, spanning_tree)

    # DFS from one node only
    if (root is not None):
        if (filter(root, None)):
            spanning_tree[root] = None
            dfs(root)
        return spanning_tree, pre, post
    
    # Algorithm loop
    for each in graph:
        # Select a non-visited node
        if (each not in visited and filter(each, None)):
            spanning_tree[each] = None
            # Explore node's connected component
            dfs(each)

    return spanning_tree, pre, post