├── LICENSE ├── README.md ├── [1].Swift syntax ├── README.md └── Swift syntax.playground │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ └── SunShijie.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── [2].Data structure ├── Data structure.playground │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ └── SunShijie.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── README.md ├── [3].Algorithm Introduction ├── Algorithm.playground │ ├── Contents.swift │ ├── contents.xcplayground │ └── playground.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ └── SunShijie.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── README.md ├── [4].Sort algorithms ├── README.md ├── Sort algorithms-log-version.playground │ ├── Contents.swift │ ├── Sources │ │ ├── Array+Extension.swift │ │ └── executionTimeInterval.swift │ ├── contents.xcplayground │ ├── playground.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── SunShijie.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── timeline.xctimeline └── Sort algorithms-pure-version.playground │ ├── Contents.swift │ ├── Sources │ ├── Array+Extension.swift │ └── executionTimeInterval.swift │ ├── contents.xcplayground │ ├── playground.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── SunShijie.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ └── timeline.xctimeline └── res └── logo.png /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 J_Knight_ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![](res/logo.png) 2 | 3 | 4 | ![](https://img.shields.io/badge/build-passing-brightgreen.svg) 5 | ![](https://img.shields.io/badge/Swift-%3E%3D4.0-FF7B2C.svg) 6 | 7 | 8 | ## Introduction 9 | 10 | Data structure and algorithm implementation in Swift language. 11 | 12 | 13 | 14 | ## Implementation Code 15 | 16 | All of the implementation code are in Swift playground files: 17 | 18 | 19 | 20 | **[1].Swift syntax**:Introduction of some basic Swift syntax which will be used in data structure and algorithm implementation. 21 | 22 | 23 | 24 | **[2].Data structure**: Introduction of data structure and implementation of **linked list**, **stack** and **queue**. 25 | 26 | 27 | 28 | **[3].Algorithm**: Simple algorithm implementation. 29 | 30 | 31 | 32 | **[4]:Sort Algorithms**: Swift code implementation of bubble sort, selection sort, insertion sort, merge sort and quick sort. 33 | 34 | 35 | 36 | 37 | Keep updating... 38 | 39 | 40 | 41 | ## Chinese Documents 42 | 43 | 44 | 45 | [1]. [ 数据结构 & 算法 in Swift (一):Swift基础和数据结构](https://juejin.im/post/5a7096fa6fb9a01cb64f163b) 46 | 47 | [2]. [数据结构 & 算法 in Swift (二):算法概述和排序算法](https://juejin.im/post/5a7b4101f265da4e7071b097) 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ## License 56 | 57 | All content is licensed under the terms of the [MIT open source license](https://github.com/knightsj/data-structure-and-algorithm-in-Swift/blob/master/LICENSE). 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /[1].Swift syntax/README.md: -------------------------------------------------------------------------------- 1 | # Swift Syntax 2 | 3 | 4 | 5 | Introduction of some basic Swift syntax which will be used in data structure and algorithm implementation. 6 | 7 | 8 | 9 | ## Contents 10 | 11 | 12 | 13 | 1. For loop 14 | 2. Generics 15 | 3. Guard 16 | 4. Function 17 | 5. Collection Type 18 | - Array 19 | - set 20 | - Dictionary 21 | 22 | 23 | 24 | ## For loop 25 | 26 | 27 | 28 | ```swift 29 | for index in 1...5 { 30 | print("index: \(index)") 31 | } 32 | // index : 1 33 | // index : 2 34 | // index : 3 35 | // index : 4 36 | // index : 5 37 | 38 | 39 | print("============ loop from 1 to 4:") 40 | 41 | for index in 1..<5 { 42 | print("index: \(index)") 43 | } 44 | // index : 1 45 | // index : 2 46 | // index : 3 47 | // index : 4 48 | 49 | 50 | // ===================== from large to small 51 | 52 | print("============ loop from 4 to 1:") 53 | for index in (1..<5).reversed() { 54 | print("index: \(index)") 55 | } 56 | // index : 4 57 | // index : 3 58 | // index : 2 59 | // index : 1 60 | 61 | ``` 62 | 63 | 64 | 65 | 66 | 67 | ## Generics 68 | 69 | 70 | 71 | ```swift 72 | // ===================== not using generics 73 | func swapTwoInts(_ a: inout Int, _ b: inout Int) { 74 | let tmp = a 75 | a = b 76 | b = tmp 77 | } 78 | 79 | func swapTwoStrings(_ a: inout String, _ b: inout String) { 80 | let tmp = a 81 | a = b 82 | b = tmp 83 | } 84 | 85 | func swapTwoDoubles(_ a: inout Double, _ b: inout Double) { 86 | let tmp = a 87 | a = b 88 | b = tmp 89 | } 90 | 91 | // ===================== using generics 92 | func swapTwoValues(_ a: inout T, _ b: inout T) { 93 | let tmp = a 94 | a = b 95 | b = tmp 96 | } 97 | ``` 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ## Guard 106 | 107 | ```swift 108 | //using if-else 109 | func buying1( money: Int , price: Int , capacity: Int , volume: Int){ 110 | 111 | if money >= price{ 112 | 113 | if capacity >= volume{ 114 | 115 | print("Start buying...") 116 | print("\(money-price) left after buying.") 117 | print("\(capacity-volume) capacity left") 118 | 119 | }else{ 120 | 121 | print("No enough capacity") 122 | } 123 | 124 | }else{ 125 | 126 | print("No enough money") 127 | 128 | } 129 | } 130 | 131 | 132 | //using guard 133 | func buying2( money: Int , price: Int , capacity: Int , volume: Int){ 134 | 135 | guard money >= price else{ 136 | print("No enough money") 137 | return 138 | } 139 | 140 | guard capacity >= volume else{ 141 | print("No enough capacity") 142 | return 143 | } 144 | 145 | print("\(money-price) money left.") 146 | print("\(capacity-volume) capacity left") 147 | } 148 | 149 | ``` 150 | 151 | 152 | 153 | ## Function 154 | 155 | 156 | 157 | ```swift 158 | // =========== no return value 159 | func log(message: String) { 160 | print("log: \(message)!") 161 | } 162 | 163 | log(message: "memory warning") 164 | // output: log: memory warning! 165 | 166 | 167 | // =========== has return value 168 | func logString(string: String) -> String { 169 | return "log: " + string 170 | } 171 | 172 | let logStr = logString(string: "memory warning!") 173 | print("\(logStr)") 174 | // output: log: memory warning! 175 | 176 | 177 | // =========== ignore params 178 | 179 | func logMessage(_ message: String) { 180 | print("log: \(message)!") 181 | } 182 | logMessage("memory warning") 183 | // output: log: memory warning! 184 | 185 | 186 | func addInt(_ a : Int ,_ b : Int){ 187 | print("sum is \(a + b)") 188 | } 189 | addInt(3, 4) 190 | //output : sum is 7 191 | 192 | 193 | // =========== value or reference passing 194 | var originalArr = [2,1,3] 195 | 196 | func removeLastInArray(_ array: inout [Int]){ 197 | array.removeLast() 198 | } 199 | print("\n============ before removing: \(originalArr)") 200 | //[2, 1, 3] 201 | removeLastInArray(&originalArr) 202 | print("============ after removing: \(originalArr)") 203 | //[2, 1] 204 | 205 | ``` 206 | 207 | 208 | 209 | ## Collection Type 210 | 211 | 212 | 213 | ### Array 214 | 215 | ```swift 216 | // immutable array 217 | let immutableNumbers: [Int] = [1, 3, 5, 4, 4, 1] 218 | print("============ immutable array:") 219 | print(immutableNumbers) 220 | 221 | // mutable array 222 | var mutableNumbers : [Int] = [2, 1, 5, 4, 1, 3] 223 | print("============ mutable array:") 224 | print(mutableNumbers) 225 | 226 | for value in mutableNumbers { 227 | if let index = mutableNumbers.index(of: value) { 228 | print("Index of \(value) is \(index)") 229 | } 230 | } 231 | 232 | mutableNumbers.forEach { value in 233 | if let index = mutableNumbers.index(of: value) { 234 | print("Index of \(value) is \(index)") 235 | } 236 | } 237 | 238 | for (index, value) in mutableNumbers.enumerated() { 239 | print("Item \(index + 1): \(value)") 240 | } 241 | 242 | 243 | 244 | mutableNumbers.append(11) 245 | print(mutableNumbers) 246 | // Output: [2, 1, 5, 4, 1, 3, 11] 247 | 248 | mutableNumbers.insert(42, at: 4) 249 | print(mutableNumbers) 250 | // Output: [2, 1, 5, 4, 42, 1, 3, 11] 251 | 252 | mutableNumbers.swapAt(0, 1) 253 | print(mutableNumbers) 254 | // Output: [1, 2, 5, 4, 42, 1, 3, 11] 255 | 256 | mutableNumbers.remove(at: 1) 257 | print(mutableNumbers) 258 | // Output: [1, 5, 4, 42, 1, 3, 11] 259 | 260 | mutableNumbers.removeFirst() 261 | print(mutableNumbers) 262 | // Output: [5, 4, 42, 1, 3, 11] 263 | 264 | mutableNumbers.removeLast() 265 | print(mutableNumbers) 266 | // Output: [5, 4, 42, 1, 3] 267 | 268 | 269 | mutableNumbers.removeAll() 270 | print(mutableNumbers) 271 | //[] 272 | ``` 273 | 274 | 275 | 276 | 277 | 278 | ### Set 279 | 280 | ```swift 281 | //value in set is unique 282 | let onesSet: Set = [1, 1, 1, 1] 283 | print(onesSet) 284 | // Output: [1] 285 | 286 | 287 | let onesArray: Array = [1, 1, 1, 1] 288 | print(onesArray) 289 | // Output: [1, 1, 1, 1] 290 | 291 | 292 | let numbersSet: Set = [1, 2, 3, 4, 5] 293 | print(numbersSet) 294 | // Output: undefined order, e.g. [5, 2, 3, 1, 4] 295 | 296 | 297 | // iteration 1 298 | for value in numbersSet { 299 | print(value) 300 | } 301 | // output is in undefined order 302 | 303 | 304 | // iteration 2 305 | numbersSet.forEach { value in 306 | print(value) 307 | } 308 | // output is in undefined order 309 | 310 | 311 | var mutableStringSet: Set = ["One", "Two", "Three"] 312 | let item = "Two" 313 | 314 | //contains 315 | if mutableStringSet.contains(item) { 316 | print("\(item) found in the set") 317 | } else { 318 | print("\(item) not found in the set") 319 | } 320 | 321 | //isEmpty 322 | let strings = Set() 323 | if strings.isEmpty { 324 | print("Set is empty") 325 | } 326 | 327 | //count 328 | let emptyStrings = Set() 329 | if emptyStrings.count == 0 { 330 | print("Set has no elements") 331 | } 332 | 333 | 334 | //insert 335 | mutableStringSet.insert("Four") 336 | 337 | //remove 1 338 | mutableStringSet.remove("Three") 339 | 340 | //remove 2 341 | if let removedElement = mutableStringSet.remove("Six") { 342 | print("\(removedElement) was removed from the Set") 343 | } else { 344 | print("Six is not found in the Set") 345 | } 346 | 347 | //removeAll() 348 | mutableStringSet.removeAll() 349 | // [] 350 | ``` 351 | 352 | 353 | 354 | ### Dictionary 355 | 356 | ### 357 | 358 | ```swift 359 | //empty dictionary 360 | var dayOfWeek = Dictionary() 361 | var dayOfWeek2 = [Int: String]() 362 | 363 | //not empty dictionary 364 | var dayOfWeek3: [Int: String] = [0: "Sun", 1: "Mon", 2: "Tue"] 365 | print(dayOfWeek3) 366 | //output:[2: "Tue", 0: "Sun", 1: "Mon"] 367 | 368 | 369 | 370 | // acess value 371 | dayOfWeek = [0: "Sun", 1: "Mon", 2: "Tue"] 372 | if let day = dayOfWeek[2] { 373 | print(day) 374 | } 375 | 376 | // iteration 1 377 | for (key, value) in dayOfWeek { 378 | print("\(key): \(value)") 379 | } 380 | 381 | // iteration 2 382 | for key in dayOfWeek.keys { 383 | print(key) 384 | } 385 | 386 | // iteration 3 387 | for value in dayOfWeek.values { 388 | print(value) 389 | } 390 | 391 | 392 | // addValue 1 393 | dayOfWeek[3] = "Wed" 394 | print(dayOfWeek) 395 | // Prints: [2: "Tue", 0: "Sun", 1: "Mon", 3: "Wed"] 396 | 397 | // updateValue 1 398 | dayOfWeek[2] = "Mardi" 399 | print(dayOfWeek) 400 | // Prints: [2: "Mardi", 0: "Sun", 1: "Mon", 3: "Wed"] 401 | 402 | // updateValue 2 403 | dayOfWeek.updateValue("Tue", forKey: 2) 404 | print(dayOfWeek) 405 | // Prints: [2: "Tue", 0: "Sun", 1: "Mon", 3: "Wed"] 406 | 407 | // removeValue 1 408 | dayOfWeek[1] = nil 409 | print(dayOfWeek) 410 | // Prints: [2: "Tue", 0: "Sun", 3: "Wed"] 411 | 412 | // removeValue 2 413 | dayOfWeek.removeValue(forKey: 2) 414 | print(dayOfWeek) 415 | // Prints: [0: "Sun", 3: "Wed"] 416 | 417 | // removeAll 418 | dayOfWeek.removeAll() 419 | 420 | print(dayOfWeek) 421 | // Output: [:] 422 | 423 | ``` 424 | 425 | -------------------------------------------------------------------------------- /[1].Swift syntax/Swift syntax.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | // =============================================================== 5 | // Swift syntax 6 | // =============================================================== 7 | 8 | // ===================== for loop ===================== // 9 | 10 | // ===================== from small to large 11 | 12 | print("============ loop from 1 to 5:") 13 | 14 | for index in 1...5 { 15 | print("index: \(index)") 16 | } 17 | // index : 1 18 | // index : 2 19 | // index : 3 20 | // index : 4 21 | // index : 5 22 | 23 | 24 | print("============ loop from 1 to 4:") 25 | 26 | for index in 1..<5 { 27 | print("index: \(index)") 28 | } 29 | // index : 1 30 | // index : 2 31 | // index : 3 32 | // index : 4 33 | 34 | 35 | // ===================== from large to small 36 | 37 | print("============ loop from 4 to 1:") 38 | for index in (1..<5).reversed() { 39 | print("index: \(index)") 40 | } 41 | // index : 4 42 | // index : 3 43 | // index : 2 44 | // index : 1 45 | 46 | 47 | // ===================== Generics ===================== // 48 | 49 | // ===================== not using generics 50 | func swapTwoInts(_ a: inout Int, _ b: inout Int) { 51 | let tmp = a 52 | a = b 53 | b = tmp 54 | } 55 | 56 | func swapTwoStrings(_ a: inout String, _ b: inout String) { 57 | let tmp = a 58 | a = b 59 | b = tmp 60 | } 61 | 62 | func swapTwoDoubles(_ a: inout Double, _ b: inout Double) { 63 | let tmp = a 64 | a = b 65 | b = tmp 66 | } 67 | 68 | // ===================== using generics 69 | func swapTwoValues(_ a: inout T, _ b: inout T) { 70 | let tmp = a 71 | a = b 72 | b = tmp 73 | } 74 | 75 | //var a = 1 76 | //var b = 2 77 | 78 | var a = 0.22 79 | var b = 0.11 80 | 81 | print("\n============ before swapping: a: \(a) b:\(b)") 82 | swapTwoValues(&a, &b) 83 | print("============ after swapping: a: \(a) b:\(b)") 84 | 85 | 86 | 87 | // ===================== guard syntax ===================== // 88 | 89 | 90 | //money: holding moneny 91 | //price: product price 92 | //capacity: bag capacity 93 | //volume: product size 94 | 95 | func buying1( money: Int , price: Int , capacity: Int , volume: Int){ 96 | 97 | if money >= price{ 98 | 99 | if capacity >= volume{ 100 | 101 | print("Start buying...") 102 | print("\(money-price) left after buying.") 103 | print("\(capacity-volume) capacity left") 104 | 105 | }else{ 106 | 107 | print("No enough capacity") 108 | } 109 | 110 | }else{ 111 | 112 | print("No enough money") 113 | 114 | } 115 | } 116 | 117 | 118 | func buying2( money: Int , price: Int , capacity: Int , volume: Int){ 119 | 120 | guard money >= price else{ 121 | print("No enough money") 122 | return 123 | } 124 | 125 | guard capacity >= volume else{ 126 | print("No enough capacity") 127 | return 128 | } 129 | 130 | print("\(money-price) money left.") 131 | print("\(capacity-volume) capacity left") 132 | } 133 | 134 | //implementation: 135 | //var result1 = buying1(money: 100, price: 80, capacity: 200, volume: 100) 136 | //var result2 = buying2(money: 100, price: 80, capacity: 200, volume: 100) 137 | 138 | 139 | 140 | // ===================== Function ===================== // 141 | 142 | print("\n============ function") 143 | // =========== no return value 144 | func log(message: String) { 145 | print("log: \(message)!") 146 | } 147 | 148 | log(message: "memory warning") 149 | // output: log: memory warning! 150 | 151 | 152 | // =========== has return value 153 | func logString(string: String) -> String { 154 | return "log: " + string 155 | } 156 | 157 | let logStr = logString(string: "memory warning!") 158 | print("\(logStr)") 159 | // output: log: memory warning! 160 | 161 | 162 | // =========== ignore params 163 | 164 | func logMessage(_ message: String) { 165 | print("log: \(message)!") 166 | } 167 | logMessage("memory warning") 168 | // output: log: memory warning! 169 | 170 | 171 | func addInt(_ a : Int ,_ b : Int){ 172 | print("sum is \(a + b)") 173 | } 174 | addInt(3, 4) 175 | //output : sum is 7 176 | 177 | 178 | // =========== value or reference passing 179 | var originalArr = [2,1,3] 180 | 181 | func removeLastInArray(_ array: inout [Int]){ 182 | array.removeLast() 183 | } 184 | print("\n============ before removing: \(originalArr)") 185 | //[2, 1, 3] 186 | removeLastInArray(&originalArr) 187 | print("============ after removing: \(originalArr)") 188 | //[2, 1] 189 | 190 | 191 | 192 | 193 | 194 | 195 | // ===================== collection type ===================== // 196 | 197 | 198 | 199 | // ===================== array 200 | 201 | print("\n============ array:") 202 | // immutable array 203 | let immutableNumbers: [Int] = [1, 3, 5, 4, 4, 1] 204 | print("============ immutable array:") 205 | print(immutableNumbers) 206 | 207 | // mutable array 208 | var mutableNumbers : [Int] = [2, 1, 5, 4, 1, 3] 209 | print("============ mutable array:") 210 | print(mutableNumbers) 211 | 212 | for value in mutableNumbers { 213 | if let index = mutableNumbers.index(of: value) { 214 | print("Index of \(value) is \(index)") 215 | } 216 | } 217 | 218 | mutableNumbers.forEach { value in 219 | if let index = mutableNumbers.index(of: value) { 220 | print("Index of \(value) is \(index)") 221 | } 222 | } 223 | 224 | for (index, value) in mutableNumbers.enumerated() { 225 | print("Item \(index + 1): \(value)") 226 | } 227 | 228 | 229 | 230 | mutableNumbers.append(11) 231 | print(mutableNumbers) 232 | // Output: [2, 1, 5, 4, 1, 3, 11] 233 | 234 | mutableNumbers.insert(42, at: 4) 235 | print(mutableNumbers) 236 | // Output: [2, 1, 5, 4, 42, 1, 3, 11] 237 | 238 | mutableNumbers.swapAt(0, 1) 239 | print(mutableNumbers) 240 | // Output: [1, 2, 5, 4, 42, 1, 3, 11] 241 | 242 | mutableNumbers.remove(at: 1) 243 | print(mutableNumbers) 244 | // Output: [1, 5, 4, 42, 1, 3, 11] 245 | 246 | mutableNumbers.removeFirst() 247 | print(mutableNumbers) 248 | // Output: [5, 4, 42, 1, 3, 11] 249 | 250 | mutableNumbers.removeLast() 251 | print(mutableNumbers) 252 | // Output: [5, 4, 42, 1, 3] 253 | 254 | 255 | mutableNumbers.removeAll() 256 | print(mutableNumbers) 257 | //[] 258 | 259 | 260 | // ===================== set 261 | 262 | print("\n============ set:") 263 | 264 | //value in set is unique 265 | let onesSet: Set = [1, 1, 1, 1] 266 | print(onesSet) 267 | // Output: [1] 268 | 269 | 270 | let onesArray: Array = [1, 1, 1, 1] 271 | print(onesArray) 272 | // Output: [1, 1, 1, 1] 273 | 274 | 275 | let numbersSet: Set = [1, 2, 3, 4, 5] 276 | print(numbersSet) 277 | // Output: undefined order, e.g. [5, 2, 3, 1, 4] 278 | 279 | 280 | // iteration 1 281 | for value in numbersSet { 282 | print(value) 283 | } 284 | // output is in undefined order 285 | 286 | 287 | // iteration 2 288 | numbersSet.forEach { value in 289 | print(value) 290 | } 291 | // output is in undefined order 292 | 293 | 294 | var mutableStringSet: Set = ["One", "Two", "Three"] 295 | let item = "Two" 296 | 297 | //contains 298 | if mutableStringSet.contains(item) { 299 | print("\(item) found in the set") 300 | } else { 301 | print("\(item) not found in the set") 302 | } 303 | 304 | //isEmpty 305 | let strings = Set() 306 | if strings.isEmpty { 307 | print("Set is empty") 308 | } 309 | 310 | //count 311 | let emptyStrings = Set() 312 | if emptyStrings.count == 0 { 313 | print("Set has no elements") 314 | } 315 | 316 | 317 | //insert 318 | mutableStringSet.insert("Four") 319 | 320 | //remove 1 321 | mutableStringSet.remove("Three") 322 | 323 | //remove 2 324 | if let removedElement = mutableStringSet.remove("Six") { 325 | print("\(removedElement) was removed from the Set") 326 | } else { 327 | print("Six is not found in the Set") 328 | } 329 | 330 | //removeAll() 331 | mutableStringSet.removeAll() 332 | // [] 333 | 334 | 335 | 336 | // ===================== dictionary 337 | 338 | print("\n============ dictionary:") 339 | 340 | 341 | 342 | //empty dictionary 343 | var dayOfWeek = Dictionary() 344 | var dayOfWeek2 = [Int: String]() 345 | 346 | //not empty dictionary 347 | var dayOfWeek3: [Int: String] = [0: "Sun", 1: "Mon", 2: "Tue"] 348 | print(dayOfWeek3) 349 | //output:[2: "Tue", 0: "Sun", 1: "Mon"] 350 | 351 | 352 | 353 | // acess value 354 | dayOfWeek = [0: "Sun", 1: "Mon", 2: "Tue"] 355 | if let day = dayOfWeek[2] { 356 | print(day) 357 | } 358 | 359 | // iteration 1 360 | for (key, value) in dayOfWeek { 361 | print("\(key): \(value)") 362 | } 363 | 364 | // iteration 2 365 | for key in dayOfWeek.keys { 366 | print(key) 367 | } 368 | 369 | // iteration 3 370 | for value in dayOfWeek.values { 371 | print(value) 372 | } 373 | 374 | 375 | // addValue 1 376 | dayOfWeek[3] = "Wed" 377 | print(dayOfWeek) 378 | // Prints: [2: "Tue", 0: "Sun", 1: "Mon", 3: "Wed"] 379 | 380 | // updateValue 1 381 | dayOfWeek[2] = "Mardi" 382 | print(dayOfWeek) 383 | // Prints: [2: "Mardi", 0: "Sun", 1: "Mon", 3: "Wed"] 384 | 385 | // updateValue 2 386 | dayOfWeek.updateValue("Tue", forKey: 2) 387 | print(dayOfWeek) 388 | // Prints: [2: "Tue", 0: "Sun", 1: "Mon", 3: "Wed"] 389 | 390 | // removeValue 1 391 | dayOfWeek[1] = nil 392 | print(dayOfWeek) 393 | // Prints: [2: "Tue", 0: "Sun", 3: "Wed"] 394 | 395 | // removeValue 2 396 | dayOfWeek.removeValue(forKey: 2) 397 | print(dayOfWeek) 398 | // Prints: [0: "Sun", 3: "Wed"] 399 | 400 | // removeAll 401 | dayOfWeek.removeAll() 402 | 403 | print(dayOfWeek) 404 | // Output: [:] 405 | 406 | 407 | 408 | -------------------------------------------------------------------------------- /[1].Swift syntax/Swift syntax.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /[1].Swift syntax/Swift syntax.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /[1].Swift syntax/Swift syntax.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knightsj/data-structure-and-algorithm-in-Swift/1a4ba59529dee19c707f1b278e3bcd70ec8e677e/[1].Swift syntax/Swift syntax.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /[2].Data structure/Data structure.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | // =============================================================== 5 | // Data Structure 6 | // =============================================================== 7 | 8 | // ===================== linked list ===================== // 9 | 10 | 11 | public class LinkedListNode { 12 | 13 | 14 | var value: T 15 | var next: LinkedListNode? 16 | weak var previous: LinkedListNode? 17 | 18 | public init(value: T) { 19 | self.value = value 20 | } 21 | } 22 | 23 | public class LinkedList { 24 | 25 | public typealias Node = LinkedListNode 26 | 27 | public var isEmpty: Bool { 28 | 29 | return head == nil 30 | } 31 | 32 | public var count: Int { 33 | 34 | guard var node = head else { 35 | return 0 36 | } 37 | 38 | var count = 1 39 | while let next = node.next { 40 | node = next 41 | count += 1 42 | } 43 | return count 44 | } 45 | 46 | private var head: Node? 47 | 48 | public var first: Node? { 49 | return head 50 | } 51 | 52 | public var last: Node? { 53 | 54 | guard var node = head else { 55 | return nil 56 | } 57 | 58 | //until node.next is nil 59 | while let next = node.next { 60 | node = next 61 | } 62 | return node 63 | } 64 | 65 | //get node of index 66 | public func node(atIndex index: Int) -> Node? { 67 | 68 | if index == 0 { 69 | //head node 70 | return head! 71 | 72 | } else { 73 | 74 | var node = head!.next 75 | 76 | guard index < count else { 77 | return nil; 78 | } 79 | 80 | for _ in 1.. count { 156 | 157 | print("out of range") 158 | return 159 | 160 | } 161 | 162 | let prev = self.node(atIndex: index-1) 163 | let next = prev?.next 164 | 165 | newNode.previous = prev 166 | newNode.next = prev?.next 167 | prev?.next = newNode 168 | next?.previous = newNode 169 | } 170 | 171 | } 172 | } 173 | 174 | //removing all nodes 175 | public func removeAll() { 176 | head = nil 177 | } 178 | 179 | //remove the last node 180 | public func removeLast() -> T? { 181 | 182 | guard !isEmpty else { 183 | return nil 184 | } 185 | 186 | return remove(node: last!) 187 | } 188 | 189 | //remove a node by it's refrence 190 | public func remove(node: Node) -> T? { 191 | 192 | guard head != nil else { 193 | print("linked list is empty") 194 | return nil 195 | } 196 | 197 | let prev = node.previous 198 | let next = node.next 199 | 200 | if let prev = prev { 201 | prev.next = next 202 | } else { 203 | head = next 204 | } 205 | 206 | next?.previous = prev 207 | 208 | node.previous = nil 209 | node.next = nil 210 | return node.value 211 | } 212 | 213 | 214 | //remove a node by it's index 215 | public func removeAt(_ index: Int) -> T? { 216 | 217 | guard head != nil else { 218 | print("linked list is empty") 219 | return nil 220 | } 221 | 222 | let node = self.node(atIndex: index) 223 | guard node != nil else { 224 | return nil 225 | } 226 | return remove(node: node!) 227 | } 228 | 229 | 230 | public func printAllNodes(){ 231 | 232 | guard head != nil else { 233 | print("linked list is empty") 234 | return 235 | } 236 | 237 | var node = head 238 | 239 | print("\nstart printing all nodes:") 240 | 241 | for index in 0..() 258 | list.isEmpty // true 259 | list.first // nil 260 | list.count // 0 261 | 262 | list.appendToTail(value: "Swift") 263 | list.isEmpty // false 264 | list.first!.value // "Swift" 265 | list.last!.value // "Swift" 266 | list.count 267 | 268 | list.appendToTail(value:"is") 269 | list.first!.value // "Swift" 270 | list.last!.value // "is" 271 | list.count 272 | 273 | list.appendToTail(value:"great") 274 | list.first!.value // "Swift" 275 | list.last!.value // "great" 276 | list.count // 3 277 | 278 | 279 | list.printAllNodes() 280 | //[0]Swift 281 | //[1]is 282 | //[2]Great 283 | 284 | list.node(atIndex: 0)?.value // Swift 285 | list.node(atIndex: 1)?.value // is 286 | list.node(atIndex: 2)?.value // great 287 | list.node(atIndex: 3)?.value // nil 288 | 289 | 290 | list.insert(LinkedListNode.init(value: "language"), atIndex: 1) 291 | list.printAllNodes() 292 | //[0]Swift 293 | //[1]language 294 | //[2]is 295 | //[3]great 296 | 297 | 298 | list.remove(node: list.first!) 299 | list.printAllNodes() 300 | //[0]language 301 | //[1]is 302 | //[2]great 303 | 304 | 305 | list.removeAt(1) 306 | list.printAllNodes() 307 | //[0]language 308 | //[1]great 309 | 310 | 311 | list.removeLast() 312 | list.printAllNodes() 313 | //[0]language 314 | 315 | list.insertToHead(value: "study") 316 | list.count // 2 317 | list.printAllNodes() 318 | //[0]study 319 | //[1]language 320 | 321 | 322 | list.removeAll() 323 | list.printAllNodes()//linked list is empty 324 | 325 | list.insert(LinkedListNode.init(value: "new"), atIndex: 3) 326 | list.printAllNodes() 327 | //[0]new 328 | 329 | list.insert(LinkedListNode.init(value: "new"), atIndex: 3) //out of range 330 | list.printAllNodes() 331 | //[0]new 332 | 333 | list.insert(LinkedListNode.init(value: "new"), atIndex: 1) 334 | list.printAllNodes() 335 | //[0]new 336 | //[1]new 337 | 338 | 339 | 340 | 341 | 342 | // ===================== stack ===================== // 343 | 344 | public struct Stack { 345 | 346 | //array 347 | fileprivate var stackArray = [T]() 348 | 349 | //count 350 | public var count: Int { 351 | return stackArray.count 352 | } 353 | 354 | //is empty ? 355 | public var isEmpty: Bool { 356 | return stackArray.isEmpty 357 | } 358 | 359 | //top element 360 | public var top: T? { 361 | 362 | if isEmpty{ 363 | return nil 364 | }else { 365 | return stackArray.last 366 | } 367 | 368 | } 369 | 370 | //push operation 371 | public mutating func push(_ element: T) { 372 | stackArray.append(element) 373 | } 374 | 375 | 376 | //pop operation 377 | public mutating func pop() -> T? { 378 | 379 | if isEmpty{ 380 | print("stack is empty") 381 | return nil 382 | }else { 383 | return stackArray.removeLast() 384 | } 385 | } 386 | 387 | //print all 388 | public mutating func printAllElements() { 389 | 390 | guard count > 0 else { 391 | print("stack is empty") 392 | return 393 | } 394 | 395 | print("\nprint all stack elemets:") 396 | for (index, value) in stackArray.enumerated() { 397 | print("[\(index)]\(value)") 398 | } 399 | } 400 | } 401 | 402 | var stack = Stack.init(stackArray: []) 403 | stack.printAllElements() //stack is empty 404 | stack.isEmpty //true 405 | 406 | stack.push(2) 407 | stack.printAllElements() 408 | //[0]2 409 | 410 | stack.isEmpty //false 411 | stack.top //2 412 | 413 | 414 | stack.push(3) 415 | stack.printAllElements() 416 | //[0]2 417 | //[1]3 418 | 419 | stack.isEmpty //false 420 | stack.top //3 421 | 422 | 423 | 424 | stack.pop() 425 | stack.printAllElements() 426 | //[0]2 427 | 428 | stack.isEmpty //false 429 | stack.top //2 430 | 431 | 432 | stack.pop() 433 | stack.printAllElements() //stack is empty 434 | stack.top //nil 435 | stack.isEmpty //true 436 | 437 | stack.pop() //stack is empty 438 | 439 | 440 | 441 | 442 | // ===================== queue ===================== // 443 | 444 | 445 | public struct Queue { 446 | 447 | //array 448 | fileprivate var queueArray = [T]() 449 | 450 | 451 | //count 452 | public var count: Int { 453 | return queueArray.count 454 | } 455 | 456 | 457 | //is empty? 458 | public var isEmpty: Bool { 459 | return queueArray.isEmpty 460 | } 461 | 462 | 463 | //front element 464 | public var front: T? { 465 | 466 | if isEmpty { 467 | print("queue is empty") 468 | return nil 469 | } else { 470 | return queueArray.first 471 | } 472 | } 473 | 474 | 475 | //add element 476 | public mutating func enqueue(_ element: T) { 477 | queueArray.append(element) 478 | } 479 | 480 | 481 | //remove element 482 | public mutating func dequeue() -> T? { 483 | if isEmpty { 484 | print("queue is empty") 485 | return nil 486 | } else { 487 | return queueArray.removeFirst() 488 | } 489 | } 490 | 491 | //print all 492 | public mutating func printAllElements() { 493 | 494 | guard count > 0 else { 495 | print("queue is empty") 496 | return 497 | } 498 | 499 | print("\nprint all queue elemets:") 500 | for (index, value) in queueArray.enumerated() { 501 | print("[\(index)]\(value)") 502 | } 503 | } 504 | 505 | } 506 | 507 | 508 | var queue = Queue.init(queueArray: []) 509 | queue.printAllElements()//queue is empty 510 | queue.isEmpty //true 511 | queue.count //0 512 | 513 | 514 | queue.enqueue(2) 515 | queue.printAllElements() 516 | queue.isEmpty //false 517 | //[0]2 518 | 519 | queue.enqueue(3) 520 | queue.printAllElements() 521 | //[0]2 522 | //[1]3 523 | 524 | 525 | queue.enqueue(4) 526 | queue.printAllElements() 527 | //[0]2 528 | //[1]3 529 | //[2]4 530 | 531 | queue.front //2 532 | 533 | 534 | 535 | queue.dequeue() 536 | queue.printAllElements() 537 | //[0]3 538 | //[1]4 539 | 540 | queue.front //3 541 | 542 | 543 | queue.dequeue() 544 | queue.printAllElements() 545 | //[0]4 546 | queue.front //4 547 | 548 | queue.dequeue() 549 | queue.printAllElements() //queue is empty 550 | 551 | 552 | queue.front //return nil, and print : queue is empty 553 | queue.isEmpty //true 554 | queue.count//0 555 | 556 | 557 | 558 | 559 | 560 | 561 | -------------------------------------------------------------------------------- /[2].Data structure/Data structure.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /[2].Data structure/Data structure.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /[2].Data structure/Data structure.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knightsj/data-structure-and-algorithm-in-Swift/1a4ba59529dee19c707f1b278e3bcd70ec8e677e/[2].Data structure/Data structure.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /[2].Data structure/README.md: -------------------------------------------------------------------------------- 1 | # Data Structure 2 | 3 | 4 | 5 | Swift implementation of linked list, stack and queue. 6 | 7 | 8 | 9 | ## Linked list 10 | 11 | 12 | 13 | ```swift 14 | public class LinkedListNode { 15 | 16 | 17 | var value: T 18 | var next: LinkedListNode? 19 | weak var previous: LinkedListNode? 20 | 21 | public init(value: T) { 22 | self.value = value 23 | } 24 | } 25 | 26 | public class LinkedList { 27 | 28 | public typealias Node = LinkedListNode 29 | 30 | public var isEmpty: Bool { 31 | 32 | return head == nil 33 | } 34 | 35 | public var count: Int { 36 | 37 | guard var node = head else { 38 | return 0 39 | } 40 | 41 | var count = 1 42 | while let next = node.next { 43 | node = next 44 | count += 1 45 | } 46 | return count 47 | } 48 | 49 | private var head: Node? 50 | 51 | public var first: Node? { 52 | return head 53 | } 54 | 55 | public var last: Node? { 56 | 57 | guard var node = head else { 58 | return nil 59 | } 60 | 61 | //until node.next is nil 62 | while let next = node.next { 63 | node = next 64 | } 65 | return node 66 | } 67 | 68 | //get node of index 69 | public func node(atIndex index: Int) -> Node? { 70 | 71 | if index == 0 { 72 | //head node 73 | return head! 74 | 75 | } else { 76 | 77 | var node = head!.next 78 | 79 | guard index < count else { 80 | return nil; 81 | } 82 | 83 | for _ in 1.. count { 159 | 160 | print("out of range") 161 | return 162 | 163 | } 164 | 165 | let prev = self.node(atIndex: index-1) 166 | let next = prev?.next 167 | 168 | newNode.previous = prev 169 | newNode.next = prev?.next 170 | prev?.next = newNode 171 | next?.previous = newNode 172 | } 173 | 174 | } 175 | } 176 | 177 | //removing all nodes 178 | public func removeAll() { 179 | head = nil 180 | } 181 | 182 | //remove the last node 183 | public func removeLast() -> T? { 184 | 185 | guard !isEmpty else { 186 | return nil 187 | } 188 | 189 | return remove(node: last!) 190 | } 191 | 192 | //remove a node by it's refrence 193 | public func remove(node: Node) -> T? { 194 | 195 | guard head != nil else { 196 | print("linked list is empty") 197 | return nil 198 | } 199 | 200 | let prev = node.previous 201 | let next = node.next 202 | 203 | if let prev = prev { 204 | prev.next = next 205 | } else { 206 | head = next 207 | } 208 | 209 | next?.previous = prev 210 | 211 | node.previous = nil 212 | node.next = nil 213 | return node.value 214 | } 215 | 216 | 217 | //remove a node by it's index 218 | public func removeAt(_ index: Int) -> T? { 219 | 220 | guard head != nil else { 221 | print("linked list is empty") 222 | return nil 223 | } 224 | 225 | let node = self.node(atIndex: index) 226 | guard node != nil else { 227 | return nil 228 | } 229 | return remove(node: node!) 230 | } 231 | 232 | 233 | public func printAllNodes(){ 234 | 235 | guard head != nil else { 236 | print("linked list is empty") 237 | return 238 | } 239 | 240 | var node = head 241 | 242 | print("\nstart printing all nodes:") 243 | 244 | for index in 0.. { 266 | 267 | //array 268 | fileprivate var stackArray = [T]() 269 | 270 | //count 271 | public var count: Int { 272 | return stackArray.count 273 | } 274 | 275 | //is empty ? 276 | public var isEmpty: Bool { 277 | return stackArray.isEmpty 278 | } 279 | 280 | //top element 281 | public var top: T? { 282 | 283 | if isEmpty{ 284 | return nil 285 | }else { 286 | return stackArray.last 287 | } 288 | 289 | } 290 | 291 | //push operation 292 | public mutating func push(_ element: T) { 293 | stackArray.append(element) 294 | } 295 | 296 | 297 | //pop operation 298 | public mutating func pop() -> T? { 299 | 300 | if isEmpty{ 301 | print("stack is empty") 302 | return nil 303 | }else { 304 | return stackArray.removeLast() 305 | } 306 | } 307 | 308 | //print all 309 | public mutating func printAllElements() { 310 | 311 | guard count > 0 else { 312 | print("stack is empty") 313 | return 314 | } 315 | 316 | print("\nprint all stack elemets:") 317 | for (index, value) in stackArray.enumerated() { 318 | print("[\(index)]\(value)") 319 | } 320 | } 321 | } 322 | ``` 323 | 324 | 325 | 326 | ## Queue 327 | 328 | ```swift 329 | public struct Queue { 330 | 331 | //array 332 | fileprivate var queueArray = [T]() 333 | 334 | 335 | //count 336 | public var count: Int { 337 | return queueArray.count 338 | } 339 | 340 | 341 | //is empty? 342 | public var isEmpty: Bool { 343 | return queueArray.isEmpty 344 | } 345 | 346 | 347 | //front element 348 | public var front: T? { 349 | 350 | if isEmpty { 351 | print("queue is empty") 352 | return nil 353 | } else { 354 | return queueArray.first 355 | } 356 | } 357 | 358 | 359 | //add element 360 | public mutating func enqueue(_ element: T) { 361 | queueArray.append(element) 362 | } 363 | 364 | 365 | //remove element 366 | public mutating func dequeue() -> T? { 367 | if isEmpty { 368 | print("queue is empty") 369 | return nil 370 | } else { 371 | return queueArray.removeFirst() 372 | } 373 | } 374 | 375 | //print all 376 | public mutating func printAllElements() { 377 | 378 | guard count > 0 else { 379 | print("queue is empty") 380 | return 381 | } 382 | 383 | print("\nprint all queue elemets:") 384 | for (index, value) in queueArray.enumerated() { 385 | print("[\(index)]\(value)") 386 | } 387 | } 388 | 389 | } 390 | ``` 391 | 392 | -------------------------------------------------------------------------------- /[3].Algorithm Introduction/Algorithm.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | // =============== sum =============== 4 | 5 | // O(n) 6 | func sumOpration1(_ n:Int) -> Int{ 7 | 8 | var sum = 0 9 | 10 | for i in 1 ... n { 11 | sum += i 12 | } 13 | 14 | return sum 15 | } 16 | sumOpration1(100)//5050 17 | 18 | 19 | // O(1) 20 | func sumOpration2(_ n:Int) -> Int{ 21 | 22 | return (1 + n) * n/2 23 | } 24 | 25 | 26 | 27 | sumOpration2(100)//5050 28 | 29 | 30 | //O(n ^ 2) 31 | func findTwoSum(_ array: [Int], target: Int) -> (Int, Int)? { 32 | 33 | guard array.count > 1 else { 34 | return nil 35 | } 36 | 37 | for i in 0.. (Int, Int)? { 62 | 63 | guard array.count > 1 else { 64 | return nil 65 | } 66 | 67 | var diffs = Dictionary() 68 | 69 | for i in 0.. Int{ 93 | return n < 2 ? 1: n * factorial(n-1) 94 | } 95 | 96 | factorial(3) //6 97 | factorial(4) //24 98 | 99 | 100 | // bad recursion - > stack overflow 101 | func factorialInfinite(_ n:Int) -> Int{ 102 | return n * factorialInfinite(n-1) 103 | } 104 | 105 | //factorialInfinite(3) 106 | 107 | // bad recursion - > stack overflow 108 | func sumOperation( _ n:Int) -> Int { 109 | if n == 0 { 110 | return 0 111 | } 112 | return n + sumOperation(n - 1) 113 | } 114 | 115 | sumOperation(2) //0 116 | //sumOperation(-1) //stack overflow 117 | 118 | 119 | 120 | // good recursion 121 | func sumOperation1( _ n:Int) -> Int { 122 | if n <= 0 { 123 | return 0 124 | } 125 | return n + sumOperation1(n - 1) 126 | } 127 | 128 | sumOperation1(-1) //0 129 | 130 | -------------------------------------------------------------------------------- /[3].Algorithm Introduction/Algorithm.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /[3].Algorithm Introduction/Algorithm.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /[3].Algorithm Introduction/Algorithm.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knightsj/data-structure-and-algorithm-in-Swift/1a4ba59529dee19c707f1b278e3bcd70ec8e677e/[3].Algorithm Introduction/Algorithm.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /[3].Algorithm Introduction/README.md: -------------------------------------------------------------------------------- 1 | # Algorithm Introduction 2 | 3 | 4 | 5 | Simple algorithm implementation. 6 | 7 | 8 | 9 | ## Sum operation 10 | 11 | ```swift 12 | // O(n) 13 | func sumOpration1(_ n:Int) -> Int{ 14 | 15 | var sum = 0 16 | 17 | for i in 1 ... n { 18 | sum += i 19 | } 20 | 21 | return sum 22 | } 23 | sumOpration1(100)//5050 24 | 25 | 26 | // O(1) 27 | func sumOpration2(_ n:Int) -> Int{ 28 | 29 | return (1 + n) * n/2 30 | } 31 | 32 | ``` 33 | 34 | 35 | 36 | ## Two Sum 37 | 38 | ```swift 39 | //O(n^2) 40 | func findTwoSum(_ array: [Int], target: Int) -> (Int, Int)? { 41 | 42 | guard array.count > 1 else { 43 | return nil 44 | } 45 | 46 | for i in 0.. (Int, Int)? { 63 | 64 | guard array.count > 1 else { 65 | return nil 66 | } 67 | 68 | var diffs = Dictionary() 69 | 70 | for i in 0.. Int{ 97 | return n < 2 ? 1: n * factorial(n-1) 98 | } 99 | 100 | 101 | // bad recursion - > stack overflow 102 | func factorialInfinite(_ n:Int) -> Int{ 103 | return n * factorialInfinite(n-1) 104 | } 105 | ``` 106 | 107 | 108 | 109 | #### Example 2 110 | 111 | ```swift 112 | // bad recursion - > stack overflow 113 | func sumOperation( _ n:Int) -> Int { 114 | if n == 0 { 115 | return 0 116 | } 117 | return n + sumOperation(n - 1) 118 | } 119 | 120 | sumOperation(2) //0 121 | //sumOperation(-1) //stack overflow 122 | 123 | 124 | 125 | // good recursion 126 | func sumOperation1( _ n:Int) -> Int { 127 | if n <= 0 { 128 | return 0 129 | } 130 | return n + sumOperation1(n - 1) 131 | } 132 | ``` 133 | 134 | -------------------------------------------------------------------------------- /[4].Sort algorithms/README.md: -------------------------------------------------------------------------------- 1 | # Sort Algorithms 2 | 3 | 4 | 5 | Swift code implementation of bubble sort, selection sort, insertion sort, merge sort and quick sort. 6 | 7 | 8 | 9 | ## Bubble Sort 10 | 11 | ```swift 12 | func bubbleSort(_ array: inout [Int]) -> [Int] { 13 | 14 | guard array.count > 1 else { return array } 15 | 16 | for i in 0 ..< array.count - 1 { 17 | 18 | for j in 0 ..< array.count - 1 - i { 19 | 20 | if array[j] > array[j+1] { 21 | array.swapAt(j, j+1) //keeping index of j is the smaller one 22 | 23 | } 24 | } 25 | } 26 | return array 27 | } 28 | ``` 29 | 30 | 31 | 32 | ## Advanced Bubble Sort 33 | 34 | ```swift 35 | func bubbleSortAdvanced(_ array: inout [Int]) -> [Int] { 36 | 37 | guard array.count > 1 else { return array } 38 | 39 | for i in 0 ..< array.count - 1 { 40 | 41 | var swapped = false 42 | for j in 0 ..< array.count - i - 1 { 43 | 44 | if array[j] > array [j+1] { 45 | array.swapAt(j, j+1) //keeping index of j is the smaller one 46 | swapped = true; 47 | } 48 | } 49 | 50 | //if there is no swapping in inner loop, it means the the part looped is already sorted, 51 | //so its time to break 52 | if (swapped == false){ break } 53 | } 54 | return array 55 | 56 | } 57 | ``` 58 | 59 | 60 | 61 | 62 | 63 | ## Selection Sort 64 | 65 | ```swift 66 | func selectionSort(_ array: inout [Int]) -> [Int] { 67 | 68 | guard array.count > 1 else { return array } 69 | 70 | // var count = 0 71 | var compare = 0 72 | //move boundary of unsorted subarray 73 | for i in 0 ..< array.count - 1{ 74 | 75 | var min = i 76 | 77 | // find the minimum element in unsorted array 78 | for j in i + 1 ..< array.count { 79 | compare += 1 80 | 81 | if array[j] < array[min] { 82 | min = j //update the minimum value index 83 | } 84 | } 85 | 86 | //if min has changed, it means there is value smaller than array[min] 87 | //if min has not changed, it means there is no value smallter than array[min] 88 | if i != min { 89 | array.swapAt(i, min) //exchange the minimum value index with current index 90 | } 91 | 92 | 93 | } 94 | return array 95 | } 96 | ``` 97 | 98 | 99 | 100 | 101 | 102 | ## Insertion Sort 103 | 104 | ```swift 105 | func insertionSort(_ array: inout [Int]) -> [Int] { 106 | 107 | guard array.count > 1 else { return array } 108 | 109 | for i in 1.. 0 && array[j] < array[j - 1] { 114 | array.swapAt(j - 1, j) 115 | j -= 1 116 | } 117 | } 118 | return array 119 | } 120 | ``` 121 | 122 | 123 | 124 | 125 | 126 | ## Merge sort 127 | 128 | ```swift 129 | func mergeSort(_ array: [Int]) -> [Int] { 130 | 131 | guard array.count > 1 else { return array } 132 | 133 | let middleIndex = array.count / 2 134 | let leftArray = mergeSort(Array(array[0.. [Int] { 144 | 145 | var leftIndex = 0 //left pile index, start from 0 146 | var rightIndex = 0 //right pile index, start from 0 147 | 148 | 149 | var sortedPile = [Int]() //sorted pile, empty in the first place 150 | 151 | 152 | while leftIndex < leftPile.count && rightIndex < rightPile.count { 153 | 154 | //append the smaller value into sortedPile 155 | if leftPile[leftIndex] < rightPile[rightIndex] { 156 | 157 | sortedPile.append(leftPile[leftIndex]) 158 | leftIndex += 1 159 | 160 | } else if leftPile[leftIndex] > rightPile[rightIndex] { 161 | 162 | sortedPile.append(rightPile[rightIndex]) 163 | rightIndex += 1 164 | 165 | } else { 166 | 167 | //same value, append both of them and move the corresponding index 168 | sortedPile.append(leftPile[leftIndex]) 169 | leftIndex += 1 170 | sortedPile.append(rightPile[rightIndex]) 171 | rightIndex += 1 172 | } 173 | } 174 | 175 | 176 | //left pile is not empty 177 | while leftIndex < leftPile.count { 178 | sortedPile.append(leftPile[leftIndex]) 179 | leftIndex += 1 180 | } 181 | 182 | //right pile is not empty 183 | while rightIndex < rightPile.count { 184 | sortedPile.append(rightPile[rightIndex]) 185 | rightIndex += 1 186 | } 187 | 188 | // print("sorted pile:\(sortedPile)") 189 | return sortedPile 190 | } 191 | ``` 192 | 193 | 194 | 195 | ## Quick Sort 196 | 197 | 198 | 199 | #### Quick sort with swift filter function 200 | 201 | option1: 202 | 203 | ```swift 204 | func quickSort0(_ array: [Int]) -> [Int] { 205 | 206 | guard array.count > 1 else { return array } 207 | 208 | let pivot = array[array.count/2] 209 | let less = array.filter { $0 < pivot } 210 | let greater = array.filter { $0 > pivot } 211 | 212 | return quickSort0(less) + quickSort0(greater) 213 | } 214 | ``` 215 | 216 | 217 | 218 | option2: 219 | 220 | ```swift 221 | func quicksort(_ array: [Int]) -> [Int] { 222 | 223 | guard array.count > 1 else { return array } 224 | 225 | let pivot = array[array.count/2] 226 | let less = array.filter { $0 < pivot } 227 | let equal = array.filter { $0 == pivot } 228 | let greater = array.filter { $0 > pivot } 229 | 230 | return quicksort(less) + equal + quicksort(greater) 231 | } 232 | 233 | ``` 234 | 235 | 236 | 237 | 238 | 239 | #### Fixed index of pivot 240 | 241 | ```swift 242 | func _partition(_ array: inout [Int], low: Int, high: Int) -> Int{ 243 | 244 | var low = low 245 | var high = high 246 | 247 | let pivotValue = array[low] 248 | 249 | while low < high { 250 | 251 | while low < high && array[high] >= pivotValue { 252 | high -= 1 253 | } 254 | array[low] = array[high] 255 | 256 | while low < high && array[low] <= pivotValue { 257 | low += 1 258 | } 259 | array[high] = array[low] 260 | } 261 | 262 | array[low] = pivotValue 263 | 264 | return low 265 | } 266 | 267 | 268 | 269 | func quickSort1(_ array: inout [Int], low: Int, high: Int){ 270 | 271 | guard array.count > 1 else { return } 272 | 273 | if low < high { 274 | 275 | //pivote index is low 276 | let pivotIndex = _partition(&array, low: low, high: high) 277 | 278 | quickSort1(&array, low: low, high: pivotIndex - 1) 279 | quickSort1(&array, low: pivotIndex + 1, high: high) 280 | } 281 | 282 | } 283 | ``` 284 | 285 | 286 | 287 | #### Random index of pivot 288 | 289 | ```swift 290 | func _partitionRandom(_ array: inout [Int], low: Int, high: Int) -> Int{ 291 | 292 | 293 | let x = UInt32(low) 294 | let y = UInt32(high) 295 | 296 | let pivotIndex = Int(arc4random() % (y - x)) + Int(x) 297 | let pivotValue = array[pivotIndex] 298 | 299 | 300 | var low = low 301 | var high = high 302 | 303 | while low < high { 304 | 305 | while low < high && array[high] >= pivotValue { 306 | high -= 1 307 | } 308 | array[low] = array[high] 309 | 310 | while low < high && array[low] <= pivotValue { 311 | low += 1 312 | } 313 | 314 | array[high] = array[low] 315 | } 316 | 317 | array[low] = pivotValue 318 | 319 | return low 320 | } 321 | 322 | 323 | func quickSort2(_ array: inout [Int], low: Int, high: Int){ 324 | 325 | guard array.count > 1 else { return } 326 | 327 | if low < high { 328 | 329 | //pivote index is random 330 | let pivotIndex = _partitionRandom(&array, low: low, high: high) 331 | quickSort2(&array, low: low, high: pivotIndex - 1) 332 | quickSort2(&array, low: pivotIndex + 1, high: high) 333 | } 334 | 335 | } 336 | ``` 337 | 338 | 339 | 340 | 341 | 342 | #### 3-way quick sort 343 | 344 | ```swift 345 | //only for swapping two elements in array 346 | func swap(_ arr: inout [Int], _ j: Int, _ k: Int) { 347 | 348 | guard j != k else { 349 | return; 350 | } 351 | 352 | let temp = arr[j] 353 | arr[j] = arr[k] 354 | arr[k] = temp 355 | } 356 | 357 | 358 | func quickSort3W(_ array: inout [Int], low: Int, high: Int) { 359 | 360 | if high <= low { return } 361 | 362 | var lt = low // arr[low+1...lt] < v 363 | var gt = high + 1 // arr[gt...high] > v 364 | var i = low + 1 // arr[lt+1...i) == v 365 | 366 | let pivoteIndex = low 367 | let pivoteValue = array[pivoteIndex] 368 | 369 | while i < gt { 370 | 371 | if array[i] < pivoteValue { 372 | 373 | swap(&array, i, lt + 1) 374 | i += 1 375 | lt += 1 376 | 377 | }else if pivoteValue < array[i]{ 378 | 379 | swap(&array, i, gt - 1) 380 | gt -= 1 381 | 382 | }else { 383 | i += 1 384 | } 385 | } 386 | 387 | swap(&array, low, lt) 388 | quickSort3W(&array, low: low, high: lt - 1) 389 | quickSort3W(&array, low: gt, high: high) 390 | 391 | 392 | } 393 | 394 | 395 | func quickSort3(_ array: inout [Int] ){ 396 | 397 | quickSort3W(&array, low: 0, high: array.count - 1) 398 | 399 | } 400 | ``` 401 | 402 | 403 | 404 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-log-version.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | import Foundation 4 | 5 | //swift original sort function 6 | //var arr = [2,1,4,7,3] 7 | //arr.sort() 8 | //print(arr) 9 | 10 | //================= Basic functions ================ // 11 | 12 | 13 | ////swap function 14 | 15 | func swap(_ arr: inout [Int], _ j: Int, _ k: Int) { 16 | 17 | guard j != k else { 18 | return; 19 | } 20 | 21 | let temp = arr[j] 22 | arr[j] = arr[k] 23 | arr[k] = temp 24 | } 25 | 26 | 27 | // 28 | //var array = [0,1,2,3,4] 29 | //swap(arr:&array, 1, 2 ) 30 | //print(array) 31 | 32 | 33 | 34 | //============= sort functions =============// 35 | 36 | 37 | //var originalArray = [9,2,3,6,7,20,1,5] 38 | //var originalArray = [4,1,2,3,5,6,7,9,8] 39 | //var originalArray = [3,4,2,5,1] 40 | 41 | var inputSize = 500 42 | var originalArray = Array.randomArray(size: inputSize, maxValue:5) 43 | 44 | //var originalArray = Array.nearlySortedArray(size: inputSize, gap: 10) 45 | 46 | //var originalArray = [2,1,3,4,6,5,8,7] 47 | //var originalArray = [2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 48 | //var originalArray = [2,1] 49 | 50 | 51 | //var originalArray = [9,1,8,5,4,6,2,7,3] 52 | //print("original array : \(originalArray)\n") 53 | print("original array:\n\(originalArray)\n") 54 | 55 | //============= swift sorting =============// 56 | 57 | print("\nswift sort...") 58 | var originalArray0 = originalArray 59 | var swiftSortedArray = [Int]() 60 | var time0 = executionTimeInterval{ 61 | originalArray0.sort() 62 | } 63 | print("swift sort time duration : \(time0.formattedTime)") 64 | 65 | //============= Simple switch sorting =============// 66 | 67 | func switchSort(_ array: inout [Int]) -> [Int] { 68 | 69 | guard array.count > 1 else { return array } 70 | 71 | for i in 0 ..< array.count { 72 | 73 | for j in i + 1 ..< array.count { 74 | // print("\(i)") 75 | if array[i] > array[j] { 76 | // print("\n change \(a[i]) and \(a[j])") 77 | array.swapAt(i, j) //keeping the value of index i is the smaller one 78 | print("\(array)") 79 | } 80 | } 81 | } 82 | 83 | return array 84 | 85 | } 86 | 87 | 88 | 89 | //print("\nswitch sort...") 90 | //var originalArray1 = originalArray 91 | //var switchSortedArray = [Int]() 92 | //var time1 = executionTimeInterval{ 93 | // switchSortedArray = switchSort(&originalArray1) 94 | //} 95 | // 96 | //print("switch sort time duration : \(time1.formattedTime)") 97 | // 98 | // 99 | // 100 | 101 | //============= Bubble Sort =============// 102 | 103 | 104 | func bubbleSort(_ array: inout [Int]) -> [Int] { 105 | 106 | guard array.count > 1 else { return array } 107 | 108 | var compareCount = 0 109 | 110 | for i in 0 ..< array.count - 1 { 111 | // print("\(i)") 112 | for j in 0 ..< array.count - 1 - i { 113 | 114 | // count += 1 115 | compareCount += 1 116 | 117 | 118 | if array[j] > array[j+1] { 119 | array.swapAt(j, j+1) //keeping index of j is the smaller one 120 | // print("after swap: \(array)") 121 | 122 | } 123 | } 124 | } 125 | print("total compare count: \(compareCount)") 126 | return array 127 | } 128 | 129 | //print("\nbubble sort...") 130 | //var originalArray2 = originalArray 131 | //var bubbleSortedArray = [Int]() 132 | //var time2 = executionTimeInterval{ 133 | // bubbleSortedArray = bubbleSort(&originalArray2) 134 | //} 135 | // 136 | //print("bubble sort time duration : \(time2.formattedTime)") 137 | // 138 | 139 | 140 | 141 | 142 | //============= Advanced Bubble Sort =============// 143 | 144 | func bubbleSortAdvanced(_ array: inout [Int]) -> [Int] { 145 | 146 | guard array.count > 1 else { return array } 147 | // var compareCount = 0 148 | 149 | for i in 0 ..< array.count - 1 { 150 | 151 | var swapped = false 152 | for j in 0 ..< array.count - i - 1 { 153 | 154 | // compareCount += 1 155 | // print("No.\(compareCount) compare \(array[j]) and \(array[j+1])") 156 | 157 | if array[j] > array [j+1] { 158 | array.swapAt(j, j+1) //keeping index of j is the smaller one 159 | // print("after swap: \(array)") 160 | swapped = true; 161 | // count += 1 162 | // print("No.\(count) swap \(j) and \(j+1)") 163 | // print("\(a)") 164 | } 165 | } 166 | 167 | //if there is no swapping in inner loop, it means the the part looped is already sorted, 168 | //so its time to break 169 | if (swapped == false){ break } 170 | } 171 | // print("total compare count: \(compareCount)") 172 | return array 173 | 174 | } 175 | 176 | 177 | //print("\nadvanced bubble sort...") 178 | //var originalArray3 = originalArray 179 | //var advancedBubbleSortedArray = [Int]() 180 | //var time3 = executionTimeInterval{ 181 | // advancedBubbleSortedArray = bubbleSortAdvanced(&originalArray3) 182 | //} 183 | 184 | 185 | 186 | //print("advanced bubble sort sorted elemets: \(advancedBubbleSortedArray.count) time duration : \(time3.formattedTime)") 187 | 188 | //============= selection Sort =============// 189 | 190 | func selectionSort(_ array: inout [Int]) -> [Int] { 191 | 192 | guard array.count > 1 else { return array } 193 | 194 | // var count = 0 195 | var compare = 0 196 | //move boundary of unsorted subarray 197 | for i in 0 ..< array.count - 1{ 198 | 199 | var min = i 200 | 201 | // find the minimum element in unsorted array 202 | for j in i + 1 ..< array.count { 203 | compare += 1 204 | 205 | if array[j] < array[min] { 206 | min = j //update the minimum value index 207 | } 208 | } 209 | 210 | //if min has changed, it means there is value smaller than array[min] 211 | //if min has not changed, it means there is no value smallter than array[min] 212 | if i != min { 213 | array.swapAt(i, min) //exchange the minimum value index with current index 214 | // count += 1 215 | // print("No.\(count) swap \(x) and \(min)") 216 | // print("after swap: \(array)") 217 | } 218 | 219 | 220 | } 221 | 222 | // print("total compare count: \(compareCount)") 223 | // print("compare times:\(compare)") 224 | return array 225 | } 226 | 227 | // 228 | // 229 | //print("\nselection sort...") 230 | //var originalArray4 = originalArray 231 | //var selectionSortedArray = [Int]() 232 | //var time4 = executionTimeInterval{ 233 | // selectionSortedArray = selectionSort(&originalArray4) 234 | //} 235 | // 236 | //print("selection sort time duration : \(time4.formattedTime)") 237 | // 238 | 239 | 240 | 241 | 242 | 243 | //============= insertion Sort =============// 244 | 245 | func insertionSort(_ array: inout [Int]) -> [Int] { 246 | 247 | guard array.count > 1 else { return array } 248 | var compare = 0 249 | for i in 1.. 0 && array[j] < array[j - 1] { 254 | compare += 1 255 | 256 | array.swapAt(j - 1, j) 257 | 258 | j -= 1 259 | } 260 | } 261 | // print("compare times:\(compare)") 262 | return array 263 | } 264 | 265 | 266 | //print("\ninsertion sort...") 267 | //var originalArray5 = originalArray 268 | //var insertSortedArray = [Int]() 269 | //var time5 = executionTimeInterval{ 270 | // insertSortedArray = insertionSort(&originalArray5) 271 | //} 272 | // 273 | //print("insertion sort time duration : \(time5.formattedTime)") 274 | // 275 | 276 | func mergeSort(_ array: [Int]) -> [Int] { 277 | 278 | guard array.count > 1 else { return array } 279 | 280 | let middleIndex = array.count / 2 281 | let leftArray = mergeSort(Array(array[0.. [Int] { 291 | 292 | // print("\nmerge left pile:\(leftPile) | right pile:\(rightPile)") 293 | 294 | var leftIndex = 0 //left pile index, start from 0 295 | var rightIndex = 0 //right pile index, start from 0 296 | 297 | 298 | var sortedPile = [Int]() //sorted pile, empty in the first place 299 | 300 | 301 | while leftIndex < leftPile.count && rightIndex < rightPile.count { 302 | 303 | //append the smaller value into sortedPile 304 | if leftPile[leftIndex] < rightPile[rightIndex] { 305 | 306 | sortedPile.append(leftPile[leftIndex]) 307 | leftIndex += 1 308 | 309 | } else if leftPile[leftIndex] > rightPile[rightIndex] { 310 | 311 | sortedPile.append(rightPile[rightIndex]) 312 | rightIndex += 1 313 | 314 | } else { 315 | 316 | //same value, append both of them and move the corresponding index 317 | sortedPile.append(leftPile[leftIndex]) 318 | leftIndex += 1 319 | sortedPile.append(rightPile[rightIndex]) 320 | rightIndex += 1 321 | } 322 | } 323 | 324 | 325 | //left pile is not empty 326 | while leftIndex < leftPile.count { 327 | sortedPile.append(leftPile[leftIndex]) 328 | leftIndex += 1 329 | } 330 | 331 | //right pile is not empty 332 | while rightIndex < rightPile.count { 333 | sortedPile.append(rightPile[rightIndex]) 334 | rightIndex += 1 335 | } 336 | 337 | // print("sorted pile:\(sortedPile)") 338 | return sortedPile 339 | } 340 | 341 | // 342 | //print("\nmerge sort...") 343 | //var originalArray6 = originalArray 344 | //var mergeSortedArray = [Int]() 345 | //var time6 = executionTimeInterval{ 346 | // mergeSortedArray = mergeSort(originalArray6) 347 | //} 348 | // 349 | //print("merge sort time duration : \(time6.formattedTime)") 350 | // 351 | 352 | // ============= Quick Sort ============ // 353 | 354 | // 355 | //func quickSort0(_ array: [T]) -> [T] { 356 | // 357 | // guard array.count > 1 else { return array } 358 | // 359 | // let pivot = array[array.count/2] 360 | // let less = array.filter { $0 < pivot } 361 | // let equal = array.filter { $0 == pivot } 362 | // let greater = array.filter { $0 > pivot } 363 | // 364 | // return quickSort0(less) + equal + quickSort0(greater) 365 | //} 366 | 367 | func quickSort0(_ array: [Int]) -> [Int] { 368 | 369 | guard array.count > 1 else { return array } 370 | 371 | let pivot = array[array.count/2] 372 | let less = array.filter { $0 < pivot } 373 | let greater = array.filter { $0 > pivot } 374 | 375 | return quickSort0(less) + quickSort0(greater) 376 | } 377 | 378 | print("\nquick sort...") 379 | var originalArray7 = originalArray 380 | var quickSortedArray = [Int]() 381 | var time7 = executionTimeInterval{ 382 | quickSortedArray = quickSort0(originalArray7) 383 | } 384 | quickSortedArray 385 | 386 | print("quick sort0 time duration : \(time7.formattedTime)") 387 | 388 | 389 | 390 | func _partition(_ array: inout [Int], low: Int, high: Int) -> Int{ 391 | 392 | var low = low 393 | var high = high 394 | 395 | let pivotValue = array[low] 396 | 397 | while low < high { 398 | 399 | while low < high && array[high] >= pivotValue { 400 | high -= 1 401 | } 402 | array[low] = array[high] 403 | 404 | while low < high && array[low] <= pivotValue { 405 | low += 1 406 | } 407 | array[high] = array[low] 408 | } 409 | 410 | array[low] = pivotValue 411 | 412 | return low 413 | } 414 | 415 | 416 | 417 | func quickSort1(_ array: inout [Int], low: Int, high: Int){ 418 | 419 | guard array.count > 1 else { return } 420 | 421 | if low < high { 422 | 423 | //pivote index is low 424 | let pivotIndex = _partition(&array, low: low, high: high) 425 | 426 | //pivote index is random 427 | // let pivotIndex = _partitionRandom(&array, low: low, high: high) 428 | quickSort1(&array, low: low, high: pivotIndex - 1) 429 | quickSort1(&array, low: pivotIndex + 1, high: high) 430 | } 431 | 432 | } 433 | 434 | 435 | 436 | var originalArray8 = originalArray 437 | var quickSortedArray1 = [Int]() 438 | var time8 = executionTimeInterval{ 439 | quickSort1(&originalArray8, low: 0, high: originalArray8.count-1) 440 | } 441 | 442 | print("quick sort1 time duration : \(time8.formattedTime)") 443 | 444 | 445 | 446 | func _partitionRandom(_ array: inout [Int], low: Int, high: Int) -> Int{ 447 | 448 | 449 | let x = UInt32(low) 450 | let y = UInt32(high) 451 | 452 | let pivotIndex = Int(arc4random() % (y - x)) + Int(x) 453 | // print("x \(x) y \(y ) pivotindex \(pivotIndex)") 454 | let pivotValue = array[pivotIndex] 455 | 456 | 457 | var low = low 458 | var high = high 459 | 460 | while low < high { 461 | 462 | while low < high && array[high] >= pivotValue { 463 | high -= 1 464 | } 465 | array[low] = array[high] 466 | // print("\nchanged:\(array)") 467 | 468 | while low < high && array[low] <= pivotValue { 469 | low += 1 470 | } 471 | 472 | array[high] = array[low] 473 | // print("changed:\(array)") 474 | } 475 | 476 | array[low] = pivotValue 477 | // print("changed1:\(array)") 478 | 479 | return low 480 | } 481 | 482 | 483 | func quickSort2(_ array: inout [Int], low: Int, high: Int){ 484 | 485 | guard array.count > 1 else { return } 486 | 487 | if low < high { 488 | 489 | //pivote index is random 490 | let pivotIndex = _partitionRandom(&array, low: low, high: high) 491 | quickSort2(&array, low: low, high: pivotIndex - 1) 492 | quickSort2(&array, low: pivotIndex + 1, high: high) 493 | } 494 | 495 | } 496 | 497 | 498 | 499 | var originalArray9 = originalArray 500 | var quickSortedArray2 = [Int]() 501 | var time9 = executionTimeInterval{ 502 | quickSort2(&originalArray9, low: 0, high: originalArray9.count - 1) 503 | } 504 | print("quick sort2 time duration : \(time9.formattedTime)") 505 | 506 | 507 | 508 | func quickSort3W(_ array: inout [Int], low: Int, high: Int) { 509 | 510 | if high <= low { return } 511 | 512 | var lt = low // arr[low+1...lt] < v 513 | var gt = high + 1 // arr[gt...high] > v 514 | var i = low + 1 // arr[lt+1...i) == v 515 | 516 | let pivoteIndex = low 517 | let pivoteValue = array[pivoteIndex] 518 | 519 | while i < gt { 520 | 521 | if array[i] < pivoteValue { 522 | 523 | swap(&array, i, lt + 1) 524 | i += 1 525 | lt += 1 526 | 527 | }else if pivoteValue < array[i]{ 528 | 529 | swap(&array, i, gt - 1) 530 | gt -= 1 531 | 532 | }else { 533 | i += 1 534 | } 535 | } 536 | 537 | swap(&array, low, lt) 538 | quickSort3W(&array, low: low, high: lt - 1) 539 | quickSort3W(&array, low: gt, high: high) 540 | 541 | 542 | } 543 | 544 | 545 | func quickSort3(_ array: inout [Int] ){ 546 | 547 | quickSort3W(&array, low: 0, high: array.count - 1) 548 | 549 | } 550 | 551 | var originalArray10 = originalArray 552 | var time10 = executionTimeInterval{ 553 | quickSort3(&originalArray10) 554 | } 555 | print("quick sort3 time duration : \(time10.formattedTime)") 556 | 557 | 558 | 559 | 560 | func quicksort4(_ array: [Int]) -> [Int] { 561 | 562 | guard array.count > 1 else { return array } 563 | 564 | let pivot = array[array.count/2] 565 | let less = array.filter { $0 < pivot } 566 | let equal = array.filter { $0 == pivot } 567 | let greater = array.filter { $0 > pivot } 568 | 569 | return quicksort4(less) + equal + quicksort4(greater) 570 | } 571 | 572 | 573 | 574 | 575 | 576 | var originalArray11 = originalArray 577 | var quickSortedArray3 = [Int]() 578 | var time11 = executionTimeInterval{ 579 | quickSortedArray3 = quicksort4(originalArray11) 580 | } 581 | 582 | print("quick sort4 time duration : \(time11.formattedTime)") 583 | 584 | 585 | 586 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-log-version.playground/Sources/Array+Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Array { 4 | 5 | static public func randomArray(size: Int, maxValue: UInt) -> [Int] { 6 | var result = [Int](repeating: 0, count:size) 7 | 8 | for i in 0 ..< size { 9 | result[i] = Int(arc4random_uniform(UInt32(maxValue))) 10 | } 11 | 12 | return result 13 | } 14 | 15 | static public func incrementalArray(size: Int) -> [Int] { 16 | var result = [Int](repeating: 0, count:size) 17 | 18 | for i in 0 ..< size { 19 | result[i] = i 20 | } 21 | 22 | return result 23 | } 24 | 25 | 26 | static public func nearlySortedArray(size: Int, gap:Int) -> [Int] { 27 | 28 | var result = [Int](repeating: 0, count:size) 29 | 30 | for i in 0 ..< size { 31 | result[i] = i 32 | } 33 | 34 | let count : Int = size / gap 35 | var arr = [Int]() 36 | 37 | for i in 0 ..< count { 38 | arr.append(i*gap) 39 | } 40 | 41 | for j in 0 ..< arr.count { 42 | let swapIndex = arr[j] 43 | result.swapAt(swapIndex,swapIndex+1) 44 | } 45 | 46 | return result 47 | } 48 | 49 | 50 | static public func reverseOrderedArray(size: Int) -> [Int] { 51 | var result = [Int](repeating: 0, count:size) 52 | 53 | for i in 0 ..< size { 54 | result[i] = size - i 55 | } 56 | 57 | return result 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-log-version.playground/Sources/executionTimeInterval.swift: -------------------------------------------------------------------------------- 1 | import QuartzCore 2 | 3 | //time interval 4 | public func executionTimeInterval(block: () -> ()) -> CFTimeInterval { 5 | let start = CACurrentMediaTime() 6 | block(); 7 | let end = CACurrentMediaTime() 8 | return end - start 9 | } 10 | 11 | 12 | //formatted time 13 | public extension CFTimeInterval { 14 | public var formattedTime: String { 15 | return self >= 1000 ? String(Int(self)) + "s" 16 | : self >= 1 ? String(format: "%.3gs", self) 17 | : self >= 1e-3 ? String(format: "%.3gms", self * 1e3) 18 | : self >= 1e-6 ? String(format: "%.3gµs", self * 1e6) 19 | : self < 1e-9 ? "0s" 20 | : String(format: "%.3gns", self * 1e9) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-log-version.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-log-version.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-log-version.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knightsj/data-structure-and-algorithm-in-Swift/1a4ba59529dee19c707f1b278e3bcd70ec8e677e/[4].Sort algorithms/Sort algorithms-log-version.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-log-version.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-pure-version.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | 3 | import Foundation 4 | 5 | //swift original sort function 6 | //var arr = [2,1,4,7,3] 7 | //arr.sort() 8 | //print(arr) 9 | 10 | //================= Basic functions ================ // 11 | 12 | 13 | ////swap function 14 | 15 | func swap(_ arr: inout [Int], _ j: Int, _ k: Int) { 16 | 17 | guard j != k else { 18 | return; 19 | } 20 | 21 | let temp = arr[j] 22 | arr[j] = arr[k] 23 | arr[k] = temp 24 | } 25 | 26 | 27 | // 28 | //var array = [0,1,2,3,4] 29 | //swap(arr:&array, 1, 2 ) 30 | //print(array) 31 | 32 | 33 | 34 | //============= sort functions =============// 35 | 36 | 37 | //var originalArray = [9,2,3,6,7,20,1,5] 38 | //var originalArray = [4,1,2,3,5,6,7,9,8] 39 | //var originalArray = [3,4,2,5,1] 40 | 41 | var inputSize = 500 42 | var originalArray = Array.randomArray(size: inputSize, maxValue:5) 43 | 44 | //var originalArray = Array.nearlySortedArray(size: inputSize, gap: 10) 45 | 46 | //var originalArray = [2,1,3,4,6,5,8,7] 47 | //var originalArray = [2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16] 48 | //var originalArray = [2,1] 49 | 50 | 51 | //var originalArray = [9,1,8,5,4,6,2,7,3] 52 | //print("original array : \(originalArray)\n") 53 | print("original array:\n\(originalArray)\n") 54 | 55 | //============= swift sorting =============// 56 | 57 | print("\nswift sort...") 58 | var originalArray0 = originalArray 59 | var swiftSortedArray = [Int]() 60 | var time0 = executionTimeInterval{ 61 | originalArray0.sort() 62 | } 63 | print("swift sort time duration : \(time0.formattedTime)") 64 | 65 | //============= Simple switch sorting =============// 66 | 67 | func switchSort(_ array: inout [Int]) -> [Int] { 68 | 69 | guard array.count > 1 else { return array } 70 | 71 | for i in 0 ..< array.count { 72 | 73 | for j in i + 1 ..< array.count { 74 | 75 | if array[i] > array[j] { 76 | array.swapAt(i, j) //keeping the value of index i is the smaller one 77 | } 78 | } 79 | } 80 | 81 | return array 82 | 83 | } 84 | 85 | 86 | 87 | //print("\nswitch sort...") 88 | //var originalArray1 = originalArray 89 | //var switchSortedArray = [Int]() 90 | //var time1 = executionTimeInterval{ 91 | // switchSortedArray = switchSort(&originalArray1) 92 | //} 93 | // 94 | //print("switch sort time duration : \(time1.formattedTime)") 95 | // 96 | // 97 | // 98 | 99 | //============= Bubble Sort =============// 100 | 101 | 102 | func bubbleSort(_ array: inout [Int]) -> [Int] { 103 | 104 | guard array.count > 1 else { return array } 105 | 106 | for i in 0 ..< array.count - 1 { 107 | 108 | for j in 0 ..< array.count - 1 - i { 109 | 110 | if array[j] > array[j+1] { 111 | array.swapAt(j, j+1) //keeping index of j is the smaller one 112 | 113 | } 114 | } 115 | } 116 | return array 117 | } 118 | 119 | //print("\nbubble sort...") 120 | //var originalArray2 = originalArray 121 | //var bubbleSortedArray = [Int]() 122 | //var time2 = executionTimeInterval{ 123 | // bubbleSortedArray = bubbleSort(&originalArray2) 124 | //} 125 | // 126 | //print("bubble sort time duration : \(time2.formattedTime)") 127 | // 128 | 129 | 130 | 131 | 132 | //============= Advanced Bubble Sort =============// 133 | 134 | func bubbleSortAdvanced(_ array: inout [Int]) -> [Int] { 135 | 136 | guard array.count > 1 else { return array } 137 | 138 | for i in 0 ..< array.count - 1 { 139 | 140 | var swapped = false 141 | for j in 0 ..< array.count - i - 1 { 142 | 143 | if array[j] > array [j+1] { 144 | array.swapAt(j, j+1) //keeping index of j is the smaller one 145 | swapped = true; 146 | } 147 | } 148 | 149 | //if there is no swapping in inner loop, it means the the part looped is already sorted, 150 | //so its time to break 151 | if (swapped == false){ break } 152 | } 153 | return array 154 | 155 | } 156 | 157 | 158 | //print("\nadvanced bubble sort...") 159 | //var originalArray3 = originalArray 160 | //var advancedBubbleSortedArray = [Int]() 161 | //var time3 = executionTimeInterval{ 162 | // advancedBubbleSortedArray = bubbleSortAdvanced(&originalArray3) 163 | //} 164 | 165 | 166 | 167 | //print("advanced bubble sort sorted elemets: \(advancedBubbleSortedArray.count) time duration : \(time3.formattedTime)") 168 | 169 | //============= selection Sort =============// 170 | 171 | func selectionSort(_ array: inout [Int]) -> [Int] { 172 | 173 | guard array.count > 1 else { return array } 174 | 175 | // var count = 0 176 | var compare = 0 177 | //move boundary of unsorted subarray 178 | for i in 0 ..< array.count - 1{ 179 | 180 | var min = i 181 | 182 | // find the minimum element in unsorted array 183 | for j in i + 1 ..< array.count { 184 | compare += 1 185 | 186 | if array[j] < array[min] { 187 | min = j //update the minimum value index 188 | } 189 | } 190 | 191 | //if min has changed, it means there is value smaller than array[min] 192 | //if min has not changed, it means there is no value smallter than array[min] 193 | if i != min { 194 | array.swapAt(i, min) //exchange the minimum value index with current index 195 | } 196 | 197 | 198 | } 199 | return array 200 | } 201 | 202 | // 203 | // 204 | //print("\nselection sort...") 205 | //var originalArray4 = originalArray 206 | //var selectionSortedArray = [Int]() 207 | //var time4 = executionTimeInterval{ 208 | // selectionSortedArray = selectionSort(&originalArray4) 209 | //} 210 | // 211 | //print("selection sort time duration : \(time4.formattedTime)") 212 | // 213 | 214 | 215 | 216 | 217 | 218 | //============= insertion Sort =============// 219 | 220 | func insertionSort(_ array: inout [Int]) -> [Int] { 221 | 222 | guard array.count > 1 else { return array } 223 | for i in 1.. 0 && array[j] < array[j - 1] { 228 | array.swapAt(j - 1, j) 229 | j -= 1 230 | } 231 | } 232 | return array 233 | } 234 | 235 | 236 | //print("\ninsertion sort...") 237 | //var originalArray5 = originalArray 238 | //var insertSortedArray = [Int]() 239 | //var time5 = executionTimeInterval{ 240 | // insertSortedArray = insertionSort(&originalArray5) 241 | //} 242 | // 243 | //print("insertion sort time duration : \(time5.formattedTime)") 244 | // 245 | 246 | func mergeSort(_ array: [Int]) -> [Int] { 247 | 248 | guard array.count > 1 else { return array } 249 | 250 | let middleIndex = array.count / 2 251 | let leftArray = mergeSort(Array(array[0.. [Int] { 261 | 262 | var leftIndex = 0 //left pile index, start from 0 263 | var rightIndex = 0 //right pile index, start from 0 264 | 265 | 266 | var sortedPile = [Int]() //sorted pile, empty in the first place 267 | 268 | 269 | while leftIndex < leftPile.count && rightIndex < rightPile.count { 270 | 271 | //append the smaller value into sortedPile 272 | if leftPile[leftIndex] < rightPile[rightIndex] { 273 | 274 | sortedPile.append(leftPile[leftIndex]) 275 | leftIndex += 1 276 | 277 | } else if leftPile[leftIndex] > rightPile[rightIndex] { 278 | 279 | sortedPile.append(rightPile[rightIndex]) 280 | rightIndex += 1 281 | 282 | } else { 283 | 284 | //same value, append both of them and move the corresponding index 285 | sortedPile.append(leftPile[leftIndex]) 286 | leftIndex += 1 287 | sortedPile.append(rightPile[rightIndex]) 288 | rightIndex += 1 289 | } 290 | } 291 | 292 | 293 | //left pile is not empty 294 | while leftIndex < leftPile.count { 295 | sortedPile.append(leftPile[leftIndex]) 296 | leftIndex += 1 297 | } 298 | 299 | //right pile is not empty 300 | while rightIndex < rightPile.count { 301 | sortedPile.append(rightPile[rightIndex]) 302 | rightIndex += 1 303 | } 304 | 305 | // print("sorted pile:\(sortedPile)") 306 | return sortedPile 307 | } 308 | 309 | // 310 | //print("\nmerge sort...") 311 | //var originalArray6 = originalArray 312 | //var mergeSortedArray = [Int]() 313 | //var time6 = executionTimeInterval{ 314 | // mergeSortedArray = mergeSort(originalArray6) 315 | //} 316 | // 317 | //print("merge sort time duration : \(time6.formattedTime)") 318 | // 319 | 320 | // ============= Quick Sort ============ // 321 | 322 | // 323 | //func quickSort0(_ array: [T]) -> [T] { 324 | // 325 | // guard array.count > 1 else { return array } 326 | // 327 | // let pivot = array[array.count/2] 328 | // let less = array.filter { $0 < pivot } 329 | // let equal = array.filter { $0 == pivot } 330 | // let greater = array.filter { $0 > pivot } 331 | // 332 | // return quickSort0(less) + equal + quickSort0(greater) 333 | //} 334 | 335 | func quickSort0(_ array: [Int]) -> [Int] { 336 | 337 | guard array.count > 1 else { return array } 338 | 339 | let pivot = array[array.count/2] 340 | let less = array.filter { $0 < pivot } 341 | let greater = array.filter { $0 > pivot } 342 | 343 | return quickSort0(less) + quickSort0(greater) 344 | } 345 | 346 | print("\nquick sort...") 347 | var originalArray7 = originalArray 348 | var quickSortedArray = [Int]() 349 | var time7 = executionTimeInterval{ 350 | quickSortedArray = quickSort0(originalArray7) 351 | } 352 | quickSortedArray 353 | 354 | print("quick sort0 time duration : \(time7.formattedTime)") 355 | 356 | 357 | 358 | func _partition(_ array: inout [Int], low: Int, high: Int) -> Int{ 359 | 360 | var low = low 361 | var high = high 362 | 363 | let pivotValue = array[low] 364 | 365 | while low < high { 366 | 367 | while low < high && array[high] >= pivotValue { 368 | high -= 1 369 | } 370 | array[low] = array[high] 371 | 372 | while low < high && array[low] <= pivotValue { 373 | low += 1 374 | } 375 | array[high] = array[low] 376 | } 377 | 378 | array[low] = pivotValue 379 | 380 | return low 381 | } 382 | 383 | 384 | 385 | func quickSort1(_ array: inout [Int], low: Int, high: Int){ 386 | 387 | guard array.count > 1 else { return } 388 | 389 | if low < high { 390 | 391 | //pivote index is low 392 | let pivotIndex = _partition(&array, low: low, high: high) 393 | 394 | quickSort1(&array, low: low, high: pivotIndex - 1) 395 | quickSort1(&array, low: pivotIndex + 1, high: high) 396 | } 397 | 398 | } 399 | 400 | 401 | 402 | var originalArray8 = originalArray 403 | var quickSortedArray1 = [Int]() 404 | var time8 = executionTimeInterval{ 405 | quickSort1(&originalArray8, low: 0, high: originalArray8.count-1) 406 | } 407 | 408 | print("quick sort1 time duration : \(time8.formattedTime)") 409 | 410 | 411 | 412 | func _partitionRandom(_ array: inout [Int], low: Int, high: Int) -> Int{ 413 | 414 | 415 | let x = UInt32(low) 416 | let y = UInt32(high) 417 | 418 | let pivotIndex = Int(arc4random() % (y - x)) + Int(x) 419 | let pivotValue = array[pivotIndex] 420 | 421 | 422 | var low = low 423 | var high = high 424 | 425 | while low < high { 426 | 427 | while low < high && array[high] >= pivotValue { 428 | high -= 1 429 | } 430 | array[low] = array[high] 431 | 432 | while low < high && array[low] <= pivotValue { 433 | low += 1 434 | } 435 | 436 | array[high] = array[low] 437 | } 438 | 439 | array[low] = pivotValue 440 | 441 | return low 442 | } 443 | 444 | 445 | func quickSort2(_ array: inout [Int], low: Int, high: Int){ 446 | 447 | guard array.count > 1 else { return } 448 | 449 | if low < high { 450 | 451 | //pivote index is random 452 | let pivotIndex = _partitionRandom(&array, low: low, high: high) 453 | quickSort2(&array, low: low, high: pivotIndex - 1) 454 | quickSort2(&array, low: pivotIndex + 1, high: high) 455 | } 456 | 457 | } 458 | 459 | 460 | 461 | var originalArray9 = originalArray 462 | var quickSortedArray2 = [Int]() 463 | var time9 = executionTimeInterval{ 464 | quickSort2(&originalArray9, low: 0, high: originalArray9.count - 1) 465 | } 466 | print("quick sort2 time duration : \(time9.formattedTime)") 467 | 468 | 469 | 470 | func quickSort3W(_ array: inout [Int], low: Int, high: Int) { 471 | 472 | if high <= low { return } 473 | 474 | var lt = low // arr[low+1...lt] < v 475 | var gt = high + 1 // arr[gt...high] > v 476 | var i = low + 1 // arr[lt+1...i) == v 477 | 478 | let pivoteIndex = low 479 | let pivoteValue = array[pivoteIndex] 480 | 481 | while i < gt { 482 | 483 | if array[i] < pivoteValue { 484 | 485 | swap(&array, i, lt + 1) 486 | i += 1 487 | lt += 1 488 | 489 | }else if pivoteValue < array[i]{ 490 | 491 | swap(&array, i, gt - 1) 492 | gt -= 1 493 | 494 | }else { 495 | i += 1 496 | } 497 | } 498 | 499 | swap(&array, low, lt) 500 | quickSort3W(&array, low: low, high: lt - 1) 501 | quickSort3W(&array, low: gt, high: high) 502 | 503 | 504 | } 505 | 506 | 507 | func quickSort3(_ array: inout [Int] ){ 508 | 509 | quickSort3W(&array, low: 0, high: array.count - 1) 510 | 511 | } 512 | 513 | var originalArray10 = originalArray 514 | var time10 = executionTimeInterval{ 515 | quickSort3(&originalArray10) 516 | } 517 | print("quick sort3 time duration : \(time10.formattedTime)") 518 | 519 | 520 | 521 | 522 | func quicksort4(_ array: [Int]) -> [Int] { 523 | 524 | guard array.count > 1 else { return array } 525 | 526 | let pivot = array[array.count/2] 527 | let less = array.filter { $0 < pivot } 528 | let equal = array.filter { $0 == pivot } 529 | let greater = array.filter { $0 > pivot } 530 | 531 | return quicksort4(less) + equal + quicksort4(greater) 532 | } 533 | 534 | 535 | 536 | 537 | 538 | var originalArray11 = originalArray 539 | var quickSortedArray3 = [Int]() 540 | var time11 = executionTimeInterval{ 541 | quickSortedArray3 = quicksort4(originalArray11) 542 | } 543 | 544 | print("quick sort4 time duration : \(time11.formattedTime)") 545 | 546 | 547 | 548 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-pure-version.playground/Sources/Array+Extension.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | extension Array { 4 | 5 | static public func randomArray(size: Int, maxValue: UInt) -> [Int] { 6 | var result = [Int](repeating: 0, count:size) 7 | 8 | for i in 0 ..< size { 9 | result[i] = Int(arc4random_uniform(UInt32(maxValue))) 10 | } 11 | 12 | return result 13 | } 14 | 15 | static public func incrementalArray(size: Int) -> [Int] { 16 | var result = [Int](repeating: 0, count:size) 17 | 18 | for i in 0 ..< size { 19 | result[i] = i 20 | } 21 | 22 | return result 23 | } 24 | 25 | 26 | static public func nearlySortedArray(size: Int, gap:Int) -> [Int] { 27 | 28 | var result = [Int](repeating: 0, count:size) 29 | 30 | for i in 0 ..< size { 31 | result[i] = i 32 | } 33 | 34 | let count : Int = size / gap 35 | var arr = [Int]() 36 | 37 | for i in 0 ..< count { 38 | arr.append(i*gap) 39 | } 40 | 41 | for j in 0 ..< arr.count { 42 | let swapIndex = arr[j] 43 | result.swapAt(swapIndex,swapIndex+1) 44 | } 45 | 46 | return result 47 | } 48 | 49 | 50 | static public func reverseOrderedArray(size: Int) -> [Int] { 51 | var result = [Int](repeating: 0, count:size) 52 | 53 | for i in 0 ..< size { 54 | result[i] = size - i 55 | } 56 | 57 | return result 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-pure-version.playground/Sources/executionTimeInterval.swift: -------------------------------------------------------------------------------- 1 | import QuartzCore 2 | 3 | //time interval 4 | public func executionTimeInterval(block: () -> ()) -> CFTimeInterval { 5 | let start = CACurrentMediaTime() 6 | block(); 7 | let end = CACurrentMediaTime() 8 | return end - start 9 | } 10 | 11 | 12 | //formatted time 13 | public extension CFTimeInterval { 14 | public var formattedTime: String { 15 | return self >= 1000 ? String(Int(self)) + "s" 16 | : self >= 1 ? String(format: "%.3gs", self) 17 | : self >= 1e-3 ? String(format: "%.3gms", self * 1e3) 18 | : self >= 1e-6 ? String(format: "%.3gµs", self * 1e6) 19 | : self < 1e-9 ? "0s" 20 | : String(format: "%.3gns", self * 1e9) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-pure-version.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-pure-version.playground/playground.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-pure-version.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knightsj/data-structure-and-algorithm-in-Swift/1a4ba59529dee19c707f1b278e3bcd70ec8e677e/[4].Sort algorithms/Sort algorithms-pure-version.playground/playground.xcworkspace/xcuserdata/SunShijie.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /[4].Sort algorithms/Sort algorithms-pure-version.playground/timeline.xctimeline: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 9 | 10 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /res/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knightsj/data-structure-and-algorithm-in-Swift/1a4ba59529dee19c707f1b278e3bcd70ec8e677e/res/logo.png --------------------------------------------------------------------------------