شکافتن و پیوند درخت جستجوی دودویی
درخت جستجو را با کلید k به دو درخت (کوچکتر و بزرگتر از k) میشکافد و بعد دو درخت را دوباره پیوند میدهد؛ هر دو O(h). شکافتن و سپس پیوند همان حذف k است.
SPLIT(t, k) درخت جستجو را به سه بخش تقسیم میکند: درخت small با کلیدهای کمتر از k، گرهی k (اگر باشد)، و درخت big با کلیدهای بیشتر از k. فقط در مسیر جستوجوی k پایین میرویم:
- زمان:
O(h) - حافظه:
O(h) for the recursion - هوروویتز–ساهنی، فصل ۵
درخت ۱۰ کلیدی با k = ۴۰؛ مسیر جستوجوی ۴۰ درخت را به دو نیم میکند، و بعد بزرگترین کلید small، یعنی ۳۵، ریشهی درخت پیوندخورده میشود.
class Node:def __init__(self, key):self.key = keyself.left = Noneself.right = Nonedef split_join(A, k):root = build(A[0])small, mid, big = split(root, k)found = mid is not Noneroot = Noneroot = join(small, big)small = Nonebig = Nonekeys = []inorder(root, keys)return keysdef split(t, k):# Returns the keys < k, the node with key k (or None), and the keys > k, as three search trees.if t is None:return None, None, Noneif k < t.key:s, m, b = split(t.left, k)t.left = breturn s, m, tif k > t.key:s, m, b = split(t.right, k)t.right = sreturn t, m, bs, b = t.left, t.rightt.left = Nonet.right = Nonereturn s, t, bdef join(small, big):# Every key in small is below every key in big. The largest key of small becomes the new root.if small is None:return bigparent = Nonem = smallwhile m.right is not None:parent = mm = m.rightif parent is None:small = m.leftelse:parent.right = m.leftm.left = smallm.right = bigreturn mdef inorder(t, keys):if t is not None:inorder(t.left, keys)keys.append(t.key)inorder(t.right, keys)def build(keys):root = Nonefor key in keys:node = Node(key)if root is None:root = nodecontinuep = rootwhile True:if key < p.key:if p.left is None:p.left = nodebreakp = p.leftelse:if p.right is None:p.right = nodebreakp = p.rightreturn root
شروع اجرا
∅
∅
∅
درخت فراخوانیهای بازگشتی
نارنجی پر = فراخوانی در حال اجرا · حاشیهی نارنجی = هنوز روی پشته · خاکستری = تمام شده
متغیرهای محلی
نارنجی = در همین گام عوض شد
A list
Call stack
- split_join()خط 8
توضیح
شکافتن
SPLIT(t, k) درخت جستجو را به سه بخش تقسیم میکند: درخت small با کلیدهای کمتر از k، گرهی k (اگر باشد)، و درخت big با کلیدهای بیشتر از k. فقط در مسیر جستوجوی k پایین میرویم:
- اگر
k < t.key: گرهیtبا زیردرخت راستش بهbigمیرود و شکافتن در زیردرخت چپ ادامه دارد. - اگر
k > t.key: برعکس،tبا زیردرخت چپش بهsmallمیرود.
پیوند
JOIN(small, big) دو درخت را که همهی کلیدهای اولی از دومی کوچکترند یکی میکند: بزرگترین گرهی small را جدا میکنیم و ریشهی تازه میکنیم، با small در چپ و big در راست. اگر یک کلید میانی m هم داشته باشیم (پیوند سهطرفه) کار سادهتر است: m ریشه میشود.
هزینه
هر دو فقط یک مسیر از ریشه تا برگ را میروند: O(h). این دو عمل پایهی درختهای treap و splay و پیادهسازی مجموعهها با اجتماع و اشتراکاند.
ورودی
A ترتیب درج کلیدها و k کلید شکافتن است.