1+ namespace Algorithms.DataStructures
2+
3+ module Treap =
4+ type TreapNode = {
5+ Value: int
6+ Priority: int64
7+ Size: int
8+ LeftChild: Option < TreapNode >
9+ RightChild: Option < TreapNode >
10+ }
11+
12+ module TreapNode =
13+ let create ( value : int ) : TreapNode =
14+ {
15+ Value = value
16+ Priority = System.Random() .NextInt64()
17+ Size = 1
18+ LeftChild = None
19+ RightChild = None
20+ }
21+
22+ let getSize ( maybeNode : Option < TreapNode >) : int =
23+ maybeNode
24+ |> Option.map ( fun node -> node.Size)
25+ |> Option.defaultValue 0
26+
27+ type TreapNode
28+ with
29+ member this.UpdateLeftChild ( leftChild : Option < TreapNode >) : TreapNode =
30+ {
31+ this with
32+ LeftChild = leftChild
33+ Size = 1 + TreapNode.getSize leftChild + TreapNode.getSize this.RightChild
34+ }
35+ member this.UpdateRightChild ( rightChild : Option < TreapNode >) : TreapNode =
36+ {
37+ this with
38+ RightChild = rightChild
39+ Size = 1 + TreapNode.getSize this.LeftChild + TreapNode.getSize rightChild
40+ }
41+
42+ [<RequireQualifiedAccess>]
43+ type Treap = {
44+ Root: Option < TreapNode >
45+ }
46+
47+ let empty : Treap = { Root = None }
48+
49+ /// Splits treap into two parts based on value
50+ /// Returns (left, right) tuple where:
51+ /// - left contains all nodes with values < split value
52+ /// - right contains all nodes with values >= split value
53+ let rec split ( root : Option < TreapNode >) ( value : int ) : Option < TreapNode > * Option < TreapNode > =
54+ match root with
55+ | None ->
56+ None, None
57+ | Some root ->
58+ if root.Value < value then
59+ // root node belongs to the left
60+ // split the right child of root and update the right child of root
61+ let updatedRightOfRoot , right = split root.RightChild value
62+ root.UpdateRightChild updatedRightOfRoot |> Some, right
63+ else
64+ // root node belongs to the right
65+ // split the left child of root and update the left child of root
66+ let left , updatedLeftOfRoot = split root.LeftChild value
67+ left, root.UpdateLeftChild updatedLeftOfRoot |> Some
68+
69+ /// Merges two treaps maintaining BST and heap properties
70+ /// Assumes all values in left treap are less than all values in right treap
71+ let rec merge ( left : Option < TreapNode >) ( right : Option < TreapNode >) : Option < TreapNode > =
72+ match left, right with
73+ | None, right -> right
74+ | left, None -> left
75+ | Some left, Some right ->
76+ if left.Priority < right.Priority then
77+ // left node is the root of the merged treap, merge its right child with right treap
78+ let updatedLeftsRightChild = merge left.RightChild ( Some right)
79+ left.UpdateRightChild updatedLeftsRightChild |> Some
80+ else
81+ // right node is the root of the merged treap, merge its left child with left treap
82+ let updatedRightsLeftChild = merge ( Some left) right.LeftChild
83+ right.UpdateLeftChild updatedRightsLeftChild |> Some
84+
85+ let insert ( value : int ) ( treap : Treap ) : Treap =
86+ let node = TreapNode.create value
87+ let left , right = split treap.Root value
88+ merge ( merge left ( Some node)) right
89+ |> fun root -> { Root = root }
90+
91+ let erase ( value : int ) ( treap : Treap ) : Treap =
92+ let left , right = split treap.Root value
93+ let _ , right = split right ( value + 1 )
94+ merge left right
95+ |> fun root -> { Root = root }
96+
97+ /// Gets the kth smallest element in the treap (0-indexed)
98+ /// Returns None if k is out of bounds
99+ let getKthElement ( treap : Treap ) ( k : uint ) : Option < int > =
100+ if TreapNode.getSize treap.Root |> uint <= k then
101+ None
102+ else
103+ let rec getKthElementImpl ( root : TreapNode ) ( k : int ) : int =
104+ assert ( k < root.Size)
105+ if root.Size = 1 then
106+ root.Value
107+ else
108+ if k < TreapNode.getSize root.LeftChild then
109+ getKthElementImpl ( root.LeftChild |> Option.get) k
110+ elif k = TreapNode.getSize root.LeftChild then
111+ root.Value
112+ else
113+ getKthElementImpl ( root.RightChild |> Option.get) ( k - TreapNode.getSize root.LeftChild - 1 )
114+ getKthElementImpl ( treap.Root |> Option.get) ( int k) |> Some
115+
116+ /// Gets the index of a value in the treap (0 indexed position in sorted order)
117+ /// Returns None if value is not found
118+ let getIndex ( treap : Treap ) ( value : int ) : Option < int > =
119+ let left , right = split treap.Root value
120+ let node , _right = split right ( value + 1 )
121+ node
122+ |> Option.map ( fun _ -> TreapNode.getSize left)
0 commit comments