Skip to content

Commit ffa6599

Browse files
committed
Implemented a Doubly Linked List structure
1 parent 2ce2905 commit ffa6599

File tree

1 file changed

+194
-0
lines changed

1 file changed

+194
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import Foundation
2+
3+
public class Node<Value> {
4+
public var value: Value?
5+
public var next: Node?
6+
public var prev: Node?
7+
8+
public init(value: Value? = nil, next: Node<Value>? = nil, prev: Node<Value>? = nil) {
9+
self.value = value
10+
self.next = next
11+
self.prev = prev
12+
}
13+
}
14+
15+
extension Node: CustomStringConvertible {
16+
public var description: String {
17+
guard let next: Node<Value> = self.next else {
18+
return "\(String(describing: value))"
19+
}
20+
return "\(String(describing: value)) <-> \(String(describing: next)) "
21+
}
22+
}
23+
24+
public struct DoublyLinkedList<Value> {
25+
26+
public var head: Node<Value>?
27+
public var tail: Node<Value>?
28+
public var count: Int = 0
29+
30+
public var isEmpty: Bool {
31+
return head == nil
32+
}
33+
34+
public mutating func push(_ value: Value) {
35+
let new: Node<Value> = Node(value: value, next: head)
36+
if head != nil { head!.prev = new }
37+
head = new
38+
if tail == nil { tail = head }
39+
count += 1
40+
}
41+
42+
public mutating func append(_ value: Value) {
43+
guard !isEmpty else {
44+
push(value)
45+
return
46+
}
47+
tail!.next = Node(value: value, prev: tail)
48+
tail = tail!.next
49+
count += 1
50+
}
51+
52+
@discardableResult
53+
public mutating func insert(_ value: Value,
54+
after node: Node<Value>) -> Node<Value> {
55+
guard tail !== node else {
56+
append(value)
57+
return tail!
58+
}
59+
var new: Node<Value> = Node(value: value, next: node.next, prev: node)
60+
node.next?.prev = new
61+
node.next = new
62+
count += 1
63+
return node.next!
64+
}
65+
66+
@discardableResult
67+
public mutating func insert(_ value: Value,
68+
before node: Node<Value>) -> Node<Value> {
69+
guard head !== node else {
70+
push(value)
71+
return head!
72+
}
73+
var new: Node<Value> = Node(value: value, next: node, prev: node.prev)
74+
node.prev?.next = new
75+
node.prev = new
76+
count += 1
77+
return node.prev!
78+
}
79+
80+
public func node(at index: Int) -> Node<Value>? {
81+
guard index > -1 || index < count else { return nil }
82+
83+
let startFromTail: Bool = index > count / 2
84+
var currentNode: Node<Value>? = startFromTail ? tail : head
85+
var currentIndex: Int = startFromTail ? count - 1 : 0
86+
var change: Int = startFromTail ? -1 : 1
87+
88+
while currentNode != nil {
89+
if currentIndex == index { break }
90+
currentNode = startFromTail ? currentNode!.prev : currentNode!.next
91+
currentIndex += change
92+
}
93+
94+
return currentNode
95+
}
96+
97+
@discardableResult
98+
public mutating func pop() -> Value? {
99+
defer {
100+
head = head?.next
101+
count -= 1
102+
if isEmpty {
103+
tail = nil
104+
} else {
105+
head!.prev = nil
106+
}
107+
}
108+
return head?.value
109+
}
110+
111+
@discardableResult
112+
public mutating func removeLast() -> Value? {
113+
defer {
114+
tail = tail?.prev
115+
count -= 1
116+
if isEmpty {
117+
head = nil
118+
} else {
119+
tail!.next = nil
120+
}
121+
}
122+
return tail?.value
123+
}
124+
125+
@discardableResult
126+
public mutating func remove(after node: Node<Value>) -> Value? {
127+
defer {
128+
if node.next != nil {
129+
count -= 1
130+
}
131+
if node.next === tail {
132+
tail = node
133+
}
134+
if let next2node: Node<Value> = node.next?.next {
135+
next2node.prev = node
136+
}
137+
node.next = node.next?.next
138+
}
139+
return node.next?.value
140+
}
141+
142+
@discardableResult
143+
public mutating func remove(before node: Node<Value>) -> Value? {
144+
defer {
145+
if node.prev != nil {
146+
count -= 1
147+
}
148+
if node.prev === head {
149+
head = node
150+
}
151+
if let prev2node: Node<Value> = node.prev?.prev {
152+
prev2node.next = node
153+
}
154+
node.prev = node.prev?.prev
155+
}
156+
return node.prev?.value
157+
}
158+
}
159+
160+
extension DoublyLinkedList: CustomStringConvertible {
161+
public var description: String {
162+
guard let head: Node<Value> = self.head else {
163+
return "Empty list"
164+
}
165+
return String(describing: head)
166+
}
167+
}
168+
169+
// Here are testing scenarios to run in a Swift playground
170+
171+
/*
172+
var list = DoublyLinkedList<Int>()
173+
174+
list.push(4)
175+
list.push(2)
176+
list.push(1)
177+
178+
list.append(6)
179+
180+
var n = list.node(at: 2)
181+
182+
list.insert(5, after: n!)
183+
list.insert(3, before: n!)
184+
185+
print(list)
186+
187+
print(list.pop()!)
188+
print(list.removeLast()!)
189+
190+
print(list.remove(after: n!)!)
191+
print(list.remove(before: n!)!)
192+
193+
print(list.count)
194+
*/

0 commit comments

Comments
 (0)