Binary Search Trees in PureScript: A Comprehensive Guide
In this article, we will take a deep dive into the world of Binary Search Trees (BST) and their implementation in PureScript.
What is a Binary Search Tree?
A Binary Search Tree (BST) is a tree data structure in which each node has at most two children, referred to as the left child and the right child. For each node, all elements in the left subtree are less than the node, and all elements in the right subtree are greater.
PureScript Implementation
In PureScript, we can define a binary tree as a custom data type Tree
, which is either a Leaf
(an empty tree) or a Node
that contains a value and two subtrees (left and right).
data Tree a = Leaf | Node (Tree a) a (Tree a)
Here a
is a type variable, indicating that our tree can store elements of any type.
Inserting Elements
We can insert elements into the BST using the insertElement
function:
insertElement:: forall a. Ord a => a -> Tree a -> Tree a
insertElement x Leaf = Node Leaf x Leaf
insertElement x (Node l a r)
| x < a = Node (insertElement x l) a r
| otherwise = Node l a (insertElement x r)
This function inserts a new value into the correct position in the tree to maintain the BST property.
Building a BST
We can build a BST from a list of elements using the buildBST
function:
buildBST :: forall a. Ord a => List a -> Tree a
buildBST Nil = Leaf
buildBST (Cons x xs) = insertElement x (buildBST xs)
This function constructs a BST by inserting each element of the list into the tree one by one.
Traversals
We can traverse the BST in different orders. For instance, preorder
and inorder
functions are implemented as follows:
preorder :: forall a. Ord a => Tree a -> Array a
preorder Leaf = []
preorder (Node l a r) = concat [[a], preorder l, preorder r]
inorder :: forall a. Ord a => Tree a -> Array a
inorder Leaf = []
inorder (Node l a r) = concat [preorder l, [a], preorder r]
- Preorder traversal visits the current node before its child nodes.
- Inorder traversal visits the left child, then the current node, and finally, the right child. This will return the values in a sorted order for a BST.
Validating a BST
We can check if a tree is a valid BST using the bst
function:
bst :: forall a. Ord a => Tree a -> Boolean
bst tree =
case tree of
Leaf -> true
Node left value right ->
let lt x = x <= value
gt x = x >= value
in all lt (setTree left) && all gt (setTree right) && bst left && bst right
This function checks if all elements in the left subtree are less than the node and all elements in the right subtree are greater. It does this check recursively for all nodes.
Conclusion
Binary Search Trees are powerful data structures that allow fast lookup, addition, and removal of items, and can be used to implement ordered collections of items. PureScript provides a type-safe and functional way to implement and work with BSTs.