Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

شجرة AVL

آخر تحديث

شجرة AVL هي شجرة بحث ثنائية ذاتية التوازن. تعمل مثل شجرة BST عادية، لكن بعد كل إدراج تتحقق من عامل توازن كل سلف - فرق الارتفاع بين شجرتيه الفرعيتين اليسرى واليمنى - وإذا أصبحت أي عقدة غير متوازنة (فرق أكبر من 1)، فإنها تنفّذ دورات لاستعادة التوازن. اضغط على تشغيل بالأعلى لمشاهدة القيم وهي تُدرَج والشجرة وهي تدور لتعود إلى شكلها.

لأنها لا تسمح أبدًا للشجرة بأن تميل أكثر من قليل، تضمن شجرة AVL ارتفاعًا بمقدار O(log n)، لذا فإن البحث والإدراج والحذف دائمًا O(log n) - حتى للمدخلات المرتبة التي قد تدمّر شجرة BST عادية. الثمن هو الدورات الإضافية وحفظ الارتفاعات عند كل إدراج.

التعقيد الزمني والمكاني

العمليةالتعقيدملاحظات
البحثO(log n)الارتفاع دائمًا ~1.44 log n
الإدراجO(log n)بالإضافة إلى O(1) دورات
الحذفO(log n)بالإضافة إلى O(log n) دورات
المساحةO(n)حقل ارتفاع واحد لكل عقدة

حالات الدوران الأربع

الحالةعدم التوازنالإصلاح
يسار-يسارثقل على يسار الابن الأيسردوران واحد إلى اليمين
يمين-يمينثقل على يمين الابن الأيمندوران واحد إلى اليسار
يسار-يمينثقل على يمين الابن الأيسردوران إلى اليسار ثم إلى اليمين
يمين-يسارثقل على يسار الابن الأيمندوران إلى اليمين ثم إلى اليسار

مثال محلول

إدراج [10, 20, 30, 40, 50, 25] قيمة تلو الأخرى:

الخطوةالبنيةالإجراء
إدراج 1010تصبح العقدة الأولى الجذر؛ متوازنة
إدراج 2010(_, 20)تذهب إلى يمين 10؛ لا تزال متوازنة
إدراج 3020(10, 30)يمين-يمين عند 10، لذا دوران واحد إلى اليسار يرفع 20 إلى الجذر
إدراج 4020(10, 30(_, 40))تذهب إلى يمين 30؛ تبقى جميع عوامل التوازن ضمن ±1
إدراج 5020(10, 40(30, 50))يمين-يمين عند 30، لذا دوران إلى اليسار عند 30 يرفع 40
إدراج 2530(20(10, 25), 40(_, 50))يمين-يسار عند 20: أدر شجرة 40 الفرعية إلى اليمين، ثم أدر 20 إلى اليسار

متى تستخدم شجرة AVL

استخدمها عندماتجنّبها عندما
تفوق عمليات البحث الإدراجات بكثير وتريد أضيق ارتفاع ممكنتهيمن عمليات الإدراج والحذف - إذ تكلّف الدورات وإعادة التوازن الإضافية أكثر من الشجرة الحمراء-السوداء
تحتاج إلى ضمان أسوأ حالة O(log n)، حتى للمدخلات العدائية أو المرتبةيكفي جدول تجزئة بسيط - لا تحتاج إلى اجتياز مرتّب أو استعلامات نطاق
تحتاج إلى عمليات مرتّبة: الاجتياز بالترتيب، السابق/اللاحق، استعلامات النطاقمجموعة البيانات صغيرة جدًا - شجرة BST عادية أو مصفوفة مرتّبة أبسط وسريعة بما يكفي
قد تصل البيانات مرتّبة بالفعل، مما يحوّل شجرة BST غير المتوازنة إلى قائمة مترابطةلا يمكنك تحمّل الذاكرة الإضافية لحقل الارتفاع لكل عقدة في حيّز ضيق للغاية

كود AVL Tree

تنفيذ نظيف وقابل للتشغيل لخوارزمية AVL Tree بلغات Python, JavaScript, Java, C++, C. اختر لغة، وانسخ الكود، أو افتحه محمّلًا مسبقًا في ساحة تجربة Coddy.

كود AVL Tree بلغة Python

Python
1class Node:2    def __init__(self, key):3        self.key = key4        self.left = None5        self.right = None6        self.height = 17
8
9def height(node):10    return node.height if node else 011
12
13def update(node):14    node.height = 1 + max(height(node.left), height(node.right))15
16
17def rotate_right(y):18    x = y.left19    y.left = x.right20    x.right = y21    update(y)22    update(x)23    return x24
25
26def rotate_left(x):27    y = x.right28    x.right = y.left29    y.left = x30    update(x)31    update(y)32    return y33
34
35def insert(node, key):36    if node is None:37        return Node(key)38    if key < node.key:39        node.left = insert(node.left, key)40    else:41        node.right = insert(node.right, key)42    update(node)43    balance = height(node.left) - height(node.right)44    # Four imbalance cases: LL, RR, LR, RL45    if balance > 1 and key < node.left.key:46        return rotate_right(node)47    if balance < -1 and key > node.right.key:48        return rotate_left(node)49    if balance > 1:50        node.left = rotate_left(node.left)51        return rotate_right(node)52    if balance < -1:53        node.right = rotate_right(node.right)54        return rotate_left(node)55    return node56
57
58def inorder(node):59    if node is None:60        return []61    return inorder(node.left) + [node.key] + inorder(node.right)62
63
64root = None65for key in [10, 20, 30, 40, 50, 25]:66    root = insert(root, key)67
68print("Inorder:", inorder(root))69print("Root:", root.key, "| tree height:", root.height)
شغّل هذا الكود في ساحة تجربة Python

الأسئلة الشائعة حول شجرة AVL

ما هو عامل التوازن في شجرة AVL؟
عامل توازن العقدة هو ارتفاع شجرتها الفرعية اليسرى ناقص ارتفاع شجرتها الفرعية اليمنى. تحافظ شجرة AVL على عامل توازن كل عقدة عند -1 أو 0 أو +1؛ فإذا دفعه الإدراج خارج هذا النطاق، تعيد الدورة التوازن.
ما الفرق بين شجرة AVL والشجرة الحمراء-السوداء؟
كلتاهما شجرتا بحث ثنائية ذاتية التوازن بعمليات O(log n). أشجار AVL أكثر توازنًا بصرامة، لذا يكون البحث أسرع قليلًا، لكنها قد تنفّذ دورات أكثر عند الإدراج/الحذف. الأشجار الحمراء-السوداء أكثر توازنًا بمرونة، وتفضّل دورات أقل - ولهذا تستخدمها كثير من المكتبات القياسية للخرائط والمجموعات.
لماذا نستخدم شجرة AVL بدلًا من شجرة بحث ثنائية عادية؟
يمكن أن تتدهور شجرة BST العادية إلى عمليات O(n) إذا وصلت القيم بترتيب مرتّب، مكوِّنة سلسلة منحرفة. تدور شجرة AVL لتبقى متوازنة، مما يضمن ارتفاعًا وعمليات O(log n) بغض النظر عن ترتيب الإدراج.
هل شجرة AVL أفضل من الشجرة الحمراء-السوداء لفهرس قاعدة بيانات؟
يعتمد ذلك على عبء العمل. أشجار AVL أكثر توازنًا بصرامة، لذا تتفوّق عندما تهيمن عمليات القراءة وتريد أقصر مسارات بحث ممكنة. لكن معظم قواعد البيانات ومكتبات اللغات تختار الأشجار الحمراء-السوداء (أو أشجار B) لأنها تعيد التوازن بدورات أقل في أعباء العمل كثيفة الكتابة، وهو ما يهم أكثر عندما يكون الإدراج والحذف متكررين.
كم عدد الدورات التي يحتاجها إدراج AVL واحد؟
يلزم على الأكثر دوران واحد - إما دوران مفرد أو مزدوج (بخطوتين) - لإعادة توازن الشجرة بعد إدراج قيمة واحدة. وذلك لأن الإدراج يزيد ارتفاع الشجرة الفرعية بمقدار واحد على الأكثر، لذا يكفي إصلاح واحد عند أدنى سلف غير متوازن. أما الحذف فمختلف: قد يتطلب حتى O(log n) دورة مع انتشار إعادة التوازن نحو الجذر.
هل يجب تحديث ارتفاعات العقد بعد كل دوران؟
نعم - من الأخطاء الشائعة تدوير المؤشرات بشكل صحيح مع نسيان إعادة حساب ارتفاع العقدتين المعنيتين. بعد كل دوران يجب تحديث ارتفاع العقدة المخفَّضة أولًا، ثم العقدة المرقّاة، لأن ارتفاع العقدة المرقّاة يعتمد على أبنائها الجدد. تخطي ذلك يترك عوامل توازن قديمة تُفسد قرارات إعادة التوازن المستقبلية.
Coddy programming languages illustration

أتقن الخوارزميات مع Coddy

ابدأ الآن