-
Notifications
You must be signed in to change notification settings - Fork 17
/
SortedArray.swift
133 lines (119 loc) · 3.52 KB
/
SortedArray.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
public struct SortedArray<Element: Comparable>: SortedSet {
fileprivate var storage: [Element] = []
public init() {}
}
extension SortedArray {
func index(for element: Element) -> Int {
var start = 0
var end = storage.count
while start < end {
let middle = start + (end - start) / 2
if element > storage[middle] {
start = middle + 1
}
else {
end = middle
}
}
return start
}
}
extension SortedArray {
public func index(of element: Element) -> Int? {
let index = self.index(for: element)
guard index < count, storage[index] == element else { return nil }
return index
}
}
extension SortedArray {
public func contains(_ element: Element) -> Bool {
let index = self.index(for: element)
return index < count && storage[index] == element
}
}
extension SortedArray {
public func forEach(_ body: (Element) throws -> Void) rethrows {
try storage.forEach(body)
}
}
extension SortedArray {
public func sorted() -> [Element] {
return storage
}
}
extension SortedArray {
@discardableResult
public mutating func insert(_ newElement: Element) -> (inserted: Bool, memberAfterInsert: Element)
{
let index = self.index(for: newElement)
if index < count && storage[index] == newElement {
return (false, storage[index])
}
storage.insert(newElement, at: index)
return (true, newElement)
}
}
extension SortedArray: RandomAccessCollection {
public typealias Indices = CountableRange<Int>
public var startIndex: Int { return storage.startIndex }
public var endIndex: Int { return storage.endIndex }
public subscript(index: Int) -> Element { return storage[index] }
}
extension SortedArray {
func index2(for element: Element) -> Int {
var start = 0
var end = storage.count
while start < end {
let middle = start + (end - start) / 2 + (end - start) >> 6
if element > storage[middle] {
start = middle + 1
}
else {
end = middle
}
}
return start
}
public func contains2(_ element: Element) -> Bool {
let index = self.index2(for: element)
return index < count && storage[index] == element
}
func index3(for element: Element) -> Int {
var start = 0
var end = storage.count
while start < end {
let diff = end - start
if diff < 1024 {
let middle = start + diff >> 1
if element > storage[middle] {
start = middle + 1
}
else {
end = middle
}
}
else {
let third = diff / 3
let m1 = start + third
let m2 = end - third
let v1 = storage[m1]
let v2 = storage[m2]
if element < v1 {
end = m1
}
else if element > v2 {
start = m2 + 1
}
else {
start = m1
end = m2 + 1
}
}
}
return start
}
public func contains3(_ element: Element) -> Bool {
let index = self.index3(for: element)
return index < count && storage[index] == element
}
}