-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTreeBuilding.fs
62 lines (51 loc) · 1.46 KB
/
TreeBuilding.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
module TreeBuilding
open TreeBuildingTypes
type Tree =
| Branch of int * Tree list
| Leaf of int
let recordId t =
match t with
| Branch (id, _) -> id
| Leaf id -> id
let isBranch t =
match t with
| Branch _ -> true
| Leaf _ -> false
let children t =
match t with
| Branch (_, c) -> c
| Leaf _ -> []
let rec build prev acc list =
match list with
| [] -> acc |> List.rev
| r :: rs ->
if r.ParentId >= r.RecordId then
failwith "Nodes with invalid parents"
elif r.RecordId <> prev + 1 then
failwith "Non-continuous list"
else
build r.RecordId (r :: acc) rs
let zeroRecord = { RecordId = 0; ParentId = -1 }
let leafs lst = build 0 [zeroRecord] lst
let rec getNode recordId records =
let children =
records
|> List.filter(fun x -> x.ParentId = recordId)
match children with
| [] -> Leaf recordId
| _ ->
let childNodes =
children
|> List.map(fun x -> getNode x.RecordId records)
Branch(recordId, childNodes)
let buildTree records =
let sortedRecords = records |> List.sortBy (fun x -> x.RecordId)
match sortedRecords with
| [] -> failwith "Empty input"
| h :: t ->
if h.ParentId <> 0 then
failwith "Root node ParentId is invalid"
elif h.RecordId <> 0 then
failwith "Root node RecordId is invalid"
else
getNode 0 (leafs t)