الخوارزميات وهياكل البيانات بلغة Java: دليل عملي
\n\nإتقان الخوارزميات وهياكل البيانات هو مرحلة أساسية في تكوين مطور Java. هذا ليس مجرد نظرية: فهم كيفية عمل القوائم، جداول التجزئة، وخوارزميات الفرز يؤثر بشكل مباشر على أداء وقابلية التوسع في الكود الخاص بك. في هذا المقال، سنستعرض هياكل البيانات والخوارزميات الأساسية بلغة Java مع أمثلة عملية ستساعدك على كتابة برامج أكثر كفاءة.
\n\n1. المصفوفات الديناميكية: ArrayList
\n\nArrayList هو تطبيق للمصفوفة الديناميكية في Java. على عكس المصفوفة العادية، يزداد حجمه تلقائيًا عند إضافة عناصر جديدة. هذا أحد هياكل البيانات الأكثر استخدامًا.
العمليات الأساسية
\n- \n
- إضافة عنصر:
add(element)— O(1) في المتوسط، O(n) عند توسيع المصفوفة. \n - الحصول على عنصر حسب الفهرس:
get(index)— O(1). \n - حذف عنصر:
remove(index)— O(n)، لأنه يتطلب إزاحة العناصر. \n
import java.util.ArrayList;\n\npublic class ArrayListExample {\n public static void main(String[] args) {\n ArrayList<Integer> numbers = new ArrayList<>();\n \n numbers.add(10);\n numbers.add(20);\n numbers.add(30);\n \n System.out.println("العنصر عند الفهرس 1: " + numbers.get(1)); // 20\n \n numbers.remove(0); // حذف العنصر الأول\n System.out.println("الحجم بعد الحذف: " + numbers.size()); // 2\n }\n}\n\n\nمتى تستخدم: عندما تحتاج إلى وصول سريع حسب الفهرس وتضيف عناصر بشكل متكرر في نهاية القائمة.
\n\n2. جداول التجزئة: HashMap
\n\nHashMap هو هيكل بيانات يخزن أزواج "مفتاح-قيمة". يستخدم دالة تجزئة للبحث السريع. في Java، HashMap هو أحد أكثر المجموعات أداءً لعمليات البحث والإدراج والحذف.
كيف يعمل؟
\nيتم تحويل كل مفتاح إلى رمز تجزئة (hash code) يحدد "السلة" (bucket) التي سيتم تخزين القيمة فيها. في حالة التصادمات (عندما تعطي مفاتيح مختلفة نفس التجزئة)، يتم استخدام قائمة مرتبطة أو شجرة حمراء-سوداء (منذ Java 8).
\n\nمثال على الاستخدام
\n\nimport java.util.HashMap;\n\npublic class HashMapExample {\n public static void main(String[] args) {\n HashMap<String, Integer> studentGrades = new HashMap<>();\n \n studentGrades.put("Alice", 90);\n studentGrades.put("Bob", 85);\n studentGrades.put("Charlie", 92);\n \n // البحث عن درجة\n int aliceGrade = studentGrades.get("Alice");\n System.out.println("درجة Alice: " + aliceGrade); // 90\n \n // التحقق من وجود مفتاح\n if (studentGrades.containsKey("David")) {\n System.out.println("David موجود في القائمة");\n } else {\n System.out.println("David غير موجود");\n }\n \n // تكرار على جميع الإدخالات\n for (String name : studentGrades.keySet()) {\n System.out.println(name + ": " + studentGrades.get(name));\n }\n }\n}\n\n\nتعقيد العمليات: في المتوسط O(1) للإدراج والبحث والحذف. في أسوأ الحالات (عند وجود عدد كبير من التصادمات) — O(n).
\n\n3. خوارزميات الفرز بلغة Java
\n\nالفرز هو إحدى العمليات الأساسية. توفر Java طرقًا مدمجة، لكن فهم آلية عملها الداخلية أمر بالغ الأهمية لكتابة كود فعال.
\n\nالفرز السريع (QuickSort)
\n\nهذه واحدة من أسرع خوارزميات الفرز. تعمل على مبدأ "فرق تسد": تختار عنصرًا محوريًا وتقسم المصفوفة إلى جزئين — أصغر وأكبر من العنصر المحوري.
\n\npublic class QuickSort {\n public static v