Algorithms and Data Structures in Kotlin: A Practical Guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Algorithms and Data Structures in Kotlin: In Practice



Kotlin is a modern multi-paradigm language actively used for Android development, backend, and even desktop applications. However, to write efficient and scalable code, knowing the syntax is not enough — you need to understand how algorithms and data structures work. In this article, we will break down key concepts in practice with examples in Kotlin. You will learn how to implement basic structures and algorithms, as well as how to use the language's built-in capabilities to optimize code.



1. Basic Data Structures: Arrays and Lists



In Kotlin, arrays are represented by the Array<T> type, and dynamic lists by List<T> (immutable) and MutableList<T> (mutable). However, in real-world tasks, it is often necessary to implement your own linked list to understand the principles of operation.



Singly Linked List in Kotlin



A linked list consists of nodes, each containing data and a reference to the next node. Let's look at a basic implementation:



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() // Output: 1 2 3}


This implementation demonstrates basic operations: adding to the end and traversal. In real projects, use Kotlin's built-in collections, but understanding the internal workings helps avoid errors when dealing with memory and performance.



2. Sorting Algorithms in Kotlin



Sorting is one of the most common operations. Kotlin has a built-in sorted() function, but for a deep understanding, it is useful to implement classic algorithms.



QuickSort



QuickSort is one of the most efficient algorithms with an average complexity of O(n log n). Implementation in Kotlin using recursion:



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()) // Output: 1, 5, 7, 8, 9, 10}


Note the use of also for swapping values — this is an idiomatic way in Kotlin. The algorithm is stable and works in-place, saving memory.



3. Searching: Binary and Linear



Searching for elements in data structures is the second most important task. Let's look at two approaches.



Linear Search



A simple but slow algorithm (O(n)). Suitable for unsorted data:



fun linearSearch(arr: IntArray, target: Int): Int {    for (i in arr.indices) {        if (arr[i] == target) return i    }    retu                

Blogs

Book Recommendations