Swift 如何在固定时间内返回下标?
当符合Swift 如何在固定时间内返回下标?,swift,collections,time-complexity,Swift,Collections,Time Complexity,当符合收集协议时,根据: extension LinkedList: Collection { typealias Index = Int typealias Element = T var startIndex: Index { return 0 } var endIndex: Index { return underestimatedCount } func index(after i: Index)
收集
协议时,根据:
extension LinkedList: Collection {
typealias Index = Int
typealias Element = T
var startIndex: Index {
return 0
}
var endIndex: Index {
return underestimatedCount
}
func index(after i: Index) -> Index {
return (i < endIndex) ? i + 1 : endIndex
}
subscript (position: Index) -> Element {
precondition(position < endIndex && position >= startIndex)
var iterator = makeIterator()
for i in 0 ..< position {
iterator.next()
if i + 1 == position {
return iterator.next()!
}
}
var zero = makeIterator()
return zero.next()!
}
}
let test = LinkedList<Int>.value(element: 2, next: LinkedList<Int>.value(element: 4, next: LinkedList<Int>.value(element: 7, next: LinkedList<Int>.value(element: 9, next: LinkedList<Int>.end))))
符合集合的类型应提供startIndex和endIndex属性,并作为O(1)操作提供对元素的下标访问
如何在固定时间内返回下标?它不需要遍历集合,直到找到正确的索引,然后返回该值吗
这是我用来符合集合的LinkedList
:
indirect enum LinkedList<T> {
case value(element: T, next: LinkedList<T>)
case end
}
extension LinkedList: Sequence {
func makeIterator() -> LinkedListIterator<T> {
return LinkedListIterator(current: self)
}
var underestimatedCount: Int {
var count = 0
for _ in self {
count += 1
}
return count
}
}
struct LinkedListIterator<T>: IteratorProtocol {
var current: LinkedList<T>
mutating func next() -> T? {
switch current {
case let .value(element, next):
current = next
return element
case .end:
return nil
}
}
}
间接枚举链接列表{
大小写值(元素:T,下一个:LinkedList)
案例结束
}
扩展链接列表:序列{
func makeIterator()->LinkedListIterator{
返回链接标识符(当前:self)
}
var-dcount:Int{
变量计数=0
为了自己{
计数+=1
}
返回计数
}
}
结构链接标识符:迭代器协议{
当前变量:LinkedList
突变func next()->T{
开关电流{
案例let.value(元素,下一个):
当前=下一个
返回元素
案例.结束:
归零
}
}
}
这就是我实际遵守协议的地方:
extension LinkedList: Collection {
typealias Index = Int
typealias Element = T
var startIndex: Index {
return 0
}
var endIndex: Index {
return underestimatedCount
}
func index(after i: Index) -> Index {
return (i < endIndex) ? i + 1 : endIndex
}
subscript (position: Index) -> Element {
precondition(position < endIndex && position >= startIndex)
var iterator = makeIterator()
for i in 0 ..< position {
iterator.next()
if i + 1 == position {
return iterator.next()!
}
}
var zero = makeIterator()
return zero.next()!
}
}
let test = LinkedList<Int>.value(element: 2, next: LinkedList<Int>.value(element: 4, next: LinkedList<Int>.value(element: 7, next: LinkedList<Int>.value(element: 9, next: LinkedList<Int>.end))))
扩展链接列表:集合{
类型别名索引=Int
typealias元素=T
var startIndex:指数{
返回0
}
var endIndex:索引{
返回数据计数
}
func index(在i:index之后)->index{
返回值(i元素{
前提条件(位置=startIndex)
var iterator=makeIterator()
对于处于0..<位置的i{
迭代器
如果i+1==位置{
返回iterator.next()!
}
}
var zero=makeIterator()
返回零。下一步()!
}
}
让test=LinkedList.value(元素:2,下一个:LinkedList.value(元素:4,下一个:LinkedList.value(元素:7,下一个:LinkedList.value(元素:9,下一个:LinkedList.end)))
集合的索引不必是Int
。一种可能的方法
是使用一个自定义索引类型,该类型引用了相应的
元素。但是,这要求列表节点是类的实例
这是我想出来的。可能还可以改进,,
但希望能证明这一点
类列表节点
存储
元素和指向下一个节点的指针,以及
整数序数
,用于生成结构列表索引
采用可比的
协议
struct ListIndex
包含对列表节点的引用,或nil
对于endIndex
struct LinkedListCollection<T>: Collection {
class ListNode {
let element: T
let next: ListNode?
let ordinal: Int
init(element: T, next: ListNode?, ordinal: Int) {
self.element = element
self.next = next
self.ordinal = ordinal
}
// Create ListNode as the head of a linked list with elements from an iterator.
convenience init?<I: IteratorProtocol>(it: inout I, ordinal: Int = 0) where I.Element == T {
if let el = it.next() {
self.init(element: el, next: ListNode(it: &it, ordinal: ordinal + 1), ordinal: ordinal)
} else {
return nil
}
}
}
struct ListIndex: Comparable {
let node: ListNode?
static func <(lhs: ListIndex, rhs: ListIndex) -> Bool {
// Compare indices according to the ordinal of the referenced
// node. `nil` (corresponding to `endIndex`) is ordered last.
switch (lhs.node?.ordinal, rhs.node?.ordinal) {
case let (r?, l?):
return r < l
case (_?, nil):
return true
default:
return false
}
}
static func ==(lhs: ListIndex, rhs: ListIndex) -> Bool {
return lhs.node?.ordinal == rhs.node?.ordinal
}
}
let startIndex: ListIndex
let endIndex: ListIndex
// Create collection as a linked list from the given elements.
init<S: Sequence>(elements: S) where S.Iterator.Element == T {
var it = elements.makeIterator()
startIndex = ListIndex(node: ListNode(it: &it))
endIndex = ListIndex(node: nil)
}
func index(after i: ListIndex) -> ListIndex {
guard let next = i.node?.next else {
return endIndex
}
return ListIndex(node: next)
}
subscript (position: ListIndex) -> T {
guard let node = position.node else {
fatalError("index out of bounds")
}
return node.element
}
}
您可以查看一下它是如何在Swift中实现的。有关此主题的更实用、理论性较低的教程,您还可以检查并注意undersweedCount
也应该是O(1)。Collection
方法的默认实现假定为O(1)下标,因此如果您使LinkedList
符合Collection
,则,你会发现其中有些太慢了。我认为Collection
s是一些类似数组的东西,它的元素可以随机访问,LinkedList
对我来说是一个序列,而不是集合。@NandiinBao那就是你想的RandomAccessCollection
;一种集合,可以在固定时间内使其索引偏移,也可以在固定时间内测量两个索引之间的距离。一个集合
只是一个序列
,它可以无破坏性地迭代,并且有一个可以下标的索引。通过n
places对索引进行偏移可以在O(n)时间内完成(但下标预计会有一个O(1)实现)。