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

جدول التجزئة

آخر تحديث

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

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

تعقيد الوقت

العمليةالمتوسطأسوأ حالة
الإدراجO(1)O(n) (كل المفاتيح تتصادم)
البحثO(1)O(n)
الحذفO(1)O(n)
المساحةO(n)O(n)

المفاهيم الأساسية

المصطلحالمعنى
دالة التجزئةتربط مفتاحًا بفهرس دلو
التصادممفتاحان يقعان في الدلو نفسه
التسلسل المنفصلكل دلو يحتفظ بقائمة من الإدخالات المتصادمة
العنونة المفتوحةبديل: استكشاف الخانة الحرة التالية
عامل الحملالإدخالات / الدلاء - يحدد إعادة التحجيم

مثال محلول

إدراج المفاتيح 20 و34 و9 و13 في جدول من 7 دلاء، باستخدام hash(k) = k % 7:

الخطوةالبنيةالإجراء
إدراج 20الدلو 6: [20]20 % 7 = 6، الدلو 6 فارغ، تخزين 20
إدراج 34الدلو 6: [20, 34]34 % 7 = 6، تصادم مع 20، إضافة 34 إلى السلسلة
إدراج 9الدلو 2: [9]9 % 7 = 2، الدلو 2 فارغ، تخزين 9
إدراج 13الدلو 6: [20, 34, 13]13 % 7 = 6، تصادم، إضافة 13 إلى سلسلة الدلو 6
البحث عن 34الدلو 6: [20, 34, 13]34 % 7 = 6، مسح السلسلة: 20 لا، 34 مطابق - وُجد

متى تستخدم جدول التجزئة

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

كود Hash Table

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

كود Hash Table بلغة Python

Python
1class HashTable:2    def __init__(self, size=8):3        self.size = size4        self.buckets = [[] for _ in range(size)]5
6    def _index(self, key):7        # Hash the key to a bucket; different keys can collide8        return sum(ord(ch) for ch in key) % self.size9
10    def set(self, key, value):11        bucket = self.buckets[self._index(key)]12        for i, (k, _) in enumerate(bucket):13            if k == key:14                bucket[i] = (key, value)  # update existing key15                return16        bucket.append((key, value))  # chain on collision17
18    def get(self, key):19        for k, v in self.buckets[self._index(key)]:20            if k == key:21                return v22        raise KeyError(key)23
24    def delete(self, key):25        bucket = self.buckets[self._index(key)]26        for i, (k, _) in enumerate(bucket):27            if k == key:28                del bucket[i]29                return30        raise KeyError(key)31
32
33table = HashTable()34table.set("apple", 3)35table.set("banana", 7)36table.set("cherry", 5)37
38print("apple  ->", table.get("apple"))39print("banana ->", table.get("banana"))40table.set("apple", 10)41print("apple  ->", table.get("apple"))42table.delete("banana")43print("bucket sizes:", [len(b) for b in table.buckets])
شغّل هذا الكود في ساحة تجربة Python

الأسئلة الشائعة حول جدول التجزئة

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

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

ابدأ الآن