Skip to content

Commit

Permalink
Merge pull request #2 from prolificinteractive/feature/linked-list-da…
Browse files Browse the repository at this point in the history
…ta-structure

Added linked list data structure
  • Loading branch information
ThibaultKlein authored Aug 31, 2018
2 parents 580291f + 8b5d887 commit fae1cf5
Show file tree
Hide file tree
Showing 8 changed files with 418 additions and 42 deletions.
10 changes: 10 additions & 0 deletions DevKit.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,14 @@ Collection of commonly used swift code.
end
end

# ==== Data Structures =====================================================================================================

s.subspec 'DataStructures' do |sp|

# Linked List
sp.subspec 'LinkedList' do |ssp|
ssp.source_files = 'DevKit/DevKit/Classes/Data\ Structures/Linked\ List/*'
end
end

end
56 changes: 52 additions & 4 deletions DevKit/DevKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
2052469C209B9C250067A328 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2052469A209B9C250067A328 /* Main.storyboard */; };
2052469E209B9C270067A328 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2052469D209B9C270067A328 /* Assets.xcassets */; };
205246A1209B9C270067A328 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2052469F209B9C270067A328 /* LaunchScreen.storyboard */; };
205246AC209B9C270067A328 /* DevKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 205246AB209B9C270067A328 /* DevKitTests.swift */; };
205246B7209B9C270067A328 /* DevKitUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 205246B6209B9C270067A328 /* DevKitUITests.swift */; };
205246CB209B9D2B0067A328 /* CalendarPermissionsValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 205246C7209B9D2B0067A328 /* CalendarPermissionsValidator.swift */; };
205246CC209B9D2B0067A328 /* CalendarPermissionsValidatorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 205246C8209B9D2B0067A328 /* CalendarPermissionsValidatorDelegate.swift */; };
Expand Down Expand Up @@ -43,6 +42,9 @@
205C74EE2135A3D700AF0B52 /* KeyboardObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 205C74EB2135A3D700AF0B52 /* KeyboardObserver.swift */; };
205C74EF2135A3D700AF0B52 /* ReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 205C74ED2135A3D700AF0B52 /* ReusableView.swift */; };
329452415E472FA3C293B641 /* Pods_DevKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4DC5340BFE3332A9CE19D779 /* Pods_DevKit.framework */; };
8E8F4AB52138698B00E2FD66 /* LinkedListNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E8F4AB42138698B00E2FD66 /* LinkedListNode.swift */; };
8E8F4AB7213869E000E2FD66 /* LinkedList.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E8F4AB6213869E000E2FD66 /* LinkedList.swift */; };
8E8F4ABC2138731500E2FD66 /* LinkedListTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E8F4ABB2138731500E2FD66 /* LinkedListTests.swift */; };
D7C6243C4F18537B1510C7A1 /* Pods_DevKitUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3939CE1C2FCEB6AE9D5E4974 /* Pods_DevKitUITests.framework */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -72,7 +74,6 @@
205246A0209B9C270067A328 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
205246A2209B9C270067A328 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
205246A7209B9C270067A328 /* DevKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DevKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
205246AB209B9C270067A328 /* DevKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevKitTests.swift; sourceTree = "<group>"; };
205246AD209B9C270067A328 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
205246B2209B9C270067A328 /* DevKitUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DevKitUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
205246B6209B9C270067A328 /* DevKitUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DevKitUITests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -108,6 +109,9 @@
439C165EDA375DDFA28D0AB6 /* Pods-DevKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DevKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-DevKit/Pods-DevKit.release.xcconfig"; sourceTree = "<group>"; };
4DC5340BFE3332A9CE19D779 /* Pods_DevKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DevKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
61E76AB64DDE67385EB88E7F /* Pods-DevKitUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DevKitUITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DevKitUITests/Pods-DevKitUITests.debug.xcconfig"; sourceTree = "<group>"; };
8E8F4AB42138698B00E2FD66 /* LinkedListNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedListNode.swift; sourceTree = "<group>"; };
8E8F4AB6213869E000E2FD66 /* LinkedList.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedList.swift; sourceTree = "<group>"; };
8E8F4ABB2138731500E2FD66 /* LinkedListTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkedListTests.swift; sourceTree = "<group>"; };
9D986637F245DC8CE1CCA9B0 /* Pods-DevKitUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DevKitUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-DevKitUITests/Pods-DevKitUITests.release.xcconfig"; sourceTree = "<group>"; };
A70409DC5600E02F5134B243 /* Pods-DevKitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DevKitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DevKitTests/Pods-DevKitTests.debug.xcconfig"; sourceTree = "<group>"; };
AA8FB83E8BE3E5509A2577E0 /* Pods_DevKitTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DevKitTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -180,7 +184,7 @@
205246AA209B9C270067A328 /* DevKitTests */ = {
isa = PBXGroup;
children = (
205246AB209B9C270067A328 /* DevKitTests.swift */,
8E8F4AB8213872F200E2FD66 /* Classes */,
205246AD209B9C270067A328 /* Info.plist */,
);
path = DevKitTests;
Expand All @@ -198,6 +202,7 @@
205246C4209B9D2B0067A328 /* Classes */ = {
isa = PBXGroup;
children = (
8E8F4AB22138696E00E2FD66 /* Data Structures */,
20524718209BB2BC0067A328 /* Views */,
2052471A209BB2F30067A328 /* Utility */,
205246DA209BA86F0067A328 /* Extensions */,
Expand Down Expand Up @@ -476,6 +481,47 @@
name = Pods;
sourceTree = "<group>";
};
8E8F4AB22138696E00E2FD66 /* Data Structures */ = {
isa = PBXGroup;
children = (
8E8F4AB32138697600E2FD66 /* Linked List */,
);
path = "Data Structures";
sourceTree = "<group>";
};
8E8F4AB32138697600E2FD66 /* Linked List */ = {
isa = PBXGroup;
children = (
8E8F4AB42138698B00E2FD66 /* LinkedListNode.swift */,
8E8F4AB6213869E000E2FD66 /* LinkedList.swift */,
);
path = "Linked List";
sourceTree = "<group>";
};
8E8F4AB8213872F200E2FD66 /* Classes */ = {
isa = PBXGroup;
children = (
8E8F4AB9213872F900E2FD66 /* Data Structures */,
);
path = Classes;
sourceTree = "<group>";
};
8E8F4AB9213872F900E2FD66 /* Data Structures */ = {
isa = PBXGroup;
children = (
8E8F4ABA2138730100E2FD66 /* Linked List */,
);
path = "Data Structures";
sourceTree = "<group>";
};
8E8F4ABA2138730100E2FD66 /* Linked List */ = {
isa = PBXGroup;
children = (
8E8F4ABB2138731500E2FD66 /* LinkedListTests.swift */,
);
path = "Linked List";
sourceTree = "<group>";
};
B4EADB9A0901D69BD2E4AFA6 /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -719,6 +765,7 @@
205246D8209BA3480067A328 /* ShadowOptions.swift in Sources */,
205C74EE2135A3D700AF0B52 /* KeyboardObserver.swift in Sources */,
205246CC209B9D2B0067A328 /* CalendarPermissionsValidatorDelegate.swift in Sources */,
8E8F4AB7213869E000E2FD66 /* LinkedList.swift in Sources */,
20524724209BB3550067A328 /* StringExtension.swift in Sources */,
205246F0209BA8B40067A328 /* UIScreenExtension.swift in Sources */,
205246F9209BA8B40067A328 /* UICollectionViewExtension.swift in Sources */,
Expand All @@ -739,6 +786,7 @@
205246EF209BA8B40067A328 /* UIScrollViewExtension.swift in Sources */,
205246F8209BA8B40067A328 /* UIImageExtension.swift in Sources */,
205246D5209BA3200067A328 /* TransitioningNavigationViewOptions.swift in Sources */,
8E8F4AB52138698B00E2FD66 /* LinkedListNode.swift in Sources */,
205246D3209B9E8F0067A328 /* TransitioningNavigationView.swift in Sources */,
20524697209B9C250067A328 /* AppDelegate.swift in Sources */,
20524720209BB3240067A328 /* CameraPhotoLibraryPermissionsValidator.swift in Sources */,
Expand All @@ -751,7 +799,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
205246AC209B9C270067A328 /* DevKitTests.swift in Sources */,
8E8F4ABC2138731500E2FD66 /* LinkedListTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
187 changes: 187 additions & 0 deletions DevKit/DevKit/Classes/Data Structures/Linked List/LinkedList.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
//
// LinkedList.swift
// DevKit
//
// Created by Thibault Klein on 8/30/18.
// Copyright © 2018 Jonathan Samudio. All rights reserved.
//

import Foundation

/// Linked List.
/// A linked list is a linear collection of data elements where each element points to the next. A linked list has several theoretical advantages over contiguous storage options such as the Swift Array:
/// - Constant time insertion and removal from the front of the list.
/// - Reliable performance characteristics.
///
///
/// - Note:
/// Use a linked list over a Swift array if you need to store a large amount of data and you need to perform
/// insertions and removals from any position in the sequence.
///
/// Do not use a linked list if you need indexing, sorting, random access to the data or sequence traversal from the back of the sequence to the front.
///
/// - Warning: Due to the fact that each node has a reference to the next node, the memory footprint of a linked list can have a negative impact on the device if the list becomes extremely large.
open class LinkedList<T> {

// MARK: - Public Properties
public var head: LinkedListNode<T>?
public var tail: LinkedListNode<T>?

/// `true` if the linked list is empty. `false` if not.
public var isEmpty: Bool {
return head == nil
}

// MARK: - Initialization

public init() { }

// MARK: - General Functions

// MARK: - Public Functions

/// Returns the linked list head's value.
///
/// - Returns: The head's value.
public func peek() -> T? {
return head?.value
}

/// Returns the node at the given index, or nil if the node can't be found.
///
/// - Complexity: O(n)
/// - Parameter index: The index to use.
/// - Returns: The node at the given index.
public func node(at index: Int) -> LinkedListNode<T>? {
var currentIndex = 0
var currentNode = head

while let current = currentNode, currentIndex != index {
currentNode = current.next
currentIndex += 1
}

return currentNode
}

// MARK: Adding Functions

/// Adds a value at the beginning of the linked list.
///
/// - Complexity: O(1)
/// - Parameter value: The value to add.
/// - Returns: The newly added node.
@discardableResult
public func push(_ value: T) -> LinkedListNode<T> {
guard !isEmpty else {
head = LinkedListNode(value: value)
tail = head

return head!
}

let node = LinkedListNode(value: value, next: head)
head = node

return node
}

/// Appends a value at the end of the linked list.
///
/// - Complexity: O(1)
/// - Parameter value: The value to add.
/// - Returns: The newly added node.
@discardableResult
public func append(_ value: T) -> LinkedListNode<T> {
guard !isEmpty else {
return push(value)
}

let node = LinkedListNode(value: value)
tail?.next = node
tail = node

return node
}

/// Inserts a value after the given node.
///
/// - Complexity: O(1)
/// - Parameters:
/// - value: The value to insert.
/// - node: The node to add after.
/// - Returns: The newly added node.
@discardableResult
public func insert(value: T, after node: LinkedListNode<T>) -> LinkedListNode<T> {
guard tail !== node else {
return append(value)
}

let newNode = LinkedListNode(value: value)
newNode.next = node.next
node.next = newNode

return newNode
}

// MARK: Removing Functions

/// Removes the value at the top of the list.
///
/// - Complexity: O(1)
/// - Returns: The value at top of the list.
public func pop() -> T? {
defer {
head = head?.next
if isEmpty {
tail = nil
}
}

return head?.value
}

/// Removes the last node of the list.
///
/// - Complexity: O(n)
/// - Returns: The value at the end of the list.
public func removeLast() -> T? {
guard !isEmpty else {
return nil
}

guard head?.next != nil else {
return pop()
}

var prev = head
var currentNode = head?.next
while currentNode?.next != nil {
currentNode = currentNode?.next
prev = prev?.next
}

prev?.next = nil
tail = prev

return currentNode?.value
}

/// Removes the node after the given node.
///
/// - Complexity: O(1)
/// - Parameter node: The node to use.
/// - Returns: The value removed.
@discardableResult
public func remove(after node: LinkedListNode<T>) -> T? {
defer {
if node.next === tail {
tail = node
}
node.next = node.next?.next
}

return node.next?.value
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// LinkedListNode.swift
// DevKit
//
// Created by Thibault Klein on 8/30/18.
// Copyright © 2018 Jonathan Samudio. All rights reserved.
//

import Foundation

/// Describes a node in a linked list.
open class LinkedListNode<T> {

// MARK: - Public Properties
public var value: T
public var next: LinkedListNode?

// MARK: - Initialization

public init(value: T, next: LinkedListNode? = nil) {
self.value = value
self.next = next
}

}
Loading

0 comments on commit fae1cf5

Please sign in to comment.