Insert node in singly linked list in swift playground - swift

Given a singly linked list, the task is to write a program to insert that element in a linked list in Swift.

import UIKit
class Node<T: Equatable>{
var value:T?
var nextNode:Node?
}
class LinkedList<T: Equatable>{
var headNode = Node<T>()
func insert(value: T){
if headNode.value == nil{
headNode.value = value
}else{
var lastNode = headNode
while lastNode.nextNode != nil {
lastNode = lastNode.nextNode!
}
let newNode: Node = Node<T>()
newNode.value = value
lastNode.nextNode = newNode
}
}
func printAllKeys() {
var currentNode: Node! = headNode
print("---------------")
while currentNode != nil && currentNode.value != nil {
print("The item is \(currentNode.value!)")
currentNode = currentNode.nextNode
}
}
}
var list = LinkedList<Int>()
list.insert(value: 5)
list.insert(value: 10)
list.printAllKeys()

Related

Swiftui + Firestore + CombineLatest keep publishing data

I'm trying to merges two published object from query of two different collections to make a single published array using combineLatest.
import Combine
import Firebase
class FirestoreViewModel: ObservableObject {
let userId: String
#Published var aList: [DocumentA]? = nil
#Published var bList: [DocumentB]? = nil
init(userId: String, listenForChanges: Bool = false) {
// Get the user
if (listenForChanges) {
self.loadA()
self.loadB()
}
}
var cList: AnyPublisher<[DocumentC]?, Never> {
return Publishers.CombineLatest(
$aList.map { (aList) -> [DocumentC]? in
guard let aList = aList else { return nil }
return aList.map {a in
DocumentC(from: a)
}
},
$bList.map { (bList) -> [DocumentC]? in
guard let bList = bList else { return nil }
return bList.map { n in
DocumentC(from: b)
}
})
.map { (aList, bList) -> [DocumentC]? in
if (aList == nil && bList == nil) { return nil }
var cList: [DocumentC] = []
if let aList = aList {
cList.append(contentsOf: aList)
}
if let bList = bList {
cList.append(contentsOf: bList)
}
return cList
}
.eraseToAnyPublisher()
}
private func loadA() {
// Start listening
Firestore.firestore().collection("colA").addSnapshotListener { (snapshot, error) in
if let error = error {
print("DEBUG: Unable to get user data: \(error.localizedDescription)")
return
}
// Invalid data return
guard let snapshot = snapshot else {
print("DEBUG: null data returned")
self.aList = nil
return
}
// Update the info
var aList: [DocumentA] = []
snapshot.documents.forEach { document in
let aData = document.data()
guard !aData.isEmpty else {
return
}
aList.append(DocumentA(from: aData)
}
self.aList = aList
}
}
private func loadB() {
// Start listening
Firestore.firestore().collection("colB").addSnapshotListener { (snapshot, error) in
if let error = error {
print("DEBUG: Unable to get user data: \(error.localizedDescription)")
return
}
// Invalid data return
guard let snapshot = snapshot else {
print("DEBUG: null data returned")
self.bList = nil
return
}
// Update the info
var bList: [DocumentB] = []
snapshot.documents.forEach { document in
let bData = document.data()
guard !bData.isEmpty else {
return
}
bList.append(DocumentB(from: bData))
}
self.userUnits = userUnits
}
}
}
When I debug, I can see that aList and bList are published once, however, the cList keeps been published eventually eating all the memory...
The cList is consumed via a onReceive statement in the view, which output each item.
Would anybody be able to tell me why the combineLatest keeps on publishing cList, though there are no fresh aList or bList published ?
Many thanks in advance.
In all likelihood, you have a situation where you update the view with values just received from cList, which causes the body to be recomputed, which causes another onReceive(vm.cList) {...}, which causes a new publisher to be returned by the computed property cList, which emits the values again and repeats the cycle.
Here's an simplified example of what I mean:
class ViewModel: ObservableObject {
#Published var aList: [Int] = [1,2]
var cList: AnyPublisher<Int, Never> {
$aList.map { $0 + $0 }.eraseToAnyPublisher()
}
}
struct ContentView: View {
#StateObject var vm = ViewModel()
#State var list: [Int] = []
var body: some View {
VStack {
ForEach(list, id: \.self) { v in
Text("\(v)")
}
}
.onReceive(vm.cList) { self.list = $0 }
}
}
To avoid that, cList shouldn't be a computed property. It could just be a lazy-ly assigned constant:
lazy var cList: AnyPublisher<Int, Never> =
$alist.map { $0 + $0 }
.eraseToAnyPublisher()

Reversing list of nodes

I have the following Node class which points to a next node :
class Node<T> {
var data: T
var next: Node<T>?
init(data: T, next: Node<T>?) {
self.data = data
self.next = next
}
}
and I wrote a method to reverse the data , for example
let list = Node<Int>(data:1,next :Node<Int>(data:2,next :Node<Int>(data :3,next :nil)))
which has values 1,2,3 should have values 3,2,1
here is my function :
extension Node {
func reverse() {
var firstNode = self
var previousNode: Node<T>? = nil
var currentNode = firstNode
var nextNode = firstNode.next
while nextNode != nil {
currentNode.next = previousNode
previousNode = currentNode
currentNode = nextNode!
nextNode = currentNode.next
}
currentNode.next = previousNode
firstNode = currentNode
var current = firstNode as Node<T>?
//print 3 2 1
while(current != nil)
{
print(current!.data)
current = current!.next
}
}
}
The printing in the method indeed displays "3 2 1" however, how can I set it to the current object to be the reversed list? Assigning at the end "self = current" seems to be prohibited.
Your list is just a variable of Node<Int> - i.e. a pointer to the head node.
You cannot mutate self to be a reference to a different node - the tail node in the original list, but you could return the last node and re-assign what list points to:
var list = Node<Int>(...)
list = list.reverse()
The reverse function would need to return a Node<T> type:
func reverse() -> Node<T> {
// your algorithm
// ...
return firstNode
}
Btw, your code doesn't account for cycles in the list. If some node points to one of its previous nodes, then your while nextNode != nil will become an infinite loop.
You have no way to know what your linked list is. Add one:
class Node<T> : CustomStringConvertible {
var data: T
var next: Node<T>?
init(data: T, next: Node<T>?) {
self.data = data
self.next = next
}
var description: String {
var s = ""
var node = Optional(self)
while node != nil {
s.append(String(describing:node!.data))
node = node?.next
}
return(s)
}
}
Now it's easy to see that your reverse is working. All you have to do is have it produce a value.
extension Node {
func reverse() -> Node? {
var firstNode = self
var previousNode: Node<T>? = nil
var currentNode = firstNode
var nextNode = firstNode.next
while nextNode != nil {
currentNode.next = previousNode
previousNode = currentNode
currentNode = nextNode!
nextNode = currentNode.next
}
currentNode.next = previousNode
firstNode = currentNode
let current = firstNode as Node<T>?
return current
}
}
Here's a test:
let list = Node<Int>(data:1,next :Node<Int>(data:2,next :Node<Int>(data :3,next :nil)))
print(list) // 123
if let newlist = list.reverse() {
print(newlist) // 321, yay!
}

How to implement doubly linked list in swift?

How can I implement a doubly linked list in Swift with all the operations like insert and deletion?
I know how to implement singly linked list but I can't find a way to make it a doubly linked list. I am a beginner in coding.
import UIKit
struct LinkedList<Value> {
var Head : node<Value>?
var Tail : node<Value>?
var isEmpty : Bool {
return Head == nil
}
// to add at the beginning of the list
mutating func push(_ value : Value) {
Head = node(value: value, nextNode: Head)
if Tail == nil {
Tail = Head
}
}
// to add at the end of the list
mutating func append(_ value : Value) {
guard !isEmpty else {
push(value)
return
}
let newNode = node(value: value)
Tail?.nextNode = newNode
Tail = newNode
}
//to find the node at particular index
func findNode(at index: Int) -> node<Value>? {
var currentIndex = 0
var currentNode = Head
while(currentNode != nil && currentIndex < index) {
currentNode = currentNode?.nextNode
currentIndex += 1
}
return currentNode
}
// to insert at a particular location
func insert(_ value : Value, afterNode : node<Value>) {
afterNode.nextNode = node(value: value, nextNode: afterNode.nextNode)
}
mutating func pop() -> Value? {
defer {
Head = Head?.nextNode
if isEmpty {
Head = nil
}
}
return Head?.value
}
mutating func removeLast() -> Value? {
guard let head = Head else {
return nil
}
guard head.nextNode != nil else {
return pop()
}
var previous = head
var current = head
while let next = current.nextNode {
previous = current
current = next
}
previous.nextNode = nil
Tail = previous
return current.value
}
mutating func remove(after node : node<Value>?) -> Value? {
defer {
if node === Tail {
Tail = node
}
node?.nextNode = node?.nextNode?.nextNode
}
return node?.nextNode?.value
}
}
extension LinkedList : CustomStringConvertible {
var description: String {
guard let linkedListHead = Head else {
return "Empty List"
}
return String(describing: linkedListHead)
}
}
class node<Value> {
var value : Value
var nextNode : node?
init(value : Value , nextNode : node? = nil) {
self.value = value
self.nextNode = nextNode
}
}
extension node : CustomStringConvertible {
var description: String {
guard let nextValue = nextNode else { return "\(value)" }
return "\(value) -> " + String(describing: nextValue) + " "
}
}
var listOfIntegers = LinkedList<Int>()
var listOfStrings = LinkedList<String>()
listOfIntegers.push(1)
listOfIntegers.push(3)
listOfIntegers.push(4)
listOfIntegers.append(6)
let nodeInfo = listOfIntegers.findNode(at: 1)!
listOfIntegers.insert(8, afterNode: nodeInfo)
print(listOfIntegers)
listOfStrings.push("hello")
listOfStrings.push("Sardar Ji!")
print(listOfStrings)
let index = 3
let node2 = listOfIntegers.findNode(at: index - 1)
listOfIntegers.remove(after: node2)
print(listOfIntegers)
I want to implement doubly linked list the same way and the output should be like this:
node1 <-> node2 <-> node3
//here is the full implementaion of doubly-linked-list in swift. updates will be appreciated.
import Foundation
struct DoublyLinkedList<DataItem> {
fileprivate var head : Node<DataItem>?
fileprivate var tail : Node<DataItem>?
var isEmpty : Bool {
return head == nil
}
//to add at the beginning
mutating func InsertAtBeginning(_ dataItem : DataItem) {
let node = Node(dataItem: dataItem, nextNode: head, previousNode: nil)
head?.previousNode = node
head = node
if tail == nil {
tail = head
}
}
//to add at the end
mutating func insertAtEnd(_ dataItem : DataItem) {
guard !isEmpty else {
InsertAtBeginning(dataItem)
return
}
let newNode = Node(dataItem: dataItem, nextNode: nil, previousNode: tail)
tail?.nextNode = newNode
//newNode.previousNode = tail
tail = newNode
}
//to insert at particular node
func insertParticularly(_ dataItem : DataItem , afterNode : Node<DataItem>) {
let node = Node(dataItem: dataItem)
afterNode.nextNode?.previousNode = node
node.nextNode = afterNode.nextNode
afterNode.nextNode = node
node.previousNode = afterNode
}
//to find a node at particular index
func findNode(at index : Int) -> Node<DataItem>? {
var currentIndex = 0
var currentNode = head
while currentNode != nil && currentIndex < index {
currentNode = currentNode?.nextNode
currentIndex += 1
}
return currentNode
}
//MARK:- remove functionality
//remove the first element
mutating func removeFirst() -> DataItem? {
defer {
head = head?.nextNode
if isEmpty {
head = nil
}
}
return head?.dataItem
}
// remove the last element
mutating func removeLast() -> DataItem? {
guard let headValue = head else {
return nil
}
guard headValue.nextNode != nil else {
return removeFirst()
}
var previous = headValue
var current = headValue
while let next = current.nextNode {
previous = current
current = next
}
previous.nextNode = nil
tail = previous
return current.dataItem
}
// remove from a specific location
mutating func removeAt(at node : Node<DataItem>?) -> DataItem? {
defer {
if node === tail {
removeLast()
}
node?.previousNode?.nextNode = node?.nextNode
node?.nextNode?.previousNode = node?.previousNode
}
return node?.nextNode?.dataItem
}
}
extension DoublyLinkedList : CustomStringConvertible {
var description : String {
guard let doublyLinkedListHead = head else { return "UnderFlow"}
//return String(describing: doublyLinkedListHead)
return doublyLinkedListHead.linkedDescription
}
}
class Node<DataItem> {
var dataItem : DataItem
var nextNode : Node?
var previousNode : Node?
init(dataItem : DataItem , nextNode : Node? = nil , previousNode : Node? = nil) {
self.dataItem = dataItem
self.nextNode = nextNode
self.previousNode = previousNode
}
}
extension Node : CustomStringConvertible {
var description: String {
return ((previousNode == nil) ? "nil" : "\(previousNode!.dataItem)") +
" <-> \(dataItem) <-> " +
((nextNode == nil) ? "nil" : "\(nextNode!.dataItem)")
}
var linkedDescription: String {
return "\(dataItem)" + ((nextNode == nil) ? "" : " <-> \(nextNode!.linkedDescription)")
}
}
var list = DoublyLinkedList<Int>()
list.InsertAtBeginning(4)
list.insertAtEnd(5)
list.insertAtEnd(4)
list.insertAtEnd(7)
list.insertAtEnd(2)
list.insertAtEnd(0)
list.description
let node1 = list.findNode(at: 3)
node1?.previousNode
list.head
Fundamentally, your problem is that you've got head and tail pointers in LinkedList, but node only has nextNode pointer. If node is the structure representing each item in the list, and if you want to be able to traverse the list in either direction, then each item needs a link to the next item and also the previous item. That's why they call it a "doubly linked list" after all.
Add a previousNode pointer to your node structure.
Go find every spot in your code where you modify a nextNode pointer and change the code to also maintain the previousNode pointer.

Nilling out optional not working in BST implementation

I am implementing a BST and working on the remove() function, problem is when I try to nil out the node to remove i.e. current, it still exists when I print the trees structure.
class Node<T : Comparable> {
var value: T
var left: Node<T>?
var right: Node<T>?
init(_ value:T) {
self.value = value
}
}
func remove(_ value:T) {
var current: Node<T>? = root
while let root = current {
if value == root.value {
if let _ = root.left, let right = root.right {
let minValue = getMinValue(right)
root.value = minValue
remove(minValue)
} else if let left = root.left {
root.value = left.value
root.left = nil
} else if let right = root.right {
root.value = right.value
root.left = nil
} else {
//This doesn't remove the reference completely
current = nil
}
} else if value > root.value {
current = root.right
} else {
current = root.left
}
}
}
My print function still prints out the node I removed in the previous function
private func printTree(_ node:Node<T>?){
guard let root = node else {
return
}
print(root.value)
printTree(root.right)
printTree(root.left)
}
Unfortunately you just set the local variable current to nil. The parent node of current still has a reference of the node you are trying to remove.

Sorting mixed String-Int Strings numerically as the primary order, then alphabetically in swift

For a String which have both String and Int values (one of each) is it possible to do simple sort that will give the items ordered in numerical order as the primary order and alphabetical as the secondary order
var nameArray = ["Dave7", "Bob8", "Cathy9", "Henry10", "Susan10", "Pat11", "Steve12", "Dan12", "Ken1", "Sean2", "Howard3", "Dixie3", "Newman5", "Billy6"]
var sortedNameArray = nameArray.sort { $0.compare($1, options: .NumericSearch) == .OrderedAscending }
print(sortedNameArray) // gives the following:
Don't want this -> ["Billy6", "Bob8", "Cathy9", "Dan12", "Dave7", "Dixie3", "Henry10", "Howard3", "Ken1", "Newman5", "Pat11", "Sean2", "Steve12", "Susan10"]
Even though .NumericSearch was used the result is alphabetical.
I was able to get the desired result using a custom binary tree. Which gives the results:
Ken1 Sean2 Dixie3 Howard3 Newman5 Billy6 Dave7 Bob8 Cathy9 Henry10 Susan10 Pat11 Dan12 Steve12
But is there a simpler solution?
extension String {
var integerValue: Int? {
return Int(self)
}
}
func extractValueFromString(theString:String)->Int{
var catNumber: [Character] = []
//print("theString \(theString)")
for character in theString.characters{
var characterString = String(character)
if var value = characterString.integerValue { //if we don't check program crashes
//if numberSet.contains(Int(String(character))!) { //another way to check but redundant here
catNumber.append(character)
//print(catNumber)
// }
}
}
let numberString = String(catNumber)
return Int(numberString)!
}
class Node{
//nodes now only arrange strings
var data = ""
var value = Int()
var left:Node?;
var right:Node?;
deinit {
//print("deleting \(data)")
// print("node deleted")
}
init(data:String){
self.data = data;
//print(data)
}
}
class binaryTreeSort{
var root:Node?
init(){
}
deinit {
//print("tree deleted")
}
func getRoot()->Node{
return root!
}
func insertNewValue(data:String){
let newNode = Node(data:data)
var node:Node? = root
if (node == nil){
root = newNode
}
while (node != nil) {
let currentValue = node?.data
if currentValue == ""{
node?.data = data
return
}
if currentValue == data {
//we don't want duplicates.
return
}
if extractValueFromString(currentValue!) < extractValueFromString(data) {
if (node!.right != nil) {
node = node!.right
//print("Going Right at data \(node!.data)")
}else{
node!.right = newNode
//print("Going New Right at data \(node!.data)")
return
}
}else if extractValueFromString(currentValue!) == extractValueFromString(data){
if currentValue < data {
if (node!.right != nil) {
node = node!.right
//print("Going Right at data \(node!.data)")
}else{
node!.right = newNode
//print("Going New Right at data \(node!.data)")
return
}
}else{
if (node!.left != nil) {
//print("Going Left at data \(node!.data)")
node = node!.left
}else{
node!.left = newNode
//print("Going New Left at data \(node!.data)")
return
}
}
}
else{
if (node!.left != nil) {
//print("Going Left at data \(node!.data)")
node = node!.left
}else{
node!.left = newNode
//print("Going New Left at data \(node!.data)")
return
}
}
}
}
func inorderPrint(baseNode:Node){
if(baseNode.left != nil)
{
inorderPrint(baseNode.left!);
//print(" \(baseNode.data)")
}
print("\(baseNode.data)")
if(baseNode.right != nil)
{
inorderPrint(baseNode.right!)
//print(" \(baseNode.data)")
}
}
func reverseOrderPrint(baseNode:Node){
if(baseNode.right != nil)
{
reverseOrderPrint(baseNode.right!)
//print(" \(baseNode.data)")
}
print("\(baseNode.data)")
if(baseNode.left != nil)
{
reverseOrderPrint(baseNode.left!);
//print(" \(baseNode.data)")
}
}
}
var myBinaryTreeSort:binaryTreeSort? = binaryTreeSort()
for item in nameArray{
//print(item)
myBinaryTreeSort!.insertNewValue(item)
}
myBinaryTreeSort!.inorderPrint(myBinaryTreeSort!.getRoot())
print("---------------")
myBinaryTreeSort!.reverseOrderPrint(myBinaryTreeSort!.getRoot())
myBinaryTreeSort = nil //delete the tree
Use map to split the names into parts, sort to sort by number and name, and then map to restore the original:
func splitName(name:String) -> (String, Int) {
if let range = name.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()) {
return (name[name.startIndex..<range.startIndex], Int(name[range.startIndex..<name.endIndex])!)
} else {
return (name, 0)
}
}
print(nameArray.map(splitName).sort({ lhs, rhs in
if lhs.1 < rhs.1 {
return true
} else if lhs.1 > rhs.1 {
return false
} else {
return lhs.0 < rhs.0
}
}).map({ "\($0.0)\($0.1)" }))
Some other ways it could be done would be to maintain element 0 of the tuple as the full name (with numbers) and then the final map just becomes map({ $0.0 }) Depending on sizes, this may be more optimal than splitting the name each time it's compared.
If you have an array, you can sort with a custom closure.
For example:
nameArray.sort({extractValueFromString($0) < extractValueFromString($1)})
Will get you close. You just need to check if they are equal and return $0 < $1 instead.
Here's how I solved this, doing something similar to what #Lou-Franco alluded to:
func endInteger(word: String) -> Int {
if let range = word.rangeOfCharacterFromSet(NSCharacterSet.decimalDigitCharacterSet()){
let numberSubstring = word.substringFromIndex(range.startIndex)
return Int(numberSubstring) ?? 0
}
return 0
}
let sortedArray = yourArray.sort{endInteger($1) > endInteger($0)}