AlgoVerse

مرتب‌سازی توپولوژیک

گره‌های گراف جهت‌دار بی‌دور را طوری می‌چیند که هر یال از گره‌ی قبلی به بعدی برود؛ مثل ترتیب گذراندن درس‌ها با پیش‌نیاز.

در گراف جهت‌دار بی‌دور (DAG)، ترتیب توپولوژیک چیدن گره‌ها در یک صف است، طوری که هر یال u → v از چپ به راست برود. مثال کلاسیک: درس‌ها و پیش‌نیازهایشان.

ادامه‌ی توضیح ↓
ورودی:
V=7 · E=8 · src=Aخروجی PDF

هفت درس؛ یال X → Y یعنی X پیش‌نیاز Y است.

  1. from collections import deque
  2. def topological_sort(graph, src):
  3. indegree = {v: 0 for v in graph}
  4. for u in graph:
  5. for v, _ in graph[u]:
  6. indegree[v] = indegree[v] + 1
  7. queue = deque(v for v in graph if indegree[v] == 0)
  8. order = []
  9. while queue:
  10. u = queue.popleft()
  11. order.append(u)
  12. for v, _ in graph[u]:
  13. indegree[v] = indegree[v] - 1
  14. if indegree[v] == 0:
  15. queue.append(v)
  16. if len(order) < len(graph):
  17. return None
  18. return order

ناوردا: indegree[v] تعداد یال‌های ورودی v از گره‌هایی است که هنوز در order نیامده‌اند.

شروع اجرا

ABCDEFG
  • گره‌ی جاری (u)
  • درخت کوتاه‌ترین مسیر تا اینجا
  • یالِ در حال بررسی

صف queue

خالی

متغیرهای محلی

src'A'

نارنجی = در همین گام عوض شد

graph dict
  • 'A': [('C', 1)]
  • 'B': [('C', 1), ('D', 1)]
  • 'C': [('E', 1)]
  • 'D': [('E', 1), ('F', 1)]
  • 'E': [('G', 1)]
  • 'F': [('G', 1)]
  • 'G': []

Call stack

  1. topological_sort()خط 4
گام ۱ از ۹۵
خط سیاه = take · خط نارنجی = گام کلیدیcount_in: 0/8 · ready: 0/1 · take: 0/7 · remove_edge: 0/8 · check: 0/8 · ready_now: 0/5

    رشد تعداد عملیات با اندازه‌ی ورودی

    میانگین ۵ گراف تصادفی برای هر n (با seed ثابت). نشانگر توخالی = ورودی فعلی.

    • remove_edge
    • take
    • ورودی فعلی (n=7)
    0204060481216202428n = تعداد گره‌هاremove_edgetake
    نمایش به شکل جدول
    nremove_edgetake
    45.24
    813.88
    1220.812
    162816
    2035.420
    2437.224
    2847.228
    توضیح

    ایده

    در گراف جهت‌دار بی‌دور (DAG)، ترتیب توپولوژیک چیدن گره‌ها در یک صف است، طوری که هر یال u → v از چپ به راست برود. مثال کلاسیک: درس‌ها و پیش‌نیازهایشان.

    الگوریتم کان

    1. برای هر گره تعداد یال‌های ورودی‌اش (indegree) را بشمار.
    2. گره‌هایی که یال ورودی ندارند آماده‌اند؛ آن‌ها را در صف بگذار.
    3. یک گره‌ی آماده بردار، به ترتیب اضافه کن و یال‌های خروجی‌اش را «حذف» کن (indegree همسایه‌ها یکی کم می‌شود). هر همسایه‌ای که indegreeش صفر شد، آماده است.

    اگر در پایان گره‌ای جا ماند، آن گره روی یک دور است و ترتیب توپولوژیک وجود ندارد.

    هزینه

    هر گره یک بار وارد صف می‌شود و هر یال یک بار حذف می‌شود: O(V + E).

    در trace به چه چیزی نگاه کنی

    • عدد کنار هر گره indegree آن است؛ وقتی صفر شد، گره وارد صف می‌شود.
    • در ورودی «دور» ببین سه گره‌ی دور هیچ‌وقت به صفر نمی‌رسند.