diff --git a/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/Contents.swift b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/Contents.swift new file mode 100644 index 0000000..2770518 --- /dev/null +++ b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/Contents.swift @@ -0,0 +1,250 @@ +import UIKit + +protocol LinkedList: class, Sequence, CustomStringConvertible { + associatedtype T + var count: Int { get } + var isEmpty: Bool { get } + func add(value: T) + func remove(value: T) -> Bool + func remove(index: Int) throws -> Bool +} + +enum LinkedListError: Error { + case indexOutOfBounds +} + +extension LinkedList { + public var description: String { + var text = "" + for node in self { + if !text.isEmpty { + text += ", " + } + text += "\(node)" + } + return "[\(text)]" + } +} + +extension LinkedList where T == Self.Element { + func append(contentsOf elements: Self) { + for e in elements { + self.add(value: e) + } + } +} + +public struct LinkedListIterator: IteratorProtocol { + private var current: Node? + + init(head: Node?) { + current = head + } + public mutating func next() -> T? { + guard let this = current else { + return nil + } + current = this.next + return this.value + } +} + +public class Node: CustomStringConvertible { + let value: T + var next: Node? + var prev: Node? + + init(value: T) { + self.value = value + } + public var description: String { + return "node:\(value)" + } +} + +public class SinglyLinkedList: LinkedList { + private var head: Node? + private var tail: Node? + private var size: Int = 0 + + public func add(value: T) { + let node = Node(value: value) + if isEmpty { + head = node + } else { + tail?.next = node + } + tail = node + size += 1 + } + public func remove(value: T) -> Bool { + var prev: Node? + var node = head + while node != nil { + if node!.value == value { + size -= 1 + unlink(prev: prev, node: node) + return true + } + prev = node + node = node?.next + } + return false + } + public func remove(index: Int) throws -> Bool { + if index < 0 || index >= size { + throw LinkedListError.indexOutOfBounds + } + var prev: Node? + var node = head + var i = 0 + while node != nil && i < size { + if i == index { + size -= 1 + unlink(prev: prev, node: node) + return true + } + prev = node + node = node?.next + i += 1 + } + return false + } + private func unlink(prev: Node?, node: Node?) { + let next = node?.next + if prev == nil { + head = next + } else { + prev?.next = next + } + } + public var isEmpty: Bool { + return head == nil + } + public var count: Int { + return size + } + public func makeIterator() -> LinkedListIterator { + return LinkedListIterator(head: head) + } +} + + +var list = SinglyLinkedList() +list.add(value: "A") +list.add(value: "B") +list.add(value: "C") +list.add(value: "D") +list.remove(value: "B") +do { + try list.remove(index: 1) + try list.remove(index: 99) +} catch { + print("Unexpected error: \(error).") +} + +print(list) +for element in list { + print(element) +} + + +public class DoublyLinkedList: LinkedList { + private var head: Node? + private var tail: Node? + private var size: Int = 0 + + public func add(value: T) { + let node = Node(value: value) + if isEmpty { + head = node + } else { + tail?.next = node + node.prev = tail + } + tail = node + size += 1 + } + public func remove(value: T) -> Bool { + var prev: Node? + var node = head + while node != nil { + if node!.value == value { + size -= 1 + unlink(prev: prev, node: node) + return true + } + prev = node + node = node?.next + } + return false + } + public func remove(index: Int) throws -> Bool { + if index < 0 || index >= size { + throw LinkedListError.indexOutOfBounds + } + var prev: Node? + var node = head + var i = 0 + while node != nil && i < size { + if i == index { + size -= 1 + unlink(prev: prev, node: node) + return true + } + prev = node + node = node?.next + i += 1 + } + return false + } + private func unlink(prev: Node?, node: Node?) { + let next = node?.next + if prev == nil { + head = next + } else { + prev?.next = next + } + if next != nil { + next?.prev = prev + } + } + public var isEmpty: Bool { + return head == nil + } + public var count: Int { + return size + } + public func makeIterator() -> LinkedListIterator { + return LinkedListIterator(head: head) + } + public func reverse() -> DoublyLinkedList { + var node = head + while let current = node { + node = current.next + swap(¤t.next, ¤t.prev) + head = current + } + return self + } +} + +let list2 = DoublyLinkedList() +list2.add(value: "A") +list2.add(value: "B") +list2.add(value: "C") +list2.add(value: "D") +print(list2) +list2.reverse() +print(list2) +for element in list2.reversed() { + print(element) +} + +print("--------") +var list3 = SinglyLinkedList() +list3.add(value: "1") +list3.add(value: "2") +list3.add(value: "3") +list.append(contentsOf: list3) +print(list) diff --git a/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/contents.xcplayground b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/contents.xcplayground new file mode 100644 index 0000000..9f5f2f4 --- /dev/null +++ b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/playground.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/homeworks/sergii.suprun_differz/homework_2/LinkedList.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + +