File: TreeSet.swift

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (84 lines) | stat: -rw-r--r-- 3,904 bytes parent folder | download
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
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift Collections open source project
//
// Copyright (c) 2022 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//

/// An unordered collection of unique elements, optimized for mutating shared
/// copies and comparing different snapshots of the same collection.
///
/// `TreeSet` has the same functionality as a standard `Set`, and
/// it largely implements the same APIs: both are hashed collection
/// types that conform to `SetAlgebra`, and both are unordered -- neither type
/// provides any guarantees about the ordering of their members.
///
/// However, `TreeSet` is optimizing specifically for use cases that
/// need to mutate shared copies or to compare a set value to one of its older
/// snapshots. To use a term from functional programming,
/// `TreeSet` implements a _persistent data structure_.
///
/// The standard `Set` stores its members in a single, flat hash table, and it
/// implements value semantics with all-or-nothing copy-on-write behavior: every
/// time a shared copy of a set is mutated, the mutation needs to make a full
/// copy of the set's storage. `TreeSet` takes a different approach: it
/// organizes its members into a tree structure, the nodes of which can be
/// freely shared across collection values. When mutating a shared copy of a set
/// value, `TreeSet` is able to simply link the unchanged parts of the
/// tree directly into the result, saving both time and memory.
///
/// This structural sharing also makes it more efficient to compare mutated set
/// values to earlier versions of themselves. When comparing or combining sets,
/// parts that are shared across both inputs can typically be handled in
/// constant time, leading to a dramatic performance boost when the two inputs
/// are still largely unchanged:
///
///     var set = TreeSet(0 ..< 10_000)
///     let copy = set
///     set.insert(20_000) // Expected to be an O(log(n)) operation
///     let diff = set.subtracting(copy) // Also O(log(n))!
///     // `diff` now holds the single item 20_000.
///
/// The tree structure also eliminates the need to reserve capacity in advance:
/// `TreeSet` creates, destroys and resizes individual nodes as needed,
/// always consuming just enough memory to store its contents. As of Swift 5.9,
/// the standard collection types never shrink their storage, so temporary
/// storage spikes can linger as unused but still allocated memory long after
/// the collection has shrunk back to its usual size.
///
/// Of course, switching to a tree structure comes with some trade offs. In
/// particular, inserting new items, removing existing ones, and iterating over
/// a `TreeSet` is expected to be a constant factor slower than a standard
/// `Set` -- allocating/deallocating nodes isn't free, and navigating the tree
/// structure requires more pointer dereferences than accessing a flat hash
/// table. However the algorithmic improvements above usually more than make up
/// for this, as long as the use case can make use of them.
@frozen // Not really -- this package is not at all ABI stable
public struct TreeSet<Element: Hashable> {
  @usableFromInline
  internal typealias _Node = _HashNode<Element, Void>

  @usableFromInline
  internal typealias _UnsafeHandle = _Node.UnsafeHandle

  @usableFromInline
  internal var _root: _Node

  @usableFromInline
  internal var _version: UInt

  @inlinable
  internal init(_root: _Node, version: UInt) {
    self._root = _root
    self._version = version
  }

  @inlinable
  internal init(_new: _Node) {
    self.init(_root: _new, version: _new.initialVersionNumber)
  }
}