Ternary Search is one of those interesting search algorithms that sparks curiosity the moment you learn how it works. Instead of splitting the array into two parts like Binary Search does, Ternary Search divides the data into three sections and narrows the search space based on two midpoints. This small twist gives the algorithm a different feel, while still keeping its structure simple enough for beginners to follow. The idea is to reduce search time by checking two key positions in each step instead of one, giving it a predictable and elegant rhythm.
with hands-on learning.
get the skills and confidence to land your next move.
Although Ternary Search is not as commonly used in everyday programming as Binary Search, it is very valuable for learning how divide-and-conquer strategies work. It is especially helpful when working with unimodal functions or optimization problems, but you can still apply it to sorted arrays when practicing the basics. For new Swift learners, Ternary Search offers a great chance to explore recursion, compare strategies, and build confidence in algorithmic thinking. Its clear structure also makes it a good stepping stone toward more advanced searching methods.
Program 1: Basic Recursive Ternary Search
This first program shows the standard and most popular version of Ternary Search using recursion. It works on a sorted array and keeps breaking the range into three parts until the target is found.
import Foundation
func ternarySearch(_ array: [Int], target: Int, left: Int, right: Int) -> Int? {
if right < left {
return nil
}
let mid1 = left + (right - left) / 3
let mid2 = right - (right - left) / 3
if array[mid1] == target {
return mid1
}
if array[mid2] == target {
return mid2
}
if target < array[mid1] {
return ternarySearch(array, target: target, left: left, right: mid1 - 1)
} else if target > array[mid2] {
return ternarySearch(array, target: target, left: mid2 + 1, right: right)
} else {
return ternarySearch(array, target: target, left: mid1 + 1, right: mid2 - 1)
}
}
let data = [3, 7, 12, 19, 24, 29, 35]
if let index = ternarySearch(data, target: 24, left: 0, right: data.count - 1) {
print("Found at index \(index)")
} else {
print("Not found")
}This version follows the traditional divide-and-conquer pattern. The algorithm checks two midpoints and decides which of the three sections to explore next. It is useful because the flow is predictable, and the recursive structure makes each step easy for beginners to trace.
Program 2: Iterative Ternary Search
Here is a loop-based version for learners who prefer avoiding recursion. It repeats the same logic using simple while loops.
import Foundation
func ternarySearchIterative(_ array: [Int], target: Int) -> Int? {
var left = 0
var right = array.count - 1
while right >= left {
let mid1 = left + (right - left) / 3
let mid2 = right - (right - left) / 3
if array[mid1] == target {
return mid1
}
if array[mid2] == target {
return mid2
}
if target < array[mid1] {
right = mid1 - 1
} else if target > array[mid2] {
left = mid2 + 1
} else {
left = mid1 + 1
right = mid2 - 1
}
}
return nil
}
let numbers = [5, 9, 14, 18, 22, 27, 31]
if let index = ternarySearchIterative(numbers, target: 14) {
print("Found at index \(index)")
} else {
print("Not found")
}This approach is helpful for beginners who want a clear view of how the boundaries move. Everything happens inside the loop, making the state changes visible with each iteration. It is a great way to understand the mechanics without the mental overhead of recursion.
Program 3: Generic Ternary Search for Comparable Types
This version makes the algorithm flexible by allowing it to work with any type that supports comparisons, such as strings or custom data.
import Foundation
func genericTernarySearch<T: Comparable>(_ array: [T], target: T, left: Int, right: Int) -> Int? {
if right < left {
return nil
}
let mid1 = left + (right - left) / 3
let mid2 = right - (right - left) / 3
if array[mid1] == target {
return mid1
}
if array[mid2] == target {
return mid2
}
if target < array[mid1] {
return genericTernarySearch(array, target: target, left: left, right: mid1 - 1)
} else if target > array[mid2] {
return genericTernarySearch(array, target: target, left: mid2 + 1, right: right)
} else {
return genericTernarySearch(array, target: target, left: mid1 + 1, right: mid2 - 1)
}
}
let words = ["apple", "banana", "cherry", "grape", "mango", "peach"]
if let index = genericTernarySearch(words, target: "grape", left: 0, right: words.count - 1) {
print("Found at index \(index)")
} else {
print("Not found")
}By working with generics, this program shows how powerful Swift can be with abstract algorithms. It teaches beginners how to write functions that adapt to many kinds of data without rewriting the logic every time.
Program 4: Ternary Search With Step-by-Step Tracing
This version prints each action the algorithm takes. It is made for learners who want to see exactly how the array gets divided at each stage.
import Foundation
func ternarySearchTrace(_ array: [Int], target: Int, left: Int, right: Int) -> Int? {
if right < left {
print("Range is empty")
return nil
}
let mid1 = left + (right - left) / 3
let mid2 = right - (right - left) / 3
print("Checking mid1 at \(mid1), mid2 at \(mid2)")
if array[mid1] == target {
return mid1
}
if array[mid2] == target {
return mid2
}
if target < array[mid1] {
print("Going left section")
return ternarySearchTrace(array, target: target, left: left, right: mid1 - 1)
} else if target > array[mid2] {
print("Going right section")
return ternarySearchTrace(array, target: target, left: mid2 + 1, right: right)
} else {
print("Going middle section")
return ternarySearchTrace(array, target: target, left: mid1 + 1, right: mid2 - 1)
}
}
let values = [1, 4, 8, 12, 17, 25, 30]
if let index = ternarySearchTrace(values, target: 17, left: 0, right: values.count - 1) {
print("Found at index \(index)")
} else {
print("Not found")
}This version makes the algorithm much easier to visualize. By printing the midpoints and path taken, beginners can follow the process as if they were solving the problem by hand.
Program 5: Ternary Search Using an Extension
This example adds Ternary Search as an extension to Swift arrays, making it feel like a built-in feature.
import Foundation
extension Array where Element: Comparable {
func ternarySearch(target: Element) -> Int? {
func search(_ left: Int, _ right: Int) -> Int? {
if right < left {
return nil
}
let mid1 = left + (right - left) / 3
let mid2 = right - (right - left) / 3
if self[mid1] == target {
return mid1
}
if self[mid2] == target {
return mid2
}
if target < self[mid1] {
return search(left, mid1 - 1)
} else if target > self[mid2] {
return search(mid2 + 1, right)
} else {
return search(mid1 + 1, mid2 - 1)
}
}
return search(0, self.count - 1)
}
}
let items = [2, 6, 9, 13, 21, 28, 34]
if let index = items.ternarySearch(target: 21) {
print("Found at index \(index)")
} else {
print("Not found")
}This extended form makes the search feel more natural and user-friendly. It shows beginners how algorithms can be wrapped into reusable methods, helping them think in terms of Swift’s expressive features.
Frequently Asked Questions (FAQ)
This section answers the common questions many beginners ask when first learning Ternary Search.
Q1. Does Ternary Search require sorted data?
Yes, just like Binary Search, it only works correctly on sorted arrays. Without sorted data, the three-way division would not guide the search correctly.
Q2. Is Ternary Search faster than Binary Search?
Even though it divides the array into three parts, Ternary Search is usually slower than Binary Search because it performs more comparisons in each step. Binary Search remains the more efficient option in most cases.
Q3. Can Ternary Search work with strings or custom types?
It can, as long as the type supports comparison and the data is sorted. The generic example earlier demonstrates this clearly.
Q4. Why does Ternary Search use two midpoints instead of one?
The two midpoints create three sections instead of two, giving the algorithm more directional information. This is helpful when exploring certain types of functions or optimization problems.
Q5. Where is Ternary Search used in real projects?
It is mostly used in searching unimodal functions or solving optimization problems, rather than simple data lookup. It is very valuable in math-heavy tasks, competitive programming, and algorithm study.
Conclusion
Ternary Search is a clear and engaging algorithm that teaches the principles of dividing a problem into multiple parts and solving each one more efficiently. Whether written with recursion, loops, generics, or extensions, the heart of the algorithm stays the same. It checks two midpoints, decides where the target might be, and reduces the range again. For beginners learning Swift, it offers a great way to explore algorithm design and practice writing reusable, structured code. With the examples here, you can experiment freely, understand the flow, and build confidence as you continue your journey into searching techniques.




