Back to Data Structures & Algorithms
2025-12-246 min read

The Stern-Brocot tree (Data Structures & Algorithms)

Learn The Stern-Brocot tree (Data Structures & Algorithms) step by step with clear examples and exercises.

Why This Matters

Welcome to this full guide on the Stern-Brocot tree and Farey sequences, essential tools for competitive programming! We'll cover practical examples using Python, helping you understand these concepts better. Let's dive in!

Importance of Understanding Stern-Brocot Tree and Farey Sequences

In competitive programming, algorithms play a crucial role. The Stern-Brocot tree and Farey sequences are powerful data structures that help solve problems related to fractions efficiently. Understanding them will equip you with valuable skills for coding challenges and interviews.

These data structures can be used in various applications, such as finding the shortest common supersequence (SCS) of two binary strings, solving Diophantine equations, and more. Mastering these concepts will not only improve your problem-solving abilities but also make you a stronger competitor in programming contests.

Prerequisites

Core Concept

Stern-Brocot Tree

The Stern-Brocot tree is a binary tree that generates all positive fractions in lower-right to upper-left order, starting from 0/1 at the root. Each non-leaf node represents the mediant (least common multiple of the denominators with the sum of numerators divided by this least common multiple) of its children's fractions.

Here's a simple Python implementation of the Stern-Brocot tree:

class Fraction:
def __init__(self, num, den):
self.num = num
self.den = den

def mediant(f1, f2):
gcd = gcd(f1.den, f2.den)
return Fraction((f1.num * f2.den + f2.num * f1.den) // gcd, gcd)

@staticmethod
def gcd(a, b):
while b:
a, b = b, a % b
return a

def __str__(self):
return f"{self.num}/{self.den}"

def build_tree(n, tree=None):
if not tree:
tree = [Fraction(0, 1)]
if len(tree) == n:
return tree

f1, f2 = tree[-2], tree[-1]
new_fraction = Fraction.mediant(f1, f2)
tree.append(new_fraction)
build_tree(n, tree + [new_fraction])
build_tree(n, tree)

Generate the first 9 fractions in the Stern-Brocot tree

fractions = build_tree(9)

for fraction in fractions:

print(fraction)


### Farey Sequence

A Farey sequence is a list of all fractions between 0 and 1 (inclusive), sorted by their size (the numerator and denominator sum). The Farey sequence for a given range [a/b, c/d] contains all fractions from [0/1, a/b] and [c/d, 1/1].

Here's a Python implementation of the Farey sequence:

def farey_sequence(n, k=None):

if not k:

k = n // 2 + 1

if k == 1:

return [Fraction(0, 1)]

fares = farey_sequence(k - 1)

for i in range(len(fares)):

f1 = fares[i]

f2 = fares[-(i + 1)]

new_fraction = Fraction.mediant(f1, f2)

fares.insert((i + 1), new_fraction)

return fares + farey_sequence(n - k)

Generate the Farey sequence for the range [0, 9]

fractions = farey_sequence(9)

for fraction in fractions:

print(fraction)

Worked Example

Let's find the mediant of 3/4 and 5/6 using both the Stern-Brocot tree and Farey sequence implementations:

  1. Find the fractions in the Stern-Brocot tree up to the level containing 3/4 and 5/6. In this case, we need to build a tree of size 12:
fractions = build_tree(12)
  1. Locate 3/4 and 5/6 in the list:
three_fourths = Fraction(3, 4)
five_sixths = Fraction(5, 6)
  1. Check their positions in the list:
index_of_three_fourths = fractions.index(three_fourths)
index_of_five_sixths = fractions.index(five_sixths)
  1. Calculate the mediant using the Stern-Brocot tree implementation:
mediant_sc = Fraction.mediant(three_fourths, five_sixths)
print("Mediant (Stern-Brocot):", mediant_sc)
  1. Calculate the mediant using the Farey sequence implementation:
mediant_fs = Fraction.mediant(farey_sequence(12)[index_of_three_fourths], farey_sequence(12)[index_of_five_sixths])
print("Mediant (Farey):", mediant_fs)

Both implementations should return the same result:

Mediant (Stern-Brocot): Fraction(23, 10)
Mediant (Farey): Fraction(23, 10)

Common Mistakes

  1. Incorrect implementation of the mediant function: Make sure you calculate the least common multiple correctly and divide the sum of numerators by this value.
  1. Misunderstanding the role of the Stern-Brocot tree and Farey sequence: Remember that the Stern-Brocot tree generates all positive fractions in lower-right to upper-left order, while the Farey sequence is a list of all fractions between 0 and 1 (inclusive), sorted by their size.
  1. Not handling edge cases properly: Ensure you handle cases where the range for the Farey sequence includes only one fraction or no fractions appropriately.
  1. Implementing inefficient algorithms: To optimize your implementations, consider using dynamic programming techniques to avoid redundant calculations and improve performance. Additionally, you may want to use a more efficient data structure for storing fractions, such as a Rational class that provides fast arithmetic operations.

Practice Questions

  1. Implement a function to find the greatest common divisor (gcd) of two integers using Euclid's algorithm.
  2. Write a Python program to generate and print the first 10 terms of the Fibonacci sequence.
  3. Given two fractions, write a function that returns their least common multiple (lcm).
  4. Implement a function to find the mediant of three fractions using both the Stern-Brocot tree and Farey sequence implementations.
  5. Write a Python program to check if a given fraction is in the Farey sequence for the range [0, 10].
  6. Implement an algorithm to find the shortest common supersequence (SCS) of two binary strings using the Stern-Brocot tree and Farey sequence.
  7. Write a function to convert a given fraction to its continued fraction representation.
  8. Implement a function to determine if a rational number is a term in the Stern-Brocot tree or Farey sequence.
  9. Write a program to find the sum of all fractions in the Farey sequence for the range [0, 100].
  10. Implement an algorithm to solve Diophantine equations using the Stern-Brocot tree and Farey sequence.

FAQ

What's the difference between the Stern-Brocot tree and the Farey sequence?

  • The Stern-Brocot tree generates all positive fractions in lower-right to upper-left order, while the Farey sequence is a list of all fractions between 0 and 1 (inclusive), sorted by their size.

How can I use the Stern-Brocot tree and Farey sequence in competitive programming?

  • These data structures are useful for solving problems related to fractions efficiently, such as finding the shortest common supersequence (SCS) of two binary strings, solving Diophantine equations, and more.

What's an example use case for the Stern-Brocot tree and Farey sequence?

  • One possible use case is to solve the problem of finding the shortest common supersequence (SCS) of two binary strings. The Stern-Brocot tree can be used to convert fractions representing the lengths of the two binary strings into a single fraction representing the length of the SCS. Then, the Farey sequence can be used to find the SCS itself.

Can I use other data structures instead of the Stern-Brocot tree and Farey sequence for solving problems related to fractions?

  • Yes, there are alternative approaches for solving such problems, but the Stern-Brocot tree and Farey sequence offer efficient solutions in many cases, especially when dealing with large numbers of fractions.

How can I optimize my Stern-Brocot tree or Farey sequence implementation?

  • To optimize your implementations, consider using dynamic programming techniques to avoid redundant calculations and improve performance. Additionally, you may want to use a more efficient data structure for storing fractions, such as a Rational class that provides fast arithmetic operations.
The Stern-Brocot tree (Data Structures & Algorithms) | Data Structures & Algorithms | XQA Learn