AlgoVerse

درخت آماره‌ی ترتیبی (OS-Select و OS-Rank)

درخت جستجویی که هر گره اندازه‌ی زیردرختش را نگه می‌دارد؛ با آن، i-امین کوچک‌ترین کلید و رتبه‌ی هر کلید در O(h) پیدا می‌شود.

اگر هر گره‌ی درخت جستجو اندازه‌ی زیردرختش (size) را هم نگه دارد، می‌توانیم آماره‌های ترتیبی را بدون پیمایش کل درخت پیدا کنیم. این یک نمونه‌ی افزودن به ساختار داده (augmenting) است (CLRS فصل ۱۷).

ادامه‌ی توضیح ↓
ورودی:
A 1×12 · i=5 · k=38خروجی PDF

۱۲ کلید؛ پنجمین کوچک‌ترین ۱۹ است و رتبه‌ی ۳۸، ۱۰ است. عدد کوچک زیر هر گره اندازه‌ی زیردرخت آن است.

  1. class Node:
  2. def __init__(self, key):
  3. self.key = key
  4. self.left = None
  5. self.right = None
  6. self.size = 1 # the number of nodes in this subtree
  7. def os_tree(A, i, k):
  8. root = build(A[0])
  9. found = select(root, i)
  10. r = rank(root, k)
  11. return [found, r]
  12. def size(x):
  13. if x is None:
  14. return 0
  15. return x.size
  16. def select(x, i):
  17. # The i-th smallest key: the root of a subtree is its (size(left) + 1)-th smallest.
  18. while x is not None:
  19. r = size(x.left) + 1
  20. if i == r:
  21. return x.key
  22. if i < r:
  23. x = x.left
  24. else:
  25. i = i - r
  26. x = x.right
  27. return None
  28. def rank(root, k):
  29. # How many keys are ≤ k: add up the left subtrees (and nodes) we pass on the way right.
  30. r = 0
  31. x = root
  32. while x is not None:
  33. if k < x.key:
  34. x = x.left
  35. elif k > x.key:
  36. r = r + size(x.left) + 1
  37. x = x.right
  38. else:
  39. r = r + size(x.left) + 1
  40. return r
  41. return None
  42. def build(keys):
  43. # An ordinary search tree, with each node's size updated on the way down.
  44. root = None
  45. for key in keys:
  46. node = Node(key)
  47. if root is None:
  48. root = node
  49. continue
  50. p = root
  51. while True:
  52. p.size = p.size + 1
  53. if key < p.key:
  54. if p.left is None:
  55. p.left = node
  56. break
  57. p = p.left
  58. else:
  59. if p.right is None:
  60. p.right = node
  61. break
  62. p = p.right
  63. return root

ناوردا: x.size = size(x.left) + size(x.right) + 1 برای هر گره؛ در OS-SELECT، جواب همیشه i-امین کلید زیردرخت x است.

شروع اجرا

∅

i5
r—
found—

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

i5
k38

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

A list

[26, 17, 41, 14, 21, 30, 47, 10, 16, 19, 28, 38]

Call stack

  1. os_tree()خط 9
گام ۱ از ۳۱۷
خط سیاه = selected, ranked · خط نارنجی = گام کلیدیbuilt: 0/1 · at: 0/4 · go_left: 0/2 · go_right: 0/1 · found: 0/1 · selected: 0/1 · rank_right: 0/2 · rank_left: 0/1 · rank_found: 0/1 · ranked: 0/1
    توضیح

    ایده

    اگر هر گره‌ی درخت جستجو اندازه‌ی زیردرختش (size) را هم نگه دارد، می‌توانیم آماره‌های ترتیبی را بدون پیمایش کل درخت پیدا کنیم. این یک نمونه‌ی افزودن به ساختار داده (augmenting) است (CLRS فصل ۱۷).

    OS-SELECT(x, i)

    ریشه‌ی هر زیردرخت، size(left) + 1-امین کوچک‌ترین کلید آن است. اگر i همین است، جواب ریشه است؛ اگر کمتر است به چپ برو؛ وگرنه به راست برو و دنبال (i − r)-امین بگرد.

    OS-RANK(k)

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

    نگه داشتن اندازه‌ها

    در درج، اندازه‌ی گره‌های مسیر یکی زیاد می‌شود؛ در چرخش‌ها (درخت قرمز-سیاه) فقط اندازه‌ی دو گره عوض می‌شود. پس با درخت متوازن همه‌ی عمل‌ها O(log n) می‌مانند.

    ورودی

    A ترتیب درج کلیدها، i رتبه‌ای که می‌خواهیم و k کلیدی که رتبه‌اش را می‌خواهیم.