Tìm chiều cao của tất cả các nút trong rừng


8

Tôi có một khu rừng, tức là các nút có các cạnh được định hướng và không có chu kỳ (có hướng hoặc không được định hướng). Tôi xác định chiều cao của đỉnh là 0 nếu nó không có bất kỳ cạnh nào hoặc số cạnh tối đa để di chuyển ngược lại để đạt đến đỉnh có chiều cao 0. vnhập mô tả hình ảnh ở đây

Tôi cũng biết rằng mức độ trung bình của một nút là một hằng số nhỏ, giả sử là 2 hoặc hơn. Để tìm chiều cao của tất cả các đỉnh, tôi có thể nghĩ đến hai thuật toán:

Thuật toán đi bộ

  1. Đi qua và đánh dấu cho các đỉnh không có cạnh đến.h= =0
  2. Đối với mỗi đỉnh có , hãy theo các cạnh đi, cập nhật chiều cao của mỗi đỉnh gặp phải nếu chiều cao trước đó nhỏ hơn.h= =0

Thuật toán biên giới

  1. Đi qua và đánh dấu cho các đỉnh không có cạnh đến và đánh dấu chúng là biên giới.h= =0
  2. Đối với mọi đỉnh biên giới, hãy xem cha mẹ của nó có con ở hoặc dưới biên giới hay không, nếu có, hãy đánh dấu cha mẹ là cộng với chiều cao lớn nhất trong số các con của nó. Đánh dấu cha mẹ là ở biên giới.1
  3. Lặp lại 2 cho đến khi không có gì ngoài biên giới.

Những câu hỏi của tôi:

  1. Có một tên cho vấn đề này, và một giải pháp nhanh nhất được biết đến?
  2. Tôi có xu hướng nghĩ đơn giản là đi lên từ tất cả các đỉnh là giải pháp nhanh nhất. Tôi có đúng khôngh= =0

Câu trả lời:


7

Trước hết, nó phụ thuộc một chút vào cách bạn có thể truy cập dữ liệu của mình để nói thuật toán nào hoạt động tốt nhất.

Dù sao, tôi sẽ đề nghị xác định độ cao theo kiểu từ trên xuống thay vì từ dưới lên. Cá nhân tôi nghĩ rằng một cách tiếp cận từ trên xuống là khái niệm đẹp hơn và dễ phân tích hơn. Đối với bất kỳ đỉnh trong rừng, điều đó đúngv

Chiều cao(v)= ={(tối đabạn đứa bé của vChiều cao(bạn))+1nếu bạn không phải là một chiếc lá0nếu không thì.

Vì vậy, bạn có thể quét tất cả các gốc, và sau đó xác định độ cao bằng cách chia một cuộc chinh phục. Bạn sẽ chạm vào mọi đỉnh nhiều nhất hai lần (quét tìm gốc + di chuyển ngang). Theo cách tiếp cận mà bạn đã đề xuất, bạn có thể phải chạm vào một số đỉnh nhiều lần.

Btw, vì bạn có một khu rừng, bạn có ít cạnh hơn các đỉnh, vì vậy bạn biết rằng bạn có mức độ trung bình nhỏ hơn hai (và do đó bạn có thể kiểm tra rễ trong thời gian tuyến tính).


+1; giải pháp đệ quy thường dễ phân tích hơn. Nó cũng phụ thuộc vào việc bạn đã có con trỏ con hay chưa, và bạn muốn một giải pháp dựa trên vòng lặp hoặc dựa trên đệ quy.
Joe

Tôi thích phân tích! Ai đó có thể giúp những người mới chỉ ra cách chuyển đổi nó thành dạng lặp không?
highBandWidth

4

Tôi không biết vấn đề này có tên chính thức hay không. Tiêu đề của bạn tổng hợp nó đủ tốt. Đi lên từ các nút chiều cao 0 sẽ nhanh chóng, miễn là bạn cẩn thận để tránh làm việc trùng lặp. Giả sử bạn có một nút có nhiều con và một đường dẫn dài phía trên nút này đến gốc. Giả sử cũng có chiều cao của mỗi đứa trẻ là khác nhau. Mỗi đứa trẻ có thể cập nhật chiều cao của nút trong câu hỏi. Vậy là được rồi. Nhưng bạn cũng nên tránh cập nhật đường dẫn dài phía trên nút đó cho đến khi tất cả các con của nó báo cáo chiều cao của chúng.

Thuật toán kết quả sẽ chạy trong thời gian tuyến tính và mã giả sẽ trông giống như thế này:

initialize a queue Q
initialize all nodes to have a property: maxChildHeight = 0
initialize all nodes of in-degree 0 to have height = 0
Add all nodes of in-degree 0 to Q
while Q is non-empty:
  pop a node v from the front of Q
  subtract 1 from the indegree of the parent of v
  set parent.maxChildHeight = max(height(v), parent.maxChildHeight)
  if the indegree of the parent is 0:
      parent.height =  maxChildHeight + 1
      add the parent to Q

3

Một vấn đề tương tự có thể được quan tâm là "Tiền tố song song trên các cây được định hướng gốc". Thuật toán tìm số cạnh của gốc từ mỗi nút. Vì vậy, các gốc kết thúc với giá trị 0, trong khi ví dụ nút dưới cùng bên phải sẽ có giá trị là hai.

Lưu ý rằng thuật toán bên dưới giải quyết vấn đề tổng quát hơn cho các cạnh có trọng số, nhưng bạn chỉ có thể khởi tạo W (i) thành 1 cho tất cả i. Và mỗi nút kế của i được cho bởi P (i) = j.

for 1 ≤ i ≤ n do in parallel
    S(i) = P(i)
    while S(i) != S(S(i)) do
        W(i) = W(i) + W(S(i))
        S(i) = S(S(i))

Hình ảnh dưới đây minh họa "giảm một nửa" độ dài đường dẫn và làm cho thời gian chạy logarit trở nên dễ hiểu. Nó không hiển thị chiều cao nút được tính toán mặc dù.

nhập mô tả hình ảnh ở đây

(từ "Giới thiệu về thuật toán song song" của Joseph Jaja).

Sử dụng nhiều bộ xử lý, có thể giải quyết được trong thời gian O (lg n), nhưng sử dụng các hoạt động O (n lg n). Có một hack để đưa nó xuống công việc tuyến tính, nhưng nó hơi liên quan.


Cảm ơn! không S(i)đại diện cho cái gì
highBandWidth

Nút kế. Vì vậy, trong lần lặp, một trong những cây bên phải, S (9) = 10, S (10) = 11, S (11) = 12, S (12) = 13 và W (9) = 1, W (10) = 1 , W (11) = 1, W (12) = 1. Trong lần lặp hai, S (9) = 11, S (10) = 12, S (11) = 13, S (12) = 13 và W (9) = 2, W (10) = 2, W (11) = 2, W (12) = 1. Trong lần lặp ba, S (9) = 13, S (10) = 13, S (11) = 13, S (12) = 13 và W (9) = 2 + 2, W (10) = 2 + 1, W (11) = 2, W (12) = 1.
Mèo Unun

Bạn phải tưởng tượng tất cả S (i) và W (i) được cập nhật cùng lúc khi bạn cố gắng tìm ra các chi tiết. Điều này có thể mơ hồ, nhưng tôi muốn đăng nó vì đây là một vấn đề song song cổ điển và rất gần với những gì bạn mô tả.
Mèo Unun
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.