Skip to content

Commit d7f172a

Browse files
committed
Improvement of Apple Ordered Set
Add explaination for apple ordered set
1 parent 0c2aa34 commit d7f172a

File tree

5 files changed

+144
-11
lines changed

5 files changed

+144
-11
lines changed

Ordered Set/AppleOrderedSet.playground/Contents.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,17 @@ s.add(-1)
66
s.add(0)
77
s.insert(4, at: 3)
88

9-
s.set(-1, at: 0)
9+
print(s.all()) // [1, 2, -1, 4, 0]
10+
11+
s.set(-1, at: 0) // We already have -1 in index: 2, so we will do nothing here
12+
13+
print(s.all()) // [1, 2, -1, 4, 0]
14+
1015
s.remove(-1)
1116

12-
print(s.object(at: 1))
17+
print(s.all()) // [1, 2, 4, 0]
18+
19+
print(s.object(at: 1)) // 2
20+
21+
print(s.object(at: 2)) // 4
1322

Ordered Set/AppleOrderedSet.playground/Sources/AppleOrderedSet.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,8 @@ public class AppleOrderedSet<T: Hashable> {
6969
indexOfKey[objects[i]] = i
7070
}
7171
}
72+
73+
public func all() -> [T] {
74+
return objects
75+
}
7276
}

Ordered Set/AppleOrderedSet.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,8 @@ public class AppleOrderedSet<T: Hashable> {
6969
indexOfKey[objects[i]] = i
7070
}
7171
}
72+
73+
public func all() -> [T] {
74+
return objects
75+
}
7276
}

Ordered Set/README.markdown

Lines changed: 121 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Ordered Set
22

3+
## Sorted Array Version
4+
35
An Ordered Set is a collection of unique items in sorted order. Items are usually sorted from least to greatest.
46

57
The Ordered Set data type is a hybrid of:
@@ -323,15 +325,129 @@ The right side did not contain the item, so we look at the left side:
323325

324326
[X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X]
325327
* mid
326-
328+
327329
[X, X, Player 1, Player 2, Player 3, Player 4, Player 5, X, X]
328330
* mid
329331

330332
Finally, we've found `Player 2`, and return index 3.
331333

332-
## See Also
334+
## Apple's Ordered Set
335+
Below the ordered set is based on sorted array. But [Apple's version](https://developer.apple.com/documentation/foundation/nsorderedset), it's pretty different. Now, let's look into how to implement apple's ordered set.
336+
337+
Here is the example about how it works
338+
339+
```swift
340+
let s = AppleOrderedSet<Int>()
341+
342+
s.add(1)
343+
s.add(2)
344+
s.add(-1)
345+
s.add(0)
346+
s.insert(4, at: 3)
347+
348+
print(s.all()) // [1, 2, -1, 4, 0]
349+
350+
s.set(-1, at: 0) // We already have -1 in index: 2, so we will do nothing here
351+
352+
print(s.all()) // [1, 2, -1, 4, 0]
353+
354+
s.remove(-1)
355+
356+
print(s.all()) // [1, 2, 4, 0]
357+
358+
print(s.object(at: 1)) // 2
359+
360+
print(s.object(at: 2)) // 4
361+
```
362+
363+
The significant difference is the the array is not sorted. The elements in the array are the same when insert them. Image the array without duplicates and with `O(logn)` or `O(1)` search time.
364+
365+
The idea here is using a data structure to provide `O(1)` or `O(logn)` time complexity, so it's easy to think about hash table.
366+
367+
```swift
368+
var indexOfKey: [T: Int]
369+
var objects: [T]
370+
```
371+
372+
`indexOfKey` is used to track the index of the element. `objects` is array holding elements.
373+
374+
We will go through some key functions details here.
375+
376+
### Add
333377

334-
[Apple Ordered Set](AppleOrderedSet.playground)
335-
@remlostime added an Apple version of `OrderedSet`
378+
Update `indexOfKey` and insert element in the end of `objects`
379+
380+
```swift
381+
// O(1)
382+
public func add(_ object: T) {
383+
guard indexOfKey[object] == nil else {
384+
return
385+
}
386+
387+
objects.append(object)
388+
indexOfKey[object] = objects.count - 1
389+
}
390+
```
391+
392+
### Insert
393+
394+
Insert in a random place of the array will cost `O(n)` time.
395+
396+
```swift
397+
// O(n)
398+
public func insert(_ object: T, at index: Int) {
399+
assert(index < objects.count, "Index should be smaller than object count")
400+
assert(index >= 0, "Index should be bigger than 0")
401+
402+
guard indexOfKey[object] == nil else {
403+
return
404+
}
405+
406+
objects.insert(object, at: index)
407+
indexOfKey[object] = index
408+
for i in index+1..<objects.count {
409+
indexOfKey[objects[i]] = i
410+
}
411+
}
412+
```
413+
414+
### Set
415+
416+
If the `object` already existed in the `OrderedSet`, do nothing. Otherwise, we need to update the `indexOfkey` and `objects`.
417+
418+
```swift
419+
// O(1)
420+
public func set(_ object: T, at index: Int) {
421+
assert(index < objects.count, "Index should be smaller than object count")
422+
assert(index >= 0, "Index should be bigger than 0")
423+
424+
guard indexOfKey[object] == nil else {
425+
return
426+
}
427+
428+
indexOfKey.removeValue(forKey: objects[index])
429+
indexOfKey[object] = index
430+
objects[index] = object
431+
}
432+
```
433+
434+
### Remove
435+
436+
Remove element in the array will cost `O(n)`. At the same time, we need to update all elements's index after the removed element.
437+
438+
```swift
439+
// O(n)
440+
public func remove(_ object: T) {
441+
guard let index = indexOfKey[object] else {
442+
return
443+
}
444+
445+
indexOfKey.removeValue(forKey: object)
446+
objects.remove(at: index)
447+
for i in index..<objects.count {
448+
indexOfKey[objects[i]] = i
449+
}
450+
}
451+
```
336452

337-
*Written By Zain Humayun*
453+
*Ordered Set is Written By Zain Humayun, Apple Ordered Set is Written By Kai Chen*

swift-algorithm-club.xcworkspace/contents.xcworkspacedata

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)