AlgoVerse

پیمایش‌های درخت

پیمایش پیش‌ترتیب، میان‌ترتیب و پس‌ترتیب یک درخت دودویی با بازگشت؛ میان‌ترتیبِ درخت جستجو کلیدها را مرتب می‌دهد.

پیمایش درخت یعنی دیدن همه‌ی گره‌ها، هر کدام دقیقاً یک بار. در درخت دودویی، هر گره یک زیردرخت چپ و یک زیردرخت راست دارد، پس طبیعی‌ترین روش بازگشت است: برای پیمایش درخت، ریشه را ببین و دو زیردرخت را (با همین روش) پیمایش کن. سه پیمایش کلاسیک فقط در جای دیدن ریشه فرق دارند:

ادامه‌ی توضیح ↓
ورودی:
n=7خروجی PDF

درخت جستجوی هفت‌گره‌ای ناکامل؛ سه پیمایش سه ترتیب متفاوت می‌دهند و میان‌ترتیب مرتب است.

  1. class Node:
  2. def __init__(self, key):
  3. self.key = key
  4. self.left = None
  5. self.right = None
  6. def traversals(root):
  7. pre = []
  8. preorder(root, pre)
  9. ino = []
  10. inorder(root, ino)
  11. post = []
  12. postorder(root, post)
  13. return pre, ino, post
  14. def preorder(node, out):
  15. if node is None:
  16. return
  17. out.append(node.key)
  18. preorder(node.left, out)
  19. preorder(node.right, out)
  20. def inorder(node, out):
  21. if node is None:
  22. return
  23. inorder(node.left, out)
  24. out.append(node.key)
  25. inorder(node.right, out)
  26. def postorder(node, out):
  27. if node is None:
  28. return
  29. postorder(node.left, out)
  30. postorder(node.right, out)
  31. out.append(node.key)

ناوردا: هر فراخوانی، کل زیردرختِ ریشه‌شده در node را پیمایش می‌کند و فقط بعد از آن برمی‌گردد.

شروع اجرا

36715171820

درخت فراخوانی‌های بازگشتی

نارنجی پر = فراخوانی در حال اجرا · حاشیه‌ی نارنجی = هنوز روی پشته · خاکستری = تمام شده

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

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

root object

  • key = 15
  • left = Node(key=6, left=Node(key=3, left=None, right=None), right=Node(key=7, left=None, right=None))
  • right = Node(key=18, left=Node(key=17, left=None, right=None), right=Node(key=20, left=None, right=None))

Call stack

  1. traversals()خط 8
گام ۱ از ۱۸۵
خط سیاه = done_pre, done_in, done_post · خط نارنجی = گام کلیدیvisit: 0/21 · done_pre: 0/1 · done_in: 0/1 · done_post: 0/1

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

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

    • visit
    • ورودی فعلی (n=7)
    02040603579111315n = تعداد کلیدهاvisit
    نمایش به شکل جدول
    nvisit
    39
    515
    721
    927
    1133
    1339
    1545
    توضیح

    ایده

    پیمایش درخت یعنی دیدن همه‌ی گره‌ها، هر کدام دقیقاً یک بار. در درخت دودویی، هر گره یک زیردرخت چپ و یک زیردرخت راست دارد، پس طبیعی‌ترین روش بازگشت است: برای پیمایش درخت، ریشه را ببین و دو زیردرخت را (با همین روش) پیمایش کن. سه پیمایش کلاسیک فقط در جای دیدن ریشه فرق دارند:

    | پیمایش | ترتیب | | --- | --- | | پیش‌ترتیب (preorder) | گره، چپ، راست | | میان‌ترتیب (inorder) | چپ، گره، راست | | پس‌ترتیب (postorder) | چپ، راست، گره |

    نکته‌ی مهم: میان‌ترتیب در درخت جستجو

    در درخت جستجوی دودویی، همه‌ی کلیدهای زیردرخت چپ کوچک‌تر و همه‌ی کلیدهای زیردرخت راست بزرگ‌ترند. پس پیمایش میان‌ترتیب کلیدها را به ترتیب صعودی می‌دهد.

    کاربردها

    • پیش‌ترتیب: کپی کردن درخت، نوشتن عبارت به شکل لهستانی.
    • پس‌ترتیب: پاک کردن درخت، محاسبه‌ی مقدار درخت عبارت، حساب کردن اندازه یا ارتفاع.

    هزینه

    هر گره یک بار دیده می‌شود: O(n). عمق بازگشت برابر ارتفاع درخت است: log n برای درخت متوازن و n برای زنجیر.

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

    • گره‌ی نارنجی همان node در فراخوانی جاری است و گره‌های سیاه قبلاً به خروجی اضافه شده‌اند.
    • لیست out زیر درخت ترتیب دیدن را نشان می‌دهد.
    • در «درخت فراخوانی‌های بازگشتی»، فراخوانی‌های ∅ همان فرزندهای ناموجودند که بلافاصله برمی‌گردند.
    • سطح جزئیات «هر دور حلقه» فقط پایان هر سه پیمایش را نشان می‌دهد.