AlgoVerse

یکریختی درخت‌ها

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

دو درخت ریشه‌دار یکریخت‌اند اگر بشود با جابه‌جا کردن فرزندان گره‌ها (و نادیده گرفتن برچسب‌ها) یکی را به دیگری تبدیل کرد.

ادامه‌ی توضیح ↓
ورودی:
A 1×6 · B 1×6خروجی PDF

b آینه‌ی a است: هر جا a فرزند چپ دارد، b فرزند راست دارد. شکل‌ها فرق دارند ولی درخت‌ها یکریخت‌اند.

  1. class Node:
  2. def __init__(self, key):
  3. self.key = key
  4. self.left = None
  5. self.right = None
  6. def isomorphic(A, B):
  7. a = build(A[0])
  8. b = build(B[0])
  9. name_a = name(a)
  10. name_b = name(b)
  11. same = name_a == name_b
  12. return same
  13. def name(node):
  14. # The canonical name of a subtree: its children's names in sorted order, wrapped in brackets.
  15. if node is None:
  16. return ""
  17. first = name(node.left)
  18. second = name(node.right)
  19. if first > second:
  20. first, second = second, first
  21. s = "(" + first + second + ")"
  22. return s
  23. def build(keys):
  24. # A binary search tree from the keys in this insertion order; only its shape matters here.
  25. root = None
  26. for k in keys:
  27. node = Node(k)
  28. if root is None:
  29. root = node
  30. continue
  31. p = root
  32. while True:
  33. if k < p.key:
  34. if p.left is None:
  35. p.left = node
  36. break
  37. p = p.left
  38. else:
  39. if p.right is None:
  40. p.right = node
  41. break
  42. p = p.right
  43. return root

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

شروع اجرا

a

∅

b

∅

name_a—
name_b—
same—

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

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

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

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

A list

[5, 3, 8, 2, 4, 1]

B list

[5, 7, 2, 8, 6, 9]

Call stack

  1. isomorphic()خط 8
گام ۱ از ۳۲۴
خط سیاه = named_a, named_b · خط نارنجی = گام کلیدیbuilt: 0/1 · named: 0/12 · reorder: 0/3 · named_a: 0/1 · named_b: 0/1 · compared: 0/1
    توضیح

    مسئله

    دو درخت ریشه‌دار یکریخت‌اند اگر بشود با جابه‌جا کردن فرزندان گره‌ها (و نادیده گرفتن برچسب‌ها) یکی را به دیگری تبدیل کرد.

    ایده: نام متعارف (Aho–Hopcroft–Ullman)

    به هر زیردرخت از پایین به بالا یک نام می‌دهیم:

    • درخت تهی نام تهی دارد،
    • نام یک گره = ( + نام فرزندانش به ترتیب مرتب + ).

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

    هزینه

    با رشته‌ها، ساختن نام‌ها می‌تواند O(n²) باشد؛ نسخه‌ی AHU به جای رشته به هر نام یک عدد صحیح می‌دهد و به O(n) می‌رسد.

    ورودی

    A و B ترتیب درج کلیدها در دو درخت جستجوی دودویی‌اند؛ فقط شکل این درخت‌ها مقایسه می‌شود.