11//: Playground - noun: a place where people can play
22
33public 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+ }
6262}
6363
6464
@@ -68,72 +68,72 @@ let array = [1, 2, 3, 4]
6868
6969let sumSegmentTree = SegmentTree ( array: array, function: + )
7070
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
7474
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]
7676
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
7979
8080
8181//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
9393}
9494
9595let gcdArray = [ 2 , 4 , 6 , 3 , 5 ]
9696
9797let gcdSegmentTree = SegmentTree ( array: gcdArray, function: gcd)
9898
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
103103
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]
105105
106- print( gcdSegmentTree. queryWithLeftBound ( 3 , rightBound: 4 ) ) // gcd(10, 5) = 5
106+ print ( gcdSegmentTree. query ( withLeftBound : 3 , rightBound: 4 ) ) // gcd(10, 5) = 5
107107
108108
109109//example of segment tree which finds minimum on given range
110110let minArray = [ 2 , 4 , 1 , 5 , 3 ]
111111
112112let minSegmentTree = SegmentTree ( array: minArray, function: min)
113113
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
116116
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]
118118
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
120120
121121
122122//type of elements in array can be any type which has some associative function
123123let stringArray = [ " a " , " b " , " c " , " A " , " B " , " C " ]
124124
125125let stringSegmentTree = SegmentTree ( array: stringArray, function: + )
126126
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"
131131
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: " ! " )
138138
139- print( stringSegmentTree. queryWithLeftBound ( 0 , rightBound: 5 ) )
139+ print ( stringSegmentTree. query ( withLeftBound : 0 , rightBound: 5 ) )
0 commit comments