2013-02-16 32 views
9

Có thể sử dụng logic tìm kiếm đầu tiên trên bề rộng để thực hiện một loại topo của DAG không? Các giải pháp trong Cormen sử dụng độ sâu tìm kiếm đầu tiên nhưng sẽ không dễ dàng hơn để sử dụng BFS?Tìm kiếm topo và tìm kiếm theo chiều rộng đầu tiên

Lý do: BFS truy cập tất cả các nút ở độ sâu cụ thể trước khi truy cập các nút có giá trị độ sâu tiếp theo. Nó tự nhiên có nghĩa là cha mẹ sẽ được liệt kê trước khi trẻ em nếu chúng ta làm một BFS. Đây không phải là chính xác những gì chúng ta cần cho một loại topo sao?

+0

Có, nó có thể được thực hiện. https://www.quora.com/Can-topological-sorting-be-done-using-BFS –

Trả lời

3

Trong BFS, tất cả các cạnh bạn thực sự đi bộ sẽ kết thúc theo đúng hướng. Nhưng tất cả các cạnh bạn không đi bộ (các nút giữa các nút ở cùng độ sâu, hoặc các nút từ các nút sâu trở lại các nút trước đó) sẽ kết thúc theo cách sai nếu bạn đặt đồ thị theo thứ tự BFS.

Có, bạn thực sự cần DFS để làm điều đó.

+1

Hãy xem điều này: https://www.quora.com/Can-topological-sorting-be-done- sử dụng-BFS –

5

Có thể, ngay cả wikipedia describes an algorithm based on BFS.

Về cơ bản, bạn sử dụng hàng đợi trong đó bạn chèn tất cả các nút không có cạnh đến. Sau đó, khi bạn giải nén một nút, bạn loại bỏ tất cả các cạnh đi của nó và chèn các nút có thể truy cập từ nó mà không có các cạnh đến khác.

6

Một chỉ BFS là chỉ đủ cho một cây (hoặc rừng cây), bởi vì trong (rừng) cây, trong độ là tối đa là 1. Bây giờ, nhìn vào trường hợp này:

B → C → D 
     ↗ 
    A 

Một BFS nơi hàng đợi được khởi tạo đến A B (có độ bằng 0) sẽ trả lại A B D C, không được sắp xếp topo. Đó là lý do tại sao bạn phải duy trì số lượng độ trong và chỉ chọn các nút có số lượng đã giảm xuống 0. (*)

BTW, đây là lỗi của 'lý do' của bạn: BFS chỉ đảm bảo một phụ huynh đã được truy cập trước đó, không phải tất cả chúng.

Sửa: (*) Nói cách khác bạn đẩy lùi các nút lân cận mà trong độ là zero (trong dụ, sau khi xử lý A, D sẽ bỏ qua). Vì vậy, bạn vẫn đang sử dụng hàng đợi và bạn vừa thêm bước lọc vào thuật toán chung. Điều đó đang được nói, tiếp tục gọi nó là một BFS là vấn đề.

0

Có, bạn có thể thực hiện phân loại topo bằng cách sử dụng BFS. Thật ra tôi đã nhớ khi giáo viên nói với tôi rằng nếu vấn đề có thể được giải quyết bằng BFS, không bao giờ chọn giải quyết nó bằng DFS. Vì logic cho BFS đơn giản hơn DFS, phần lớn thời gian bạn sẽ luôn muốn có giải pháp đơn giản cho vấn đề.

Như YvesgereY và IVlad đã đề cập, bạn cần phải bắt đầu với các nút trong đó indegree là , có nghĩa là không có các nút khác chỉ đạo đối với họ. Hãy chắc chắn để thêm các nút này vào kết quả của bạn trước tiên.Bạn có thể sử dụng một HashMap để ánh xạ mọi nút với sự không rõ ràng của nó, và một hàng đợi rất thường thấy trong BFS để hỗ trợ truyền tải của bạn. Khi bạn thăm dò ý kiến ​​một nút từ hàng đợi, sự chênh lệch của hàng xóm của nó cần phải được giảm xuống 1, điều này giống như xóa nút khỏi biểu đồ và xóa cạnh giữa nút và các nút lân cận. Mỗi khi bạn đi qua các nút với 0 không đồng ý, hãy cung cấp cho họ hàng đợi để kiểm tra hàng xóm của họ sau đó và thêm họ vào kết quả.

public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) { 

    ArrayList<DirectedGraphNode> result = new ArrayList<>(); 
    if (graph == null || graph.size() == 0) { 
     return result; 
    } 
    Map<DirectedGraphNode, Integer> indegree = new HashMap<DirectedGraphNode, Integer>(); 
    Queue<DirectedGraphNode> queue = new LinkedList<DirectedGraphNode>(); 

    //mapping node to its indegree to the HashMap, however these nodes 
    //have to be directed to by one other node, nodes whose indegree == 0 
    //would not be mapped. 
    for (DirectedGraphNode DAGNode : graph){ 
     for (DirectedGraphNode nei : DAGNode.neighbors){ 
      if(indegree.containsKey(nei)){ 
       indegree.put(nei, indegree.get(nei) + 1); 
      } else { 
       indegree.put(nei, 1); 
      } 
     } 
    } 


    //find all nodes with indegree == 0. They should be at starting positon in the result 
    for (DirectedGraphNode GraphNode : graph) { 
     if (!indegree.containsKey(GraphNode)){ 
      queue.offer(GraphNode); 
      result.add(GraphNode); 
     } 
    } 


    //everytime we poll out a node from the queue, it means we delete it from the 
    //graph, we will minus its neighbors indegree by one, this is the same meaning 
    //as we delete the edge from the node to its neighbors. 
    while (!queue.isEmpty()) { 
     DirectedGraphNode temp = queue.poll(); 
     for (DirectedGraphNode neighbor : temp.neighbors){ 
      indegree.put(neighbor, indegree.get(neighbor) - 1); 
      if (indegree.get(neighbor) == 0){ 
       result.add(neighbor); 
       queue.offer(neighbor); 
      } 
     } 
    } 
    return result; 
} 
Các vấn đề liên quan