Binary Search Trees#

Binary Tree#

Overview

  • A binary tree is a hierarchical data structure consisting of nodes.

  • Each node contains a value and references to its left and right children.

  • The left child is smaller than the parent, while the right child is larger.

https://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Binary_tree_v2.svg/1920px-Binary_tree_v2.svg.png
\[bin\_tree = \{1, 7, 9, 2, 6, 9, 5, 11, 5 \}\]

Implementing binary trees#

Node

\(data\)

\(left\) child

\(right\) child

../../_images/15_s7.png

\(tree = \{a, b, c, d, e, f\}\)

\(k\)-ary trees#

https://media.geeksforgeeks.org/wp-content/cdn-uploads/20201102101430/Tree2.jpg

Fig. 14 Every node has between \(0\) and \(k\) children#

https://miro.medium.com/v2/resize:fit:1400/format:webp/1*CMGFtehu01ZEBgzHG71sMg.png
https://miro.medium.com/max/1400/1*fh2By4u-SxTlt6u2xHqnCg.png

Fig. 15
Full Binary Tree is a Binary Tree in which every node has 0 or 2 children.
towardsdatascience.com
#

https://miro.medium.com/max/1400/1*M1qfRR59TR9-i4pmI-_Clg.png

Fig. 16
Complete Binary Tree has all levels completely filled with nodes except the last level and in the last level, all the nodes are as left side as possible. – towardsdatascience.com
#

https://miro.medium.com/max/1400/1*EgcvwUHXnmdOpbHQwgCknA.png

Fig. 17
Perfect Binary Tree is a Binary Tree in which all internal nodes have 2 children and all the leaf nodes are at the same depth or same level. – towardsdatascience.com
#

https://miro.medium.com/max/1400/1*m5BjLJeSrSGH4US-QXj4aA.png

Fig. 18
Degenerate Binary Tree is a Binary Tree where every parent node has only one child node. – towardsdatascience.com
#

https://miro.medium.com/max/1400/1*jSq-xjEZYytNDIBpZNQC2w.png

Fig. 19
Balanced Binary Tree is a Binary tree in which height of the left and the right sub-trees of every node may differ by at most 1. – towardsdatascience.com
#

Binary Search Trees#

Understanding BSTs

https://blog.penjee.com/wp-content/uploads/2015/11/binary-search-tree-sorted-array-animation.gif
  • Each node in a binary tree can have at most two children.

    • This means that a node can have either zero, one, or two children.

  • The left child of a node is typically smaller than the node, while the right child is larger (or equal) than the node.

    • This rule is often associated with binary search trees (BSTs), where the values are arranged in a specific order for efficient searching and retrieval.

  • The order of children matters.

    • In a binary tree, the left child is typically referenced before the right child.

    • The order of children affects the tree’s traversal and interpretation.

  • Nodes are connected by edges.

    • The connections between nodes are represented by edges in a binary tree.

    • Each node (except the root) has exactly one incoming edge from its parent.

  • The height of a binary tree.

    • The height of a binary tree is the maximum number of edges from the root to a leaf node.

    • It represents the longest path from the root to any leaf node in the tree.

  • The depth (level) of a node.

    • The depth (or level) of a node in a binary tree represents the number of edges from the root to that node.

    • The root node is at depth 0, its children are at depth 1, and so on.

  • The number of nodes in a binary tree.

    • The total number of nodes in a binary tree can vary.

    • The minimum number of nodes in a binary tree is 0, while the maximum number depends on the height of the tree.

Simplified is bst

A BST has symmetric order

  • each node \(x\) in a BST has a key

\[key(x)\]
  • for all nodes \(y\) in the left subtree of \(x\),

\[key(y) < key(x)^{**}\]
  • for all nodes \(y\) in the right subtree of \(x\),

\[key(y) > key(x)^{**}\]
https://i.pinimg.com/originals/4e/5a/00/4e5a00c98d5b46ed4cbf224ac11dc115.png

(**) assume that the keys of a BST are pairwise distinct

https://res.cloudinary.com/practicaldev/image/fetch/s--od-naD9n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://miro.medium.com/max/975/1*PWJiwTxRdQy8A_Y0hAv5Eg.png

BST Classes#

BSTNode
 1class BSTNode { 
 2  
 3  private: 
 4    int data;  
 5    BSTNode *left;  
 6    BSTNode *right;
 7  
 8  public:
 9    BSTNode(int d);
10    ~BSTNode();
11  
12  friend class BSTree;
13
14};
BSTree
 1class BSTree{
 2  
 3  private:
 4    BSTNode *root;
 5    void destroy(BSTNode *p);
 6    
 7  public:
 8    BSTree();
 9    ~BSTree();
10    void insert(int d);
11    void remove(int d);  
12    BSTNode *search(int d);
13
14};

insert#

To insert a new value into a BST:

  • Start at the root node.

  • If the value is smaller, go to the left subtree; if larger, go to the right subtree.

  • Repeat steps 2 until an empty spot is found.

  • Insert the new node in the empty spot.

remove#

To delete a node from a BST:

  • Find the node to delete.

  • If the node has no children, simply remove it.

  • If the node has one child, replace it with its child.

  • If the node has two children, find the node’s successor (smallest value in the right subtree) or predecessor (largest value in the left subtree).

  • Replace the node with its successor/predecessor and delete the successor/predecessor from its original position.

../../_images/algorithm-binary-tree-search_4.JPG

Fig. 20 \(remove : leaf\)#

../../_images/algorithm-binary-tree-search_5.JPG

Fig. 21 \(remove:\ with\ 1\ child\)#

../../_images/algorithm-binary-tree-search_6.JPG

Fig. 22 \(remove:\ with\ 2\ children\)#

Traversals#

Implications#

Traversal of a tree T is a systematic way of accessing, or “visiting,” all the positions of T . The specific action associated with the “visit” of a position p depends on the application of this traversal, and could involve anything from incrementing a counter to performing some complex computation for p.

https://www.bogotobogo.com/GoLang/images/BinarySearchTree_BST/print_functions.png
// nodes of the BST are visited in a
// pre-defined order before visiting
// their child nodes.

algorithm preorder (p) {
  if (p) {
    visit(p)
    preorder(p -> left)
    preorder(p -> right)
  }
}
https://sbme-tutorials.github.io/2020/data-structure-FALL/images/Tree06.png

Fig. 23 preorder#

// nodes of the BST are visited in a 
// pre-defined order after visiting 
// their child nodes.

algorithm postorder (p) {
  if (p) {
    postorder(p -> left)
    postorder(p -> right)
    visit(p)
  }
}
https://sbme-tutorials.github.io/2020/data-structure-FALL/images/Tree07.png

Fig. 24 postorder#

// nodes of the BST are visited in
// ascending order of their values.

algorithm inorder (p) {
  if (p) {
    inorder(p -> left)
    visit(p)
    inorder(p -> right)
  }
}
https://sbme-tutorials.github.io/2020/data-structure-FALL/images/Tree08.png

Fig. 25 inorder#

How would we:

best-case

worst-case

average-case

search

insert

remove

\[Cost\ of\ basic\ operations??\]

best-case

worst-case

average-case

search

\(O(1)\)

\(O(n)\)

\(O(log\ n)\)

insert

\(O(1)\)

\(O(n)\)

\(O(log\ n)\)

remove

\(O(log\ n)\)

\(O(n)\)

\(O(log\ n)\)

\[Cost\ of\ basic\ operations??\]

Average-case analysis#

If \(n\) distinct keys are inserted into a BST in random order, expected number of compares for basic operations is

\[\ \sim2\ ln\ n \approx 1.39\ log\ n\ \]
  • proof: 1-1 correspondence with quick-sort

https://mycloudology.com/algorithm-binary-tree-search/algorithm-binary-tree-search_10.JPG
\[ \ \ h = O(log\ n) \ \ \]

Collections / Dictionaries#

What?

Sequential (unordered)

Sequential (ordered)

BST

search

search for a key

\(O(n)\)

\(O(log\ n)\)

\(O(h)\)

insert

insert a key

\(O(n)\)

\(O(n)\)

\(O(h)\)

delete

delete a key

\(O(n)\)

\(O(n)\)

\(O(h)\)

min/max

smallest/largest key

\(O(n)\)

\(O(1)\)

\(O(h)\)

floor/ceiling

predecessor / successor

\(O(n)\)

\(O(log\ n)\)

\(O(h)\)

rank

# of keys less than key

\(O(n)\)

\(O(log\ n)\)

\(O(h)\)**

(**) requires the use of ‘size’ at every node