2013-04-23 40 views
6

Tôi biết có hai cách để biểu diễn biểu đồ của tôi: một cách sử dụng ma trận và một cách khác là sử dụng danh sách.Làm cách nào để đảo ngược biểu đồ trong thời gian tuyến tính?

Nếu tôi sử dụng ma trận, tôi phải lật tất cả các bit trong ma trận. Không phải mất thời gian O (V^2) sao?

Nếu tôi sử dụng danh sách, tôi sẽ không phải duyệt qua từng danh sách, từng cái một và tạo một bộ mới? Điều đó dường như có thời gian O (V + E) là tuyến tính. Tôi có đúng không?

Vì vậy, tôi có một câu hỏi khác tại đây. Hãy xem xét, ví dụ, tôi sử dụng thuật toán Dijkstra trên đồ thị của tôi (ma trận hoặc danh sách), và chúng tôi sử dụng hàng đợi ưu tiên cho cấu trúc dữ liệu đằng sau hiện trường. Có mối quan hệ nào về biểu diễn biểu đồ và việc sử dụng cấu trúc dữ liệu không? Nó có ảnh hưởng đến hiệu suất của thuật toán không?

Giả sử tôi sử dụng danh sách đại diện và hàng đợi ưu tiên cho thuật toán Dijkstra, liệu có sự khác biệt giữa ma trận và xếp hàng ưu tiên sử dụng cho Dijkstra không?

Tôi đoán nó chỉ liên quan đến hoạt động makeQueue? Hoặc họ không có khác nhau ở tất cả?

+0

Traversal danh sách kề không xảy ra trong thời gian tuyến tính trong chung như E = O (V^2). – collapsar

+0

@collapsar Nó * luôn luôn * xảy ra trong thời gian tuyến tính có liên quan đến các đỉnh * và cạnh *. Để xác định độ phức tạp thời gian chỉ trên một phần của đầu vào (nghĩa là chỉ đỉnh) (không nêu rõ) có vẻ hơi phi lý, * đặc biệt là * khi thời gian liên quan trực tiếp đến một phần khác của đầu vào (nhưng tôi không thể tranh luận rằng mọi người có thể định nghĩa nó như bạn đã làm). Và E = O (V^2) là cho các đồ thị dày đặc. Đồ thị thưa thớt là E = O (V). – Dukeling

+0

@ dukeling bạn đúng khi chỉ ra rằng việc giảm kích thước của một vấn đề đối với một vô hướng duy nhất liên quan đến việc thiếu chính xác. otoh, ký hiệu lớn-Oh mô tả trường hợp xấu nhất và, xem xét đồ thị, không có ràng buộc bổ sung trường hợp xấu nhất có nghĩa là E = O (V^2). là chính xác, O (V^2) không chính xác cho việc đảo ngược cạnh trên ma trận kề - hoặc nếu thể hiện biểu diễn một cột cờ lớn so với col-major, chuyển vị là O (1). – collapsar

Trả lời

19

Đảo ngược danh sách kề của Đồ thị được chỉ định có thể được thực hiện trong thời gian tuyến tính. Chúng tôi chỉ duyệt qua biểu đồ một lần. Thứ tự phức tạp sẽ là O (| V | + | E |).

  1. Duy trì HashMap của danh sách Adjaceny trong đó khóa là nhãn đỉnh và giá trị là một ArrayList của các đỉnh liền kề của đỉnh khóa.
  2. Để đảo ngược, hãy tạo HashMap mới cùng loại. Quét bản đồ băm ban đầu và cho mỗi phím bạn đi qua, duyệt qua danh sách tương ứng.
  3. Đối với mỗi đỉnh được tìm thấy trong danh sách giá trị, thêm khóa trong hashMap mới, đặt khóa của HashMap gốc làm mục nhập trong ArrayList tương ứng với khóa mới trong HashMap mới.
public static HashMap<Character,ArrayList <Character>> getReversedAdjLists(RGraph g) 
{ 
    HashMap <Character, ArrayList<Character>> revAdjListMap = new HashMap <Character, ArrayList<Character>>(); 
    Set <Character> oldLabelSet = g.adjListMap.keySet(); 

    for(char oldLabel:oldLabelSet) 
    { 
     ArrayList<Character> oldLabelList = g.adjListMap.get(oldLabel); 

     for (char newLabel : oldLabelList) 
     { 
      ArrayList<Character> newLabelList = revAdjListMap.get(newLabel); 

      if (newLabelList == null) 
      { 
       newLabelList = new ArrayList<Character>(); 
       newLabelList.add(oldLabel); 
      } 
      else if (! newLabelList.contains(oldLabel)) 
      { 
       newLabelList.add(oldLabel); 
      } 

      revAdjListMap.put(newLabel, newLabelList); 
     } 
    } 

    return revAdjListMap; 
} 
+0

Câu trả lời hay. Ban đầu tôi đã cố gắng làm điều này với một mảng 2D tĩnh, nhưng sự chuyển vị của ma trận đó (để hoàn thành đảo ngược) là O (n^2) tôi khá chắc chắn. – scottyseus

0

Tôi nghĩ việc đảo ngược biểu đồ bằng cách duyệt qua danh sách sẽ là O (V), vì mỗi đỉnh bạn phải thêm hoặc xóa cạnh (V-1). Đối với thuật toán Dijkstra, như tôi hiểu, nếu bạn đại diện cho đồ thị dưới dạng ma trận hoặc danh sách thuật toán lấy O (V), nhưng một số cấu trúc dữ liệu khác sẽ nhanh hơn. Nhanh nhất được biết đến là một đống Fibonacci, cung cấp cho O (E + VlogV).

+0

Nếu tôi giữ hai danh sách thì sao? Danh sách các cạnh đến và danh sách các cạnh đi, điều này có vẻ là một ý tưởng tốt? –

+0

@TimothyLeung: Tại sao? Tôi không thấy làm thế nào mà sẽ cung cấp cho bất kỳ lợi thế hơn một danh sách các cạnh đi. – Beta

+0

@Beta Tôi tưởng tượng nó sẽ chỉ là O (V^2) khi biểu đồ dày đặc. Xem xét không có cạnh. Bạn chỉ làm O (1) làm việc ở mọi đỉnh, do đó, O (V). Do đó các cạnh phải đi vào trong sự phức tạp. – Dukeling

Các vấn đề liên quan