Dart Program to Implement Ternary Search

Dart Program to Implement Ternary Search

Searching efficiently is one of the most important skills a programmer can develop, and Ternary Search is a smart algorithm designed to do exactly that. Unlike binary search, which divides the dataset into two parts, Ternary Search splits it into three segments, helping you narrow down the location of the target element faster in certain scenarios. Learning Ternary Search in Dart is a great way for beginners to understand recursive thinking, divide-and-conquer strategies, and the practical applications of searching algorithms.

Pluralsight Logo
Accelerate your tech career
with hands-on learning.
Whether you're a tech newbie or a total pro,
get the skills and confidence to land your next move.
Start 10-Day Free Trial

Ternary Search is particularly useful when dealing with sorted datasets where frequent searches are required. It is applied in scenarios like finding elements in ordered arrays, optimizing function evaluations, or solving problems where repeated comparisons are costly. In this article, we will explore multiple ways to implement Ternary Search in Dart, including iterative and recursive approaches, so beginners can follow along with clear, executable examples.

Program 1: Recursive Ternary Search

This program demonstrates a classic recursive approach to Ternary Search, dividing the array into three parts and recursively checking the correct segment.

int ternarySearch(List<int> numbers, int left, int right, int target) {

  if (right >= left) {

    int mid1 = left + ((right - left) ~/ 3);
    int mid2 = right - ((right - left) ~/ 3);

    if (numbers[mid1] == target) return mid1;
    if (numbers[mid2] == target) return mid2;

    if (target < numbers[mid1]) return ternarySearch(numbers, left, mid1 - 1, target);
    else if (target > numbers[mid2]) return ternarySearch(numbers, mid2 + 1, right, target);
    else return ternarySearch(numbers, mid1 + 1, mid2 - 1, target);

  }

  return -1;

}

void main() {

  List<int> numbers = [10, 20, 30, 40, 50, 60, 70];
  int target = 50;
  int result = ternarySearch(numbers, 0, numbers.length - 1, target);

  if (result != -1) {
    print("Element $target found at index $result");
  } else {
    print("Element $target not found in the list");
  }

}

In this program, the array is divided into three parts with two midpoints. By recursively checking each segment, the search narrows down efficiently. Beginners can see how recursion simplifies dividing the problem into smaller, manageable parts.

Program 2: Iterative Ternary Search

This example demonstrates an iterative approach, avoiding recursion while implementing the same logic for searching elements.

int iterativeTernarySearch(List<int> numbers, int target) {

  int left = 0;
  int right = numbers.length - 1;

  while (left <= right) {

    int mid1 = left + ((right - left) ~/ 3);
    int mid2 = right - ((right - left) ~/ 3);

    if (numbers[mid1] == target) return mid1;
    if (numbers[mid2] == target) return mid2;

    if (target < numbers[mid1]) {
      right = mid1 - 1;
    } else if (target > numbers[mid2]) {
      left = mid2 + 1;
    } else {
      left = mid1 + 1;
      right = mid2 - 1;
    }

  }

  return -1;

}

void main() {

  List<int> numbers = [5, 15, 25, 35, 45, 55];
  int target = 35;
  int result = iterativeTernarySearch(numbers, target);

  if (result != -1) {
    print("Element $target found at index $result");
  } else {
    print("Element $target not found in the list");
  }

}

The iterative method achieves the same result as recursion without the overhead of function calls. Beginners can see a step-by-step narrowing of the search range, which is helpful in understanding how divide-and-conquer works in loops.

Program 3: Ternary Search on a Large Dataset

This program demonstrates Ternary Search on a larger sorted array to highlight its efficiency over linear search.

int ternarySearchLarge(List<int> numbers, int target) {

  int left = 0;
  int right = numbers.length - 1;

  while (left <= right) {

    int mid1 = left + ((right - left) ~/ 3);
    int mid2 = right - ((right - left) ~/ 3);

    if (numbers[mid1] == target) return mid1;
    if (numbers[mid2] == target) return mid2;

    if (target < numbers[mid1]) {
      right = mid1 - 1;
    } else if (target > numbers[mid2]) {
      left = mid2 + 1;
    } else {
      left = mid1 + 1;
      right = mid2 - 1;
    }

  }

  return -1;

}

void main() {

  List<int> numbers = List.generate(100, (i) => i * 2);
  int target = 88;
  int result = ternarySearchLarge(numbers, target);

  if (result != -1) {
    print("Element $target found at index $result");
  } else {
    print("Element $target not found in the list");
  }

}

By applying Ternary Search on 100 elements, beginners can appreciate the reduction in comparisons compared to linear search. It clearly shows the power of divide-and-conquer on larger datasets.

Program 4: Recursive Ternary Search with Function Reuse

This example wraps Ternary Search logic in a reusable function to make it easier to search multiple elements without rewriting the logic.

int reusableTernarySearch(List<int> numbers, int left, int right, int target) {

  if (right >= left) {

    int mid1 = left + ((right - left) ~/ 3);
    int mid2 = right - ((right - left) ~/ 3);

    if (numbers[mid1] == target) return mid1;
    if (numbers[mid2] == target) return mid2;

    if (target < numbers[mid1]) return reusableTernarySearch(numbers, left, mid1 - 1, target);
    else if (target > numbers[mid2]) return reusableTernarySearch(numbers, mid2 + 1, right, target);
    else return reusableTernarySearch(numbers, mid1 + 1, mid2 - 1, target);

  }

  return -1;

}

void main() {

  List<int> numbers = [3, 6, 9, 12, 15, 18, 21];
  int target = 15;
  int result = reusableTernarySearch(numbers, 0, numbers.length - 1, target);

  if (result != -1) {
    print("Element $target found at index $result");
  } else {
    print("Element $target not found in the list");
  }

}

This method teaches beginners how to structure recursive functions for repeated use, promoting modular and maintainable code while still leveraging the efficiency of Ternary Search.

Program 5: Ternary Search with Error Handling

This program shows a robust implementation that handles empty arrays or cases where the target is not present.

int safeTernarySearch(List<int> numbers, int left, int right, int target) {

  if (numbers.isEmpty) return -1;

  if (right >= left) {

    int mid1 = left + ((right - left) ~/ 3);
    int mid2 = right - ((right - left) ~/ 3);

    if (numbers[mid1] == target) return mid1;
    if (numbers[mid2] == target) return mid2;

    if (target < numbers[mid1]) return safeTernarySearch(numbers, left, mid1 - 1, target);
    else if (target > numbers[mid2]) return safeTernarySearch(numbers, mid2 + 1, right, target);
    else return safeTernarySearch(numbers, mid1 + 1, mid2 - 1, target);

  }

  return -1;

}

void main() {

  List<int> numbers = [7, 14, 21, 28, 35, 42];
  int target = 21;
  int result = safeTernarySearch(numbers, 0, numbers.length - 1, target);

  if (result != -1) {
    print("Element $target found at index $result");
  } else {
    print("Element $target not found in the list");
  }

}

Error handling ensures the program remains safe when given an empty list or a target that does not exist. Beginners can learn the importance of robust coding practices alongside algorithm implementation.

Frequently Asked Questions (FAQ)

Ternary Search is a useful algorithm for sorted datasets, and beginners often have questions about it.

Q1: What is Ternary Search used for?
Ternary Search is used to locate elements in sorted arrays efficiently by dividing the search space into three segments.

Q2: Can it work on unsorted arrays?
No, Ternary Search requires the dataset to be sorted for correct results.

Q3: Is Ternary Search faster than binary search?
In theory, Ternary Search can reduce comparisons slightly, but binary search is usually simpler and faster in practice for most datasets.

Q4: How are the midpoints calculated?
Two midpoints are calculated to split the array into three equal segments, allowing the algorithm to narrow down the search efficiently.

Q5: Why should beginners learn Ternary Search?
It teaches divide-and-conquer techniques, recursion, and iterative logic in a clear and structured way, enhancing understanding of efficient search algorithms.

Conclusion

Ternary Search is a powerful algorithm for efficiently searching sorted datasets. By implementing it in Dart using recursive, iterative, reusable, and safe approaches, beginners can learn important programming concepts like divide-and-conquer, recursion, loops, and error handling.

Practicing these programs helps beginners understand both the logic and efficiency of advanced searching algorithms. Starting with simple examples, experimenting with recursion and iteration, and applying error-handling techniques can strengthen algorithmic thinking and prepare learners for more complex problems in Dart programming.

Scroll to Top