1
1
//: Playground - noun: a place where people can play
2
2
3
3
public class SegmentTree < T> {
4
-
5
- private var value : T
6
- private var function : ( T , T ) -> T
7
- private var leftBound : Int
8
- private var rightBound : Int
9
- private var leftChild : SegmentTree < T > ?
10
- private var rightChild : SegmentTree < T > ?
11
-
12
- public init ( array: [ T ] , leftBound: Int , rightBound: Int , function: ( T , T ) -> T ) {
13
- self . leftBound = leftBound
14
- self . rightBound = rightBound
15
- self . function = function
16
-
17
- if leftBound == rightBound {
18
- value = array [ leftBound]
19
- } else {
20
- let middle = ( leftBound + rightBound) / 2
21
- leftChild = SegmentTree < T > ( array: array, leftBound: leftBound, rightBound: middle, function: function)
22
- rightChild = SegmentTree < T > ( array: array, leftBound: middle+ 1 , rightBound: rightBound, function: function)
23
- value = function ( leftChild!. value, rightChild!. value)
24
- }
25
- }
26
-
27
- public convenience init ( array: [ T ] , function: ( T , T ) -> T ) {
28
- self . init ( array: array, leftBound: 0 , rightBound: array. count- 1 , function: function)
29
- }
30
-
31
- public func queryWithLeftBound ( leftBound : Int , rightBound: Int ) -> T {
32
- if self . leftBound == leftBound && self . rightBound == rightBound {
33
- return self . value
34
- }
35
-
36
- guard let leftChild = leftChild else { fatalError ( " leftChild should not be nil " ) }
37
- guard let rightChild = rightChild else { fatalError ( " rightChild should not be nil " ) }
38
-
39
- if leftChild. rightBound < leftBound {
40
- return rightChild. queryWithLeftBound ( leftBound, rightBound: rightBound)
41
- } else if rightChild. leftBound > rightBound {
42
- return leftChild. queryWithLeftBound ( leftBound, rightBound: rightBound)
43
- } else {
44
- let leftResult = leftChild. queryWithLeftBound ( leftBound, rightBound: leftChild. rightBound)
45
- let rightResult = rightChild. queryWithLeftBound ( rightChild. leftBound, rightBound: rightBound)
46
- return function ( leftResult, rightResult)
47
- }
48
- }
49
-
50
- public func replaceItemAtIndex ( index: Int , withItem item: T ) {
51
- if leftBound == rightBound {
52
- value = item
53
- } else if let leftChild = leftChild, rightChild = rightChild {
54
- if leftChild. rightBound >= index {
55
- leftChild. replaceItemAtIndex ( index, withItem: item)
56
- } else {
57
- rightChild. replaceItemAtIndex ( index, withItem: item)
58
- }
59
- value = function ( leftChild. value, rightChild. value)
60
- }
61
- }
4
+
5
+ private var value : T
6
+ private var function : ( T , T ) -> T
7
+ private var leftBound : Int
8
+ private var rightBound : Int
9
+ private var leftChild : SegmentTree < T > ?
10
+ private var rightChild : SegmentTree < T > ?
11
+
12
+ public init ( array: [ T ] , leftBound: Int , rightBound: Int , function: @escaping ( T , T ) -> T ) {
13
+ self . leftBound = leftBound
14
+ self . rightBound = rightBound
15
+ self . function = function
16
+
17
+ if leftBound == rightBound {
18
+ value = array [ leftBound]
19
+ } else {
20
+ let middle = ( leftBound + rightBound) / 2
21
+ leftChild = SegmentTree < T > ( array: array, leftBound: leftBound, rightBound: middle, function: function)
22
+ rightChild = SegmentTree < T > ( array: array, leftBound: middle+ 1 , rightBound: rightBound, function: function)
23
+ value = function ( leftChild!. value, rightChild!. value)
24
+ }
25
+ }
26
+
27
+ public convenience init ( array: [ T ] , function: @escaping ( T , T ) -> T ) {
28
+ self . init ( array: array, leftBound: 0 , rightBound: array. count- 1 , function: function)
29
+ }
30
+
31
+ public func query ( withLeftBound : Int , rightBound: Int ) -> T {
32
+ if self . leftBound == leftBound && self . rightBound == rightBound {
33
+ return self . value
34
+ }
35
+
36
+ guard let leftChild = leftChild else { fatalError ( " leftChild should not be nil " ) }
37
+ guard let rightChild = rightChild else { fatalError ( " rightChild should not be nil " ) }
38
+
39
+ if leftChild. rightBound < leftBound {
40
+ return rightChild. query ( withLeftBound : leftBound, rightBound: rightBound)
41
+ } else if rightChild. leftBound > rightBound {
42
+ return leftChild. query ( withLeftBound : leftBound, rightBound: rightBound)
43
+ } else {
44
+ let leftResult = leftChild. query ( withLeftBound : leftBound, rightBound: leftChild. rightBound)
45
+ let rightResult = rightChild. query ( withLeftBound : rightChild. leftBound, rightBound: rightBound)
46
+ return function ( leftResult, rightResult)
47
+ }
48
+ }
49
+
50
+ public func replaceItem ( at index: Int , withItem item: T ) {
51
+ if leftBound == rightBound {
52
+ value = item
53
+ } else if let leftChild = leftChild, let rightChild = rightChild {
54
+ if leftChild. rightBound >= index {
55
+ leftChild. replaceItem ( at : index, withItem: item)
56
+ } else {
57
+ rightChild. replaceItem ( at : index, withItem: item)
58
+ }
59
+ value = function ( leftChild. value, rightChild. value)
60
+ }
61
+ }
62
62
}
63
63
64
64
@@ -68,72 +68,72 @@ let array = [1, 2, 3, 4]
68
68
69
69
let sumSegmentTree = SegmentTree ( array: array, function: + )
70
70
71
- print( sumSegmentTree. queryWithLeftBound ( 0 , rightBound: 3 ) ) // 1 + 2 + 3 + 4 = 10
72
- print( sumSegmentTree. queryWithLeftBound ( 1 , rightBound: 2 ) ) // 2 + 3 = 5
73
- print( sumSegmentTree. queryWithLeftBound ( 0 , rightBound: 0 ) ) // 1 = 1
71
+ print ( sumSegmentTree. query ( withLeftBound : 0 , rightBound: 3 ) ) // 1 + 2 + 3 + 4 = 10
72
+ print ( sumSegmentTree. query ( withLeftBound : 1 , rightBound: 2 ) ) // 2 + 3 = 5
73
+ print ( sumSegmentTree. query ( withLeftBound : 0 , rightBound: 0 ) ) // 1 = 1
74
74
75
- sumSegmentTree. replaceItemAtIndex ( 0 , withItem: 2 ) //our array now is [2, 2, 3, 4]
75
+ sumSegmentTree. replaceItem ( at : 0 , withItem: 2 ) //our array now is [2, 2, 3, 4]
76
76
77
- print( sumSegmentTree. queryWithLeftBound ( 0 , rightBound: 0 ) ) // 2 = 2
78
- print( sumSegmentTree. queryWithLeftBound ( 0 , rightBound: 1 ) ) // 2 + 2 = 4
77
+ print ( sumSegmentTree. query ( withLeftBound : 0 , rightBound: 0 ) ) // 2 = 2
78
+ print ( sumSegmentTree. query ( withLeftBound : 0 , rightBound: 1 ) ) // 2 + 2 = 4
79
79
80
80
81
81
//you can use any associative function (i.e (a+b)+c == a+(b+c)) as function for segment tree
82
- func gcd( m: Int, _ n: Int) - > Int {
83
- var a = 0
84
- var b = max ( m, n)
85
- var r = min ( m, n)
86
-
87
- while r != 0 {
88
- a = b
89
- b = r
90
- r = a % b
91
- }
92
- return b
82
+ func gcd( _ m: Int , _ n: Int ) -> Int {
83
+ var a = 0
84
+ var b = max ( m, n)
85
+ var r = min ( m, n)
86
+
87
+ while r != 0 {
88
+ a = b
89
+ b = r
90
+ r = a % b
91
+ }
92
+ return b
93
93
}
94
94
95
95
let gcdArray = [ 2 , 4 , 6 , 3 , 5 ]
96
96
97
97
let gcdSegmentTree = SegmentTree ( array: gcdArray, function: gcd)
98
98
99
- print( gcdSegmentTree. queryWithLeftBound ( 0 , rightBound: 1 ) ) // gcd(2, 4) = 2
100
- print( gcdSegmentTree. queryWithLeftBound ( 2 , rightBound: 3 ) ) // gcd(6, 3) = 3
101
- print( gcdSegmentTree. queryWithLeftBound ( 1 , rightBound: 3 ) ) // gcd(4, 6, 3) = 1
102
- print( gcdSegmentTree. queryWithLeftBound ( 0 , rightBound: 4 ) ) // gcd(2, 4, 6, 3, 5) = 1
99
+ print ( gcdSegmentTree. query ( withLeftBound : 0 , rightBound: 1 ) ) // gcd(2, 4) = 2
100
+ print ( gcdSegmentTree. query ( withLeftBound : 2 , rightBound: 3 ) ) // gcd(6, 3) = 3
101
+ print ( gcdSegmentTree. query ( withLeftBound : 1 , rightBound: 3 ) ) // gcd(4, 6, 3) = 1
102
+ print ( gcdSegmentTree. query ( withLeftBound : 0 , rightBound: 4 ) ) // gcd(2, 4, 6, 3, 5) = 1
103
103
104
- gcdSegmentTree. replaceItemAtIndex ( 3 , withItem: 10 ) //gcdArray now is [2, 4, 6, 10, 5]
104
+ gcdSegmentTree. replaceItem ( at : 3 , withItem: 10 ) //gcdArray now is [2, 4, 6, 10, 5]
105
105
106
- print( gcdSegmentTree. queryWithLeftBound ( 3 , rightBound: 4 ) ) // gcd(10, 5) = 5
106
+ print ( gcdSegmentTree. query ( withLeftBound : 3 , rightBound: 4 ) ) // gcd(10, 5) = 5
107
107
108
108
109
109
//example of segment tree which finds minimum on given range
110
110
let minArray = [ 2 , 4 , 1 , 5 , 3 ]
111
111
112
112
let minSegmentTree = SegmentTree ( array: minArray, function: min)
113
113
114
- print( minSegmentTree. queryWithLeftBound ( 0 , rightBound: 4 ) ) // min(2, 4, 1, 5, 3) = 1
115
- print( minSegmentTree. queryWithLeftBound ( 0 , rightBound: 1 ) ) // min(2, 4) = 2
114
+ print ( minSegmentTree. query ( withLeftBound : 0 , rightBound: 4 ) ) // min(2, 4, 1, 5, 3) = 1
115
+ print ( minSegmentTree. query ( withLeftBound : 0 , rightBound: 1 ) ) // min(2, 4) = 2
116
116
117
- minSegmentTree. replaceItemAtIndex ( 2 , withItem: 10 ) // minArray now is [2, 4, 10, 5, 3]
117
+ minSegmentTree. replaceItem ( at : 2 , withItem: 10 ) // minArray now is [2, 4, 10, 5, 3]
118
118
119
- print( minSegmentTree. queryWithLeftBound ( 0 , rightBound: 4 ) ) // min(2, 4, 10, 5, 3) = 2
119
+ print ( minSegmentTree. query ( withLeftBound : 0 , rightBound: 4 ) ) // min(2, 4, 10, 5, 3) = 2
120
120
121
121
122
122
//type of elements in array can be any type which has some associative function
123
123
let stringArray = [ " a " , " b " , " c " , " A " , " B " , " C " ]
124
124
125
125
let stringSegmentTree = SegmentTree ( array: stringArray, function: + )
126
126
127
- print( stringSegmentTree. queryWithLeftBound ( 0 , rightBound: 1 ) ) // "a"+"b" = "ab"
128
- print( stringSegmentTree. queryWithLeftBound ( 2 , rightBound: 3 ) ) // "c"+"A" = "cA"
129
- print( stringSegmentTree. queryWithLeftBound ( 1 , rightBound: 3 ) ) // "b"+"c"+"A" = "bcA"
130
- print( stringSegmentTree. queryWithLeftBound ( 0 , rightBound: 5 ) ) // "a"+"b"+"c"+"A"+"B"+"C" = "abcABC"
127
+ print ( stringSegmentTree. query ( withLeftBound : 0 , rightBound: 1 ) ) // "a"+"b" = "ab"
128
+ print ( stringSegmentTree. query ( withLeftBound : 2 , rightBound: 3 ) ) // "c"+"A" = "cA"
129
+ print ( stringSegmentTree. query ( withLeftBound : 1 , rightBound: 3 ) ) // "b"+"c"+"A" = "bcA"
130
+ print ( stringSegmentTree. query ( withLeftBound : 0 , rightBound: 5 ) ) // "a"+"b"+"c"+"A"+"B"+"C" = "abcABC"
131
131
132
- stringSegmentTree. replaceItemAtIndex ( 0 , withItem: " I " )
133
- stringSegmentTree. replaceItemAtIndex ( 1 , withItem: " like " )
134
- stringSegmentTree. replaceItemAtIndex ( 2 , withItem: " algorithms " )
135
- stringSegmentTree. replaceItemAtIndex ( 3 , withItem: " and " )
136
- stringSegmentTree. replaceItemAtIndex ( 4 , withItem: " swift " )
137
- stringSegmentTree. replaceItemAtIndex ( 5 , withItem: " ! " )
132
+ stringSegmentTree. replaceItem ( at : 0 , withItem: " I " )
133
+ stringSegmentTree. replaceItem ( at : 1 , withItem: " like " )
134
+ stringSegmentTree. replaceItem ( at : 2 , withItem: " algorithms " )
135
+ stringSegmentTree. replaceItem ( at : 3 , withItem: " and " )
136
+ stringSegmentTree. replaceItem ( at : 4 , withItem: " swift " )
137
+ stringSegmentTree. replaceItem ( at : 5 , withItem: " ! " )
138
138
139
- print( stringSegmentTree. queryWithLeftBound ( 0 , rightBound: 5 ) )
139
+ print ( stringSegmentTree. query ( withLeftBound : 0 , rightBound: 5 ) )
0 commit comments