Skip to content

Commit 95b45f0

Browse files
committed
Split sorted set and ordered set
1 parent d7f172a commit 95b45f0

File tree

21 files changed

+738
-732
lines changed

21 files changed

+738
-732
lines changed

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

-76
This file was deleted.

Ordered Set/AppleOrderedSet.playground/contents.xcplayground

-4
This file was deleted.

Ordered Set/AppleOrderedSet.swift

-76
This file was deleted.

Ordered Set/AppleOrderedSet.playground/Contents.swift Ordered Set/OrderedSet.playground/Contents.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
let s = AppleOrderedSet<Int>()
1+
let s = OrderedSet<Int>()
22

33
s.add(1)
44
s.add(2)

Ordered Set/OrderedSet.playground/Pages/Example 3.xcplaygroundpage/timeline.xctimeline

-6
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,76 @@
1-
/*
2-
An Ordered Set is a collection where all items in the set follow an ordering,
3-
usually ordered from 'least' to 'most'. The way you value and compare items
4-
can be user-defined.
5-
*/
6-
public struct OrderedSet<T: Comparable> {
7-
private var internalSet = [T]()
8-
9-
public init() { }
10-
11-
// Returns the number of elements in the OrderedSet.
12-
public var count: Int {
13-
return internalSet.count
14-
}
15-
16-
// Inserts an item. Performance: O(n)
17-
public mutating func insert(_ item: T) {
18-
if exists(item) {
19-
return // don't add an item if it already exists
20-
}
21-
22-
// Insert new the item just before the one that is larger.
23-
for i in 0..<count {
24-
if internalSet[i] > item {
25-
internalSet.insert(item, at: i)
26-
return
27-
}
1+
public class OrderedSet<T: Hashable> {
2+
private var objects: [T] = []
3+
private var indexOfKey: [T: Int] = [:]
4+
5+
public init() {}
6+
7+
// O(1)
8+
public func add(_ object: T) {
9+
guard indexOfKey[object] == nil else {
10+
return
2811
}
29-
30-
// Append to the back if the new item is greater than any other in the set.
31-
internalSet.append(item)
12+
13+
objects.append(object)
14+
indexOfKey[object] = objects.count - 1
3215
}
33-
34-
// Removes an item if it exists. Performance: O(n)
35-
public mutating func remove(_ item: T) {
36-
if let index = index(of: item) {
37-
internalSet.remove(at: index)
16+
17+
// O(n)
18+
public func insert(_ object: T, at index: Int) {
19+
assert(index < objects.count, "Index should be smaller than object count")
20+
assert(index >= 0, "Index should be bigger than 0")
21+
22+
guard indexOfKey[object] == nil else {
23+
return
3824
}
39-
}
40-
41-
// Returns true if and only if the item exists somewhere in the set.
42-
public func exists(_ item: T) -> Bool {
43-
return index(of: item) != nil
44-
}
45-
46-
// Returns the index of an item if it exists, or -1 otherwise.
47-
public func index(of item: T) -> Int? {
48-
var leftBound = 0
49-
var rightBound = count - 1
50-
51-
while leftBound <= rightBound {
52-
let mid = leftBound + ((rightBound - leftBound) / 2)
53-
54-
if internalSet[mid] > item {
55-
rightBound = mid - 1
56-
} else if internalSet[mid] < item {
57-
leftBound = mid + 1
58-
} else if internalSet[mid] == item {
59-
return mid
60-
} else {
61-
// When we get here, we've landed on an item whose value is equal to the
62-
// value of the item we're looking for, but the items themselves are not
63-
// equal. We need to check the items with the same value to the right
64-
// and to the left in order to find an exact match.
65-
66-
// Check to the right.
67-
for j in stride(from: mid, to: count - 1, by: 1) {
68-
if internalSet[j + 1] == item {
69-
return j + 1
70-
} else if internalSet[j] < internalSet[j + 1] {
71-
break
72-
}
73-
}
74-
75-
// Check to the left.
76-
for j in stride(from: mid, to: 0, by: -1) {
77-
if internalSet[j - 1] == item {
78-
return j - 1
79-
} else if internalSet[j] > internalSet[j - 1] {
80-
break
81-
}
82-
}
83-
return nil
84-
}
25+
26+
objects.insert(object, at: index)
27+
indexOfKey[object] = index
28+
for i in index+1..<objects.count {
29+
indexOfKey[objects[i]] = i
8530
}
86-
return nil
8731
}
88-
89-
// Returns the item at the given index.
90-
// Assertion fails if the index is out of the range of [0, count).
91-
public subscript(index: Int) -> T {
92-
assert(index >= 0 && index < count)
93-
return internalSet[index]
32+
33+
// O(1)
34+
public func object(at index: Int) -> T {
35+
assert(index < objects.count, "Index should be smaller than object count")
36+
assert(index >= 0, "Index should be bigger than 0")
37+
38+
return objects[index]
9439
}
95-
96-
// Returns the 'maximum' or 'largest' value in the set.
97-
public func max() -> T? {
98-
return count == 0 ? nil : internalSet[count - 1]
40+
41+
// O(1)
42+
public func set(_ object: T, at index: Int) {
43+
assert(index < objects.count, "Index should be smaller than object count")
44+
assert(index >= 0, "Index should be bigger than 0")
45+
46+
guard indexOfKey[object] == nil else {
47+
return
48+
}
49+
50+
indexOfKey.removeValue(forKey: objects[index])
51+
indexOfKey[object] = index
52+
objects[index] = object
9953
}
100-
101-
// Returns the 'minimum' or 'smallest' value in the set.
102-
public func min() -> T? {
103-
return count == 0 ? nil : internalSet[0]
54+
55+
// O(1)
56+
public func indexOf(_ object: T) -> Int {
57+
return indexOfKey[object] ?? -1
10458
}
105-
106-
// Returns the k-th largest element in the set, if k is in the range
107-
// [1, count]. Returns nil otherwise.
108-
public func kLargest(_ k: Int) -> T? {
109-
return k > count || k <= 0 ? nil : internalSet[count - k]
59+
60+
// O(n)
61+
public func remove(_ object: T) {
62+
guard let index = indexOfKey[object] else {
63+
return
64+
}
65+
66+
indexOfKey.removeValue(forKey: object)
67+
objects.remove(at: index)
68+
for i in index..<objects.count {
69+
indexOfKey[objects[i]] = i
70+
}
11071
}
111-
112-
// Returns the k-th smallest element in the set, if k is in the range
113-
// [1, count]. Returns nil otherwise.
114-
public func kSmallest(_ k: Int) -> T? {
115-
return k > count || k <= 0 ? nil : internalSet[k - 1]
72+
73+
public func all() -> [T] {
74+
return objects
11675
}
11776
}
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2-
<playground version='6.0' target-platform='ios' display-mode='raw' executeOnSourceChanges='false'>
3-
<pages>
4-
<page name='Example 1'/>
5-
<page name='Example 2'/>
6-
<page name='Example 3'/>
7-
</pages>
2+
<playground version='5.0' target-platform='ios'>
3+
<timeline fileName='timeline.xctimeline'/>
84
</playground>

0 commit comments

Comments
 (0)