2010-04-15 37 views
8

Thời hạn cho dự án này đang kết thúc nhanh chóng và tôi không có nhiều thời gian để giải quyết những gì nó còn lại. Vì vậy, thay vì tìm kiếm các thuật toán tốt nhất (và có lẽ phức tạp hơn/tốn thời gian), tôi đang tìm các thuật toán dễ nhất để thực hiện một vài thao tác trên một cấu trúc Graph.Gợi ý các thuật toán đơn giản nhất cho một số thao tác Biểu đồ

Các hoạt động tôi sẽ cần phải làm như sau:

  • Liệt kê tất cả người dùng trong mạng theo đồ thị được đưa ra một khoảng cách X
  • Liệt kê tất cả người dùng trong mạng theo đồ thị được đưa ra một khoảng cách X và loại các mối quan hệ
  • Tính con đường ngắn nhất giữa 2 người dùng trên mạng theo đồ thị được đưa ra một loại quan hệ
  • Tính khoảng cách tối đa giữa 2 người dùng trên mạng theo đồ thị
  • Tính mo st người dùng kết nối từ xa trên mạng graph

Một vài lưu ý về thực hiện Graph tôi:

  • Nút cạnh có 2 thuộc tính, là một trong những loại charint khác. Chúng đại diện cho loại quan hệ và trọng lượng tương ứng.
  • Đồ thị được triển khai với danh sách được liên kết, cho cả hai đỉnh và cạnh. Ý tôi là, mỗi đỉnh trỏ đến điểm tiếp theo và mỗi đỉnh cũng trỏ tới đầu của một danh sách liên kết khác, các cạnh của đỉnh cụ thể đó.

Những gì tôi biết về những gì tôi cần phải làm:

  • Tôi không biết nếu điều này là đơn giản nhất như tôi đã nói ở trên, nhưng đối với con đường ngắn nhất giữa 2 người, tôi tin rằng các Dijkstra thuật toán là những gì mọi người dường như đề nghị khá thường xuyên vì vậy tôi nghĩ rằng tôi sẽ đi với điều đó.
    • Tôi đã tìm kiếm và tìm kiếm và tôi thấy khó thực hiện thuật toán này, có ai biết về bất kỳ hướng dẫn nào hay dễ hiểu vì vậy tôi có thể tự thực hiện thuật toán này không? Nếu có thể, với các ví dụ mã nguồn C, nó sẽ giúp ích rất nhiều. Tôi thấy nhiều ví dụ với ký hiệu toán học nhưng điều đó chỉ làm tôi bối rối hơn.
    • Bạn có nghĩ rằng điều này sẽ hữu ích nếu tôi "chuyển đổi" biểu đồ thành ma trận kề để đại diện cho trọng số liên kết và loại quan hệ? Nó sẽ được dễ dàng hơn để thực hiện các thuật toán trên đó thay vì các danh sách liên kết? Tôi có thể dễ dàng thực hiện một chức năng để thực hiện chuyển đổi đó khi cần thiết. Tôi đang nói điều này bởi vì tôi có cảm giác sẽ dễ dàng hơn sau khi đọc một vài trang về chủ đề này, nhưng tôi có thể sai.
  • Tôi không có bất kỳ ý tưởng nào về 4 hoạt động, đề xuất khác?

Trả lời

8

Liệt kê tất cả người dùng trong mạng theo đồ thị được đưa ra một khoảng cách X

Một khoảng cách X từ những gì? từ nút bắt đầu hoặc khoảng cách X giữa chúng? Bạn có thể đưa ra một ví dụ không? Điều này có thể hoặc có thể không đơn giản như thực hiện tìm kiếm BF hoặc chạy Dijkstra.

Giả sử bạn bắt đầu tại một nút nhất định và muốn liệt kê tất cả các nút có khoảng cách X đến nút bắt đầu, chỉ cần chạy BFS từ nút bắt đầu. Khi bạn sắp chèn một nút mới vào hàng đợi, kiểm tra xem khoảng cách từ nút bắt đầu đến nút bạn muốn chèn nút mới từ + trọng số của cạnh từ nút bạn muốn chèn nút mới từ đến nút mới là < = X. Nếu nó thấp hơn, chèn nút mới và nếu nó bằng nhau chỉ cần in nút mới (và chỉ chèn nó nếu bạn cũng có thể có 0 như là một trọng lượng cạnh).

Liệt kê tất cả người dùng trong mạng theo đồ thị được đưa ra một khoảng cách X và loại liên quan

Xem ở trên. Chỉ cần nhân tố trong kiểu quan hệ vào BFS: nếu kiểu của cha/mẹ khác với kiểu của nút bạn đang cố chèn vào hàng đợi, đừng chèn nó vào.

Tính con đường ngắn nhất giữa 2 người dùng trên mạng theo đồ thị được đưa ra một loại quan hệ

Các thuật toán phụ thuộc vào một số yếu tố:

  • Bao lâu thì bạn sẽ cần phải tính toán điều này?
  • Bạn có bao nhiêu nút?

Vì bạn muốn dễ dàng, dễ nhất là Roy-Floyd và Dijkstra's.

  • Sử dụng Roy-Floyd là khối trong số lượng nút, vì vậy không hiệu quả. Chỉ sử dụng điều này nếu bạn có thể đủ khả năng để chạy nó một lần và sau đó trả lời mỗi truy vấn trong O (1). Sử dụng điều này nếu bạn có thể đủ khả năng để giữ ma trận kề trong bộ nhớ.
  • Dijkstra là bậc hai về số lượng nút nếu bạn muốn giữ cho nó đơn giản, nhưng bạn sẽ phải chạy nó mỗi lần bạn muốn tính khoảng cách giữa hai nút. Nếu bạn muốn sử dụng Dijkstra's, hãy sử dụng danh sách kề.

Dưới đây là các triển khai C: Roy-FloydDijkstra_1, Dijkstra_2. Bạn có thể tìm thấy rất nhiều trên google với "<algorithm name> c implementation".

Chỉnh sửa: Roy-Floyd nằm ngoài câu hỏi cho 18 000 nút, như là ma trận kề. Nó sẽ mất quá nhiều thời gian để xây dựng và quá nhiều bộ nhớ. Đặt cược tốt nhất của bạn là sử dụng thuật toán Dijkstra cho mỗi truy vấn, nhưng tốt nhất là triển khai Dijkstra bằng cách sử dụng một đống - trong các liên kết mà tôi đã cung cấp, hãy sử dụng một đống để tìm mức tối thiểu. Nếu bạn chạy Dijkstra cổ điển trên mỗi truy vấn, điều đó cũng có thể mất một thời gian rất dài.

Một tùy chọn khác là sử dụng thuật toán Bellman-Ford trên mỗi truy vấn, sẽ cung cấp cho bạn thời gian chạy là O(Nodes*Edges) cho mỗi truy vấn. Tuy nhiên, đây là một đánh giá quá cao nếu bạn không thực hiện nó như Wikipedia nói với bạn. Thay vào đó, hãy sử dụng hàng đợi tương tự như hàng được sử dụng trong BFS. Bất cứ khi nào một nút cập nhật khoảng cách của nó từ nguồn, chèn nút đó trở lại vào hàng đợi. Điều này sẽ rất nhanh trong thực tế, và cũng sẽ làm việc cho trọng lượng tiêu cực. Tôi đề nghị bạn sử dụng hoặc là Dijkstra với đống, vì Dijkstra cổ điển có thể mất một thời gian dài trên 18 000 nút.

Tính khoảng cách tối đa giữa 2 người dùng trên mạng theo đồ thị

Cách đơn giản nhất là sử dụng tùy ý: thử tất cả các khả năng và giữ cho con đường dài nhất được tìm thấy. This is NP-complete, vì vậy các giải pháp đa thức không tồn tại.

Điều này thực sự tệ nếu bạn có 18 000 nút, tôi không biết bất kỳ thuật toán nào (đơn giản hoặc cách khác) sẽ hoạt động khá nhanh cho nhiều nút. Xem xét xấp xỉ nó bằng cách sử dụng các thuật toán tham lam.Hoặc có thể biểu đồ của bạn có các thuộc tính nhất định mà bạn có thể tận dụng. Ví dụ, nó là một DAG (Đồ thị theo chu kỳ)?

Tính người dùng kết nối xa nhất trên mạng graph

Nghĩa là bạn muốn tìm đường kính của đồ thị. Cách đơn giản nhất để làm điều này là tìm khoảng cách giữa hai nút (tất cả các cặp đường ngắn nhất - hoặc chạy Roy-Floyd hoặc Dijkstra giữa hai nút và chọn hai với khoảng cách tối đa).

Một lần nữa, điều này rất khó thực hiện nhanh chóng với số lượng nút và cạnh của bạn. Tôi e rằng bạn không may mắn về hai câu hỏi cuối cùng này, trừ khi biểu đồ của bạn có các thuộc tính đặc biệt có thể được khai thác.

Bạn có nghĩ rằng nó sẽ giúp ích nếu tôi "chuyển đổi" biểu đồ thành ma trận kề để đại diện cho trọng số liên kết và loại quan hệ? Nó sẽ được dễ dàng hơn để thực hiện các thuật toán trên đó thay vì các danh sách liên kết? Tôi có thể dễ dàng thực hiện một chức năng để thực hiện chuyển đổi đó khi cần thiết. Tôi đang nói điều này bởi vì tôi có cảm giác sẽ dễ dàng hơn sau khi đọc một vài trang về chủ đề này, nhưng tôi có thể sai.

Không, ma trận kề và Roy-Floyd là một ý tưởng rất tồi trừ khi ứng dụng của bạn nhắm mục tiêu siêu máy tính.

+0

1) Khoảng cách X, tôi giả sử nó giống như tổng trọng lượng giữa 2 nút. 2) Tôi không biết tần suất, các hoạt động ở trên là các tùy chọn trong menu Giao diện người dùng. 3) Nó giống như ~ 18000 đỉnh với ~ 520000 liên kết trên mẫu dữ liệu được cung cấp. 4) Ngoài ra, cảm ơn các liên kết, tôi sẽ điều tra ... –

+0

Tôi đã cập nhật câu trả lời của mình và cũng đã thêm một số câu hỏi khác :). – IVlad

+0

Không có đặc tính đặc biệt ... Vâng, nếu bạn nói không có thuật toán đặc biệt và sẽ mất quá nhiều thời gian với những thuật toán thông thường, hơn là tôi không hiểu điểm của các hoạt động này là một phần của dự án. Năm ngoái (mà tôi đã không hoàn thành vì các vấn đề cá nhân) dự án tương tự nhưng chỉ có con đường ngắn nhất được hỏi: S –

5

Giả sử O(E log V) là thời gian chạy được chấp nhận, nếu bạn đang làm điều gì đó trực tuyến, điều này có thể không thực hiện được, và nó sẽ yêu cầu một số máy móc được hỗ trợ cao hơn.

  • Liệt kê tất cả người dùng trong mạng theo đồ thị được đưa ra một khoảng cách X

Djikstra's algorithm là tốt cho điều này, trong một thời gian sử dụng. Bạn có thể lưu kết quả để sử dụng trong tương lai, với quét tuyến tính qua tất cả các đỉnh (hoặc tốt hơn, sắp xếp và tìm kiếm nhị phân).

  • Liệt kê tất cả người dùng trong mạng theo đồ thị được đưa ra một khoảng cách X và loại liên quan

Có thể là gần như tương tự như trên - chỉ cần sử dụng một số chức năng mà trọng lượng sẽ là vô hạn nếu nó là không phải của mối quan hệ chính xác.

  • Tính con đường ngắn nhất giữa 2 người dùng trên mạng theo đồ thị được đưa ra một loại quan hệ

Tương tự như trên, về cơ bản, chỉ cần xác định sớm nếu bạn kết hợp hai người sử dụng. (Ngoài ra, bạn có thể "đáp ứng ở giữa", và chấm dứt sớm nếu bạn tìm thấy một người nào đó trên cả hai cây bao trùm con đường ngắn nhất)

  • Tính khoảng cách tối đa giữa 2 người dùng trên mạng theo đồ thị

Longest pathNP-complete problem.

  • Tính người dùng kết nối xa nhất trên mạng graph

Đây là đường kính của đồ thị, bạn có thể đọc về trên Math World.

Đối với danh sách kề kề với câu hỏi ma trận kề, điều đó tùy thuộc vào mức độ đông dân cư của biểu đồ của bạn. Ngoài ra, nếu bạn muốn lưu trữ kết quả, thì ma trận có thể là cách để đi.

+0

Nó giống như ~ 18000 đỉnh với ~ 520000 liên kết trên mẫu dữ liệu được cung cấp. –

+0

Trong trường hợp đó, O (E log V) phải đủ tốt, bạn có thể sắp xếp lưu trữ ma trận (có thể bạn có thể, nhưng nó hơi nhiều) ~ 18000^2 = ~ 324 triệu, và nó sẽ cho phép mọi thứ hội tụ nhanh hơn, nhưng 18000^3 là một cái gì đó như Floyd-Warshall đang đến gần quá nhiều. – Larry

1

Thuật toán đơn giản nhất để tính đường đi ngắn nhất giữa hai nút là Floyd-Warshall. Nó chỉ gấp ba lần cho các vòng lặp; đó là nó.

Nó tính ALL -pairs con đường ngắn nhất trong O(N^3), vì vậy nó có thể làm việc nhiều hơn cần thiết, và sẽ mất một thời gian nếu N là rất lớn.

+0

Tôi không muốn nó dễ dàng lol. Nó có lẽ sẽ mất rất nhiều thời gian và tôi không nghĩ rằng những người chỉ dẫn sẽ thích điều đó. –

+0

Vâng, tôi chỉ đọc về các đỉnh 18K ngay bây giờ; đó chắc chắn là ngoài câu hỏi. – polygenelubricants

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