Chapters

Hide chapters

Data Structures & Algorithms in Dart

Second Edition · Flutter · Dart 3.0 · VS Code 1.78

Section VI: Challenge Solutions

Section 6: 21 chapters
Show chapters Hide chapters

10. Binary Search Trees
Written by Jonathan Sande

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Heads up... You’re accessing parts of this content for free, with some sections shown as scrambled text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

A binary search tree, or BST, is a data structure that facilitates fast lookup, insert and removal operations. Consider the following decision tree where picking a side forfeits all the possibilities of the other side, cutting the problem in half:

no yes no yes no yes no yes yes no Should I go the gym? Did I go yesterday? Did I go jogging yesterday? Am I still feeling sore? Did I run 5km? Go to the gym Go to the gym Go to sleep Rest for the day Break Go to the gym Did you slack off in the last session?

Once choose a branch, there is no looking back. You keep going until you make a final decision at a leaf node. Binary trees let you do the same thing. Specifically, a binary search tree imposes two rules on the binary tree you saw in the previous chapter:

  • The value of a left child must be less than the value of its parent.
  • Consequently, the value of a right child must be greater than or equal to the value of its parent.

Binary search trees use these properties to save you from performing unnecessary checking. As a result, lookup, insert and removal have an average time complexity of O(log n), which is considerably faster than linear data structures such as lists and linked lists.

In this chapter, you’ll learn about the benefits of BST relative to a list and, as usual, implement the data structure from scratch.

List vs. BST

To illustrate the power of using BST, you’ll look at some common operations and compare the performance of lists against the binary search tree.

Consider the following two collections:

1 25 88 18 45 4 40 105 20 77 70 40 18 77 1 20 70 105 4 25 45 88

Lookup

There’s only one way to do element lookups for an unsorted list. You need to check every element in the list from the start:

4 11 24 42 43 3 26 214 35 23 89
Mionfxeqn biv 602

51 78 34 21 832 04 43 2 16 7 86
Jieqmyoql cux 555

Insertion

The performance benefits for the insertion operation follow a similar story. Assume you want to insert 0 into a collection. Inserting at the front of the list causes all other elements to shift backwards by one position. It’s like butting in line. Everyone in the line behind your chosen spot needs to make space for you by shuffling back:

4 58 05 80 25 9 63 899 57 23 73 1 3 14 29 80 92 7 37 956 46 63 42
Azlinlupv 4 oq tuhyos urwud

98 47 07 50 355 31 06 1 52 0 03

Removal

Similar to insertion, removing an element in a list also triggers a shuffling of elements:

9 44 16 36 54 2 36 596 75 23 43 1 96 80 94 4 69 298 72 91 89 bivoqu 43
Zuhiyums 55 jcob qba jugv

30 28 73 45 251 71 07 3 87 0 90

Implementation

Open up the starter project for this chapter. In the lib folder, you’ll find binary_node.dart with the BinaryNode type you created in the previous chapter. Create a new file named binary_search_tree.dart in the same folder and add the following code to it:

Inserting Elements

In accordance with BST rules, nodes of the left child must contain values less than the current node. Nodes of the right child must contain values greater than or equal to the current node. You’ll implement the insert method while respecting these rules.

Adding an Insert Method

Add the following to BinarySearchTree:

Testing it Out

Open bin/starter.dart and replace the contents with the following:

Balanced vs. Unbalanced Trees

The previous tree looks a bit unbalanced, but it does follow the rules. However, this tree layout has undesirable consequences. When working with trees, you always want to achieve a balanced format:

3 5 4 2 2 3 1 8 4 2 ducexzay olrequhcay

7 5 6 3 0 9 5 3 9 5 odbupijjek maramxuq 6 1 3

Building a Balanced Tree

Add the following function below main:

Finding Elements

Finding an element in a binary search tree requires you to traverse through its nodes. It’s possible to come up with a relatively simple implementation by using the existing traversal mechanisms that you learned about in the previous chapter.

Optimizing contains

Relying on the properties of BST can help you avoid needless comparisons. Back in BinarySearchTree, replace contains with the following:

Removing Elements

Removing elements is a little more tricky because you need to handle a few different scenarios.

Removing a Leaf Node

Removing a leaf node is straightforward. Simply detach the leaf node:

0 8 6 6 9 9
bifavibp 3

Removing Nodes With One Child

When removing nodes with one child, you’ll need to reconnect that child with the rest of the tree:

2 2 3 7 0 0
recanelv 4, vgimj xij ayi qgejk

Removing Nodes With Two Children

Nodes with two children are a bit more complicated, so a more complex example tree will better illustrate how to handle this situation. Assume that you have the following tree and that you want to remove the value 25:

75 00 75 76 86 20 05 60 82 49 92 50 86

57 34 46 20 11 92 10 04 97 91 05 01

12 81 94 56 42 73 53 52 55 23 92 49 17

63 06 48 28 29 08 85 46 65 35 83 17 01

Finding the Minimum Node in a Subtree

Open up binary_search_tree.dart. You’ll implement the remove method in just a minute, but first add the following helper extension at the bottom of the file:

Implementing remove

Now add these two methods to BinarySearchTree:

Handling the Removal Cases

Replace the // more to come comment above with the following code:

Testing it Out

Head back to main and test remove by writing the following:

Challenges

Think you’ve gotten the hang of binary search trees? Try out these three challenges to lock the concepts down. As usual, you can find the answers in the Challenge Solutions section at the end of the book.

Challenge 1: Binary Tree or Binary Search Tree?

Write a function that checks if a binary tree is a binary search tree.

Challenge 2: Equality

Given two binary trees, how would you test if they are equal or not?

Challenge 3: Is it a Subtree?

Create a method that checks if the current tree contains all the elements of another tree.

Key Points

  • The binary search tree (BST) is a powerful data structure for holding sorted data.
  • Elements of the binary search tree must be comparable.
  • The time complexity for insert, remove and contains methods in a BST is O(log n).
  • Performance will degrade to O(n) as the tree becomes unbalanced. This is undesirable, but self-balancing trees such as the AVL tree can overcome the problem.
Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.

You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now