مقدمة في الخوارزميات وهياكل البيانات بلغة جافا
دراسة الخوارزميات وهياكل البيانات هي الأساس الذي يُبنى عليه مسار أي مبرمج. بالنسبة لمطوري جافا، فإن فهم كيفية عمل هياكل البيانات والخوارزميات الأساسية أمر بالغ الأهمية: فهو يؤثر بشكل مباشر على الأداء، وقابلية قراءة الكود، والقدرة على حل المشكلات المعقدة. في هذه المقالة، سنشرح المفاهيم الرئيسية بلغة بسيطة، مع أمثلة كود توضيحية بلغة جافا.
بغض النظر عما إذا كنت تستعد لمقابلة عمل أو ترغب ببساطة في كتابة كود أكثر كفاءة، فإن هذه المقالة ستكون نقطة انطلاقك.
ما هي هياكل البيانات؟
هيكل البيانات هو طريقة لتنظيم وتخزين البيانات في ذاكرة الحاسوب. يمكن للاختيار الصحيح لهيكل البيانات أن يسرّع البرنامج بعشرات المرات. في جافا، يوجد نوعان من هياكل البيانات: المضمنة (المصفوفات) والمجموعات (الفئات من إطار عمل مجموعات جافا).
المصفوفات (Array)
المصفوفة هي أبسط وأسرع هيكل بيانات. تقوم بتخزين عناصر من نفس النوع في منطقة ذاكرة متصلة. الوصول إلى عنصر عن طريق الفهرس يحدث فورياً (O(1))، لكن إضافة أو حذف العناصر يتطلب إعادة إنشاء المصفوفة.
public class ArrayExample { public static void main(String[] args) { // الإعلان عن مصفوفة وتهيئتها int[] numbers = new int[5]; numbers[0] = 10; numbers[1] = 20; numbers[2] = 30; // طريقة بديلة String[] fruits = {"تفاح", "موز", "برتقال"}; // اجتياز المصفوفة for (int i = 0; i < fruits.length; i++) { System.out.println(fruits[i]); } }}ArrayList - مصفوفة ديناميكية
يحل ArrayList المشكلة الرئيسية للمصفوفة العادية - الحجم الثابت. فهو يتوسع تلقائياً عند إضافة عناصر جديدة. هذا أحد أشهر هياكل البيانات في جافا.
import java.util.ArrayList;
public class ArrayListExample { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); // إضافة عناصر list.add("Java"); list.add("Python"); list.add("JavaScript"); // الحصول على عنصر حسب الفهرس System.out.println("العنصر الأول: " + list.get(0)); // حذف عنصر list.remove("Python"); // حجم القائمة System.out.println("حجم القائمة: " + list.size()); }}الخوارزميات الأساسية للمبتدئين
الخوارزمية هي سلسلة من الخطوات لحل مشكلة. سنستعرض ثلاث خوارزميات أساسية يجب أن يعرفها كل مطور جافا.
البحث الخطي
أبسط خوارزمية بحث: نتحقق بشكل متسلسل من كل عنصر في المصفوفة حتى نجد العنصر المطلوب.
public class LinearSearch { public static int findElement(int[] arr, int target) { for (int i = 0; i < arr.length; i++) { if (arr[i] == target) { return i; // إرجاع فهرس العنصر الذي تم العثور عليه } } return -1; // لم يتم العثور على العنصر } public static void main(String[] args) { int[] data = {5, 3, 8, 1, 9, 2}; int index = findElement(data, 8); System.out.println("فهرس العنصر 8: " + index); // سيطبع: 2 }}البحث الثنائي
يعمل البحث الثنائي بشكل أسرع بكثير من البحث الخطي، لكنه يتطلب أن تكون المصفوفة مرتبة. تقوم الخوارزمية بتقسيم المصفوفة إلى نصفين في كل خطوة، متجاهلة نصف العناصر.
import java.util.Arrays;
public class BinarySearch { public static int binarySearch(int[] arr, int target) { int left = 0; int right = arr.length - 1; while (left <= right) { int mid = l