الخوارزميات وهياكل البيانات بلغة Kotlin: تطبيق عملي
Kotlin هي لغة حديثة متعددة النماذج تُستخدم بنشاط في تطوير تطبيقات Android، والخوادم الخلفية، وحتى تطبيقات سطح المكتب. ومع ذلك، لكتابة كود فعال وقابل للتوسع، لا يكفي معرفة بناء الجملة - بل يجب فهم كيفية عمل الخوارزميات وهياكل البيانات. في هذه المقالة، سنشرح المفاهيم الأساسية عمليًا مع أمثلة بلغة Kotlin. ستتعلم كيفية تنفيذ الهياكل والخوارزميات الأساسية، وكذلك كيفية استخدام الإمكانيات المدمجة في اللغة لتحسين الكود.
1. هياكل البيانات الأساسية: المصفوفات والقوائم
في Kotlin، يتم تمثيل المصفوفات بنوع Array<T>، والقوائم الديناميكية بنوع List<T> (غير قابل للتغيير) و MutableList<T> (قابل للتغيير). ومع ذلك، في المهام الواقعية، غالبًا ما يكون من الضروري تنفيذ قائمة مرتبطة خاصة بك لفهم مبادئ العمل.
قائمة مرتبطة أحادية الاتجاه بلغة Kotlin
تتكون القائمة المرتبطة من عقد، تحتوي كل منها على بيانات ومرجع للعقدة التالية. لنلقِ نظرة على التنفيذ الأساسي:
class Node<T>(var value: T, var next: Node<T>? = null)
class LinkedList<T> { private var head: Node<T>? = null
fun add(value: T) { val newNode = Node(value) if (head == null) { head = newNode } else { var current = head while (current?.next != null) { current = current.next } current?.next = newNode } }
fun printAll() { var current = head while (current != null) { print("${current.value} ") current = current.next } println() }}
fun main() { val list = LinkedList<Int>() list.add(1) list.add(2) list.add(3) list.printAll() // الإخراج: 1 2 3}يوضح هذا التنفيذ العمليات الأساسية: الإضافة في النهاية والاجتياز. في المشاريع الحقيقية، استخدم مجموعات Kotlin المدمجة، لكن فهم البنية الداخلية يساعد في تجنب الأخطاء عند العمل مع الذاكرة والأداء.
2. خوارزميات الفرز بلغة Kotlin
الفرز هو أحد أكثر العمليات شيوعًا. في Kotlin، توجد دالة مدمجة sorted()، ولكن للفهم العميق، من المفيد تنفيذ الخوارزميات الكلاسيكية.
الفرز السريع (QuickSort)
QuickSort هي واحدة من أكثر الخوارزميات فعالية بمتوسط تعقيد O(n log n). التنفيذ بلغة Kotlin باستخدام العودية:
fun quickSort(arr: IntArray, low: Int, high: Int) { if (low < high) { val pivotIndex = partition(arr, low, high) quickSort(arr, low, pivotIndex - 1) quickSort(arr, pivotIndex + 1, high) }}
fun partition(arr: IntArray, low: Int, high: Int): Int { val pivot = arr[high] var i = low - 1 for (j in low until high) { if (arr[j] <= pivot) { i++ arr[i] = arr[j].also { arr[j] = arr[i] } } } arr[i + 1] = arr[high].also { arr[high] = arr[i + 1] } return i + 1}
fun main() { val array = intArrayOf(10, 7, 8, 9, 1, 5) quickSort(array, 0, array.size - 1) println(array.joinToString()) // الإخراج: 1, 5, 7, 8, 9, 10}لاحظ استخدام also لتبادل القيم - هذه طريقة اصطلاحية في Kotlin. الخوارزمية مستقرة وتعمل في المكان (in-place)، مما يوفر الذاكرة.
3. البحث: الثنائي والخطي
البحث عن العناصر في هياكل البيانات هو ثاني أهم مهمة. دعنا ننظر في طريقتين.
البحث الخطي
خوارزمية بسيطة ولكنها بطيئة (O(n)). مناسبة للبيانات غير المرتبة:
fun linearSearch(arr: IntArray, target: Int): Int { for (i in arr.indices) { if (arr[i] == target) return i } retu