|
2 | 2 | An Ordered Set is a collection of unique items in sorted order. Items are usually sorted from least to greatest. The Ordered Set data type is a representation of a [Set in Mathematics](https://en.wikipedia.org/wiki/Set_(mathematics)). It's important to keep in mind that two items can have the same *value* but still may not be equal.
|
3 | 3 | For example, we could define "a" and "z" to have the same value (their lengths), but clearly "a" != "z".
|
4 | 4 |
|
5 |
| -### Examples of Ordered Sets |
| 5 | +## Why use an Ordered Set? |
| 6 | +Ordered Sets should be considered for use when you need to require keeping your collection sorted at all times, and do lookups on the collection much more freuqently than inserting or deleting items. A good example would be keeping track of the rankings of players in a scoreboard (see example 2 below). Many of the lookup operations for an Ordered Set are **O(1)**. |
| 7 | + |
| 8 | +### These are Ordered Sets |
6 | 9 | ```
|
7 | 10 | [1, 2, 3, 6, 8, 10, 1000]
|
8 | 11 | Where each item (Integers) has it's normal definition of value and equality
|
@@ -161,6 +164,177 @@ First, `j` starts at the mid value. Above, we've already checked to see that the
|
161 | 164 | The combined runtime for this function is **O(log(n) + k)** where `n` is the length of the set, and `k` is the number of
|
162 | 165 | items with the same *value* as the one that is being searched for.
|
163 | 166 |
|
| 167 | +Since the set is sorted, the following operations are all **O(1)**: |
| 168 | + |
| 169 | +```swift |
| 170 | + // returns the 'maximum' or 'largest' value in the set |
| 171 | + public func max() -> T! { |
| 172 | + return count == 0 ? nil : internalSet[count - 1] |
| 173 | + } |
| 174 | + |
| 175 | + // returns the 'minimum' or 'smallest' value in the set |
| 176 | + public func min() -> T! { |
| 177 | + return count == 0 ? nil : internalSet[0] |
| 178 | + } |
| 179 | + |
| 180 | + // returns the k largest element in the set, if k is in the range [1, count] |
| 181 | + // returns nil otherwise |
| 182 | + public func kLargest(k: Int) -> T! { |
| 183 | + return k > count || k <= 0 ? nil : internalSet[count - k] |
| 184 | + } |
| 185 | + |
| 186 | + // returns the k smallest element in the set, if k is in the range [1, count] |
| 187 | + // returns nil otherwise |
| 188 | + public func kSmallest(k: Int) -> T! { |
| 189 | + return k > count || k <= 0 ? nil : internalSet[k - 1] |
| 190 | + } |
| 191 | +``` |
| 192 | + |
| 193 | +## Examples |
| 194 | +Below are a few examples that can be found in the playground file. |
| 195 | + |
| 196 | +### Example 1 |
| 197 | +Here we create a set with random Integers. Pringint the largest/smallest 5 numbers in the set is fairly easy. |
| 198 | +``` swift |
| 199 | +// Example 1 with type Int |
| 200 | +var mySet = OrderedSet<Int>() |
| 201 | + |
| 202 | +// insert random ints into the set |
| 203 | + |
| 204 | +for _ in 0..<50 { |
| 205 | + mySet.insert(randomNum(50, max: 500)) |
| 206 | +} |
| 207 | + |
| 208 | +print(mySet) |
| 209 | + |
| 210 | +print(mySet.max()) |
| 211 | +print(mySet.min()) |
| 212 | + |
| 213 | +// print the 5 largest values |
| 214 | +for k in 1..<6 { |
| 215 | + print(mySet.kLargest(k)) |
| 216 | +} |
| 217 | + |
| 218 | +// print the 5 lowest values |
| 219 | +for k in 1..<6 { |
| 220 | + print(mySet.kSmallest(k)) |
| 221 | +} |
| 222 | +``` |
| 223 | + |
| 224 | +### Exmaple 2 |
| 225 | +In this example we take a look at something a bit more interesting. We define a `Player` struct as follows: |
| 226 | +``` swift |
| 227 | +struct Player : Comparable { |
| 228 | + var name: String! = String.random() |
| 229 | + var points = randomNum(0, max: 5000) |
| 230 | + |
| 231 | + init(name: String, points: Int){ |
| 232 | + self.name = name |
| 233 | + self.points = points |
| 234 | + } |
| 235 | + |
| 236 | + init(){} |
| 237 | +} |
| 238 | + |
| 239 | +// == operator for struct Player |
| 240 | +// Player x is equal to Player y if and only if both players have the same name and number of points |
| 241 | +func ==(x: Player, y: Player) -> Bool { |
| 242 | + return x.name == y.name && x.points == y.points |
| 243 | +} |
| 244 | + |
| 245 | +// < operator for struct Player |
| 246 | +// Player x is less than Player y if and only if x has less points than y |
| 247 | +func <(x: Player, y: Player) -> Bool { |
| 248 | + return x.points < y.points |
| 249 | +} |
| 250 | +``` |
| 251 | +The set we create will hold players. One thing to note is that two `Player`'s can each have the same value, but are not guaranteed to be equal. |
| 252 | + |
| 253 | +Inserting 20 random players and one player we will track of. |
| 254 | +``` swift |
| 255 | +// Example 2 with type Player |
| 256 | +var playerSet = OrderedSet<Player>() |
| 257 | + |
| 258 | +// populate with random players. |
| 259 | +var anotherPlayer = Player() |
| 260 | +for _ in 0..<20 { |
| 261 | + playerSet.insert(Player()) |
| 262 | +} |
| 263 | + |
| 264 | +// we'll look for this player later |
| 265 | +playerSet.insert(anotherPlayer) |
| 266 | +``` |
| 267 | + |
| 268 | +Next, we can find the players with the most and least amount of points very quickly. |
| 269 | +``` swift |
| 270 | +// highest and lowest players: |
| 271 | +print(playerSet.max()) |
| 272 | +print(playerSet.min()) |
| 273 | +``` |
| 274 | + |
| 275 | +Next we use the findIndex function to find out what rank `anotherPlayer` in comparison to the other `Player`s. |
| 276 | +``` swift |
| 277 | +// we'll find our player now |
| 278 | +print("'Another Player (\(anotherPlayer.name))' is ranked at level: \(playerSet.count - playerSet.findIndex(anotherPlayer)) with \(anotherPlayer.points) points") |
| 279 | +``` |
| 280 | + |
| 281 | +### Example 3 |
| 282 | +The final example demonstrates the need to look for the right item even after the Binary Search has completed. 9 Players are inserted into the set. |
| 283 | +``` swift |
| 284 | + |
| 285 | +var repeatedSet = OrderedSet<Player>() |
| 286 | + |
| 287 | +repeatedSet.insert(Player(name:"Player 1", points: 100)) |
| 288 | +repeatedSet.insert(Player(name: "Player 1", points: 100)) |
| 289 | +repeatedSet.insert(Player(name: "Player 2", points: 100)) |
| 290 | +repeatedSet.insert(Player(name: "Player 3", points: 100)) |
| 291 | +repeatedSet.insert(Player(name: "Player 4", points: 100)) |
| 292 | +repeatedSet.insert(Player(name: "Player 5", points: 100)) |
| 293 | +repeatedSet.insert(Player(name: "Player 6", points: 50)) |
| 294 | +repeatedSet.insert(Player(name: "Player 7", points: 200)) |
| 295 | +repeatedSet.insert(Player(name: "Player 8", points: 250)) |
| 296 | +repeatedSet.insert(Player(name: "Player 9", points: 25)) |
| 297 | + |
| 298 | +print(repeatedSet) |
| 299 | +``` |
| 300 | + |
| 301 | +The set looks something like this: |
| 302 | +``` |
| 303 | +[Player 9, Player 6, Player 1, Player 2, Player 3, Player 4, Player 5, Player 7, Player 8] |
| 304 | +``` |
164 | 305 |
|
| 306 | +The next line looks for `Player 2`: |
| 307 | +``` swift |
| 308 | +print(repeatedSet.findIndex(Player(name: "Player 2", points: 100))) |
| 309 | +``` |
| 310 | + |
| 311 | +After the Binary Search finishes, the value of `mid` is at index 5 |
| 312 | +``` |
| 313 | +[Player 9, Player 6, Player 1, Player 2, Player 3, Player 4, Player 5, Player 7, Player 8] |
| 314 | + mid |
| 315 | +``` |
| 316 | +However, we know this may not be where `Player 2` is, so we check both sides of `mid`. The shown Players below are the ones with the same value as `Player 4`, and are the ones we check after the Binary Search. |
| 317 | + |
| 318 | +``` |
| 319 | +[X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] |
| 320 | + mid |
| 321 | +``` |
| 322 | + |
| 323 | +The code then checks the right of `mid` (Every `Player` with an * below it) |
| 324 | +``` |
| 325 | +[X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] |
| 326 | + mid * |
| 327 | +``` |
| 328 | + |
| 329 | +The right side did not contain the item, so we look at the left side. |
| 330 | +``` |
| 331 | +[X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] |
| 332 | + * mid |
| 333 | +``` |
| 334 | +``` |
| 335 | +[X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X] |
| 336 | + * mid |
| 337 | +``` |
| 338 | +We've found `Player 2`! Index 3 is then returned. |
165 | 339 |
|
166 | 340 | *Written By Zain Humayun*
|
0 commit comments