From aedd3470a7c76b47c23e507b35861ac7227aa822 Mon Sep 17 00:00:00 2001 From: Paridhi Malviya Date: Wed, 31 Dec 2025 00:33:32 -0600 Subject: [PATCH] Implement Stack using array. Implement Stack using Linked list. Implement Singly linked list. --- Precourse1-Swift/LinkedList.swift | 91 ++++++++++ .../LinkedListToStackAdapter.swift | 159 ++++++++++++++++++ Precourse1-Swift/SinglyLinkedList.swift | 73 ++++++++ Precourse1-Swift/Stack.swift | 75 +++++++++ 4 files changed, 398 insertions(+) create mode 100644 Precourse1-Swift/LinkedList.swift create mode 100644 Precourse1-Swift/LinkedListToStackAdapter.swift create mode 100644 Precourse1-Swift/SinglyLinkedList.swift create mode 100644 Precourse1-Swift/Stack.swift diff --git a/Precourse1-Swift/LinkedList.swift b/Precourse1-Swift/LinkedList.swift new file mode 100644 index 000000000..2ec4ea080 --- /dev/null +++ b/Precourse1-Swift/LinkedList.swift @@ -0,0 +1,91 @@ +// +// LinkedList.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 12/16/25. +// + + +/* + To implement a linked list, we need two primary components + A Node class - to hold the data aand reference ot the next node + LinkedList class - to manage the nodes and provide methods for operations like insertion and traversal + */ + +class Node { + var value: T + var next: Node? //refrence to the next node in the linkedlist. + + init(value: T, next: Node? = nil) { + self.value = value + self.next = next + } +} + +//the linkedlist class +class LinkedList { + private var head: Node? + private var tail: Node? + + var isEmpty: Bool { + return head == nil + } + + init() { + + } +} + +//append - insert at the end of the LinkedList +extension LinkedList { + func append(value: T) { + let newNode = Node(value: value) + if let currentTail = tail { + currentTail.next = newNode + } else { + //If the list was empty, then the new node is both head and tail + head = newNode + } + tail = newNode + } + + //prepend - insert at the beginning + //This add a new node to the front of the list, which is an O(1) operation. + func prepend(value: T) { + let newNode = Node(value: value) + if let currentHead = head { + newNode.next = currentHead + } else { + //if the list is empty then head and tail both will be the new node + tail = newNode + } + head = newNode + } +} + +//Traversal and display (optional, for testing) +extension LinkedList: CustomStringConvertible { + //you can loop through the list to print it's elements. Can make linkedList conform to the CustomStringConvertible to easily prints it's elements + var description: String { + var text = "[" + var currentHead = head + while let node = currentHead { + text += "\(node.value)" + currentHead = node.next + if currentHead != nil { + text += ", " + } + } + return text + "]" + } +} + +class LinkedListPractice { + init() { + let linkedList = LinkedList() + linkedList.append(value: "a") + linkedList.append(value: "b") + linkedList.append(value: "c") + print(linkedList) + } +} diff --git a/Precourse1-Swift/LinkedListToStackAdapter.swift b/Precourse1-Swift/LinkedListToStackAdapter.swift new file mode 100644 index 000000000..d4294a015 --- /dev/null +++ b/Precourse1-Swift/LinkedListToStackAdapter.swift @@ -0,0 +1,159 @@ +// +// LinkedListToStackAdapter.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 12/16/25. +// + +//Implement stack using linked list + +class LLNode { + var value: T + var next: LLNode? + + init(value: T, next: LLNode?) { + self.value = value + self.next = next + } +} + +class LLLinkedList { + private var head: LLNode? + private var tail: LLNode? + + var isEmpty: Bool { + return head == nil + } + + var count: Int { + var currentHead = head + var count = 0 + while (currentHead != nil) { + count += 1 + currentHead = currentHead?.next + } + return count + } + + init() { + + } +} + +extension LLLinkedList { + func append(value: T) { + let newNode = LLNode(value: value, next: nil) + if head == nil { + //means linkedlist is empty, so set the newnode as the head and tail both + tail = newNode + head = newNode + } else { + //if linked list is not empty then do normal appending + tail?.next = newNode + tail = newNode + } + } + + func prepend(value: T) { + let newNode = LLNode(value: value, next: nil) + if head == nil { + //linked list is empty + head = LLNode(value: value, next: nil) + tail = head + } else { + // linked list is not empty + newNode.next = head + head = newNode + } + } + + func removeFirstNode() -> LLNode? { + if (head == nil) { + //it means the ll is empty + return nil + } else { + //if the ll is not empty + let currentHead = head + if let nextNode = head?.next { + head = nextNode + } else if (head?.next == nil) { + head = nil + } + return currentHead + } + } + + var currentHead: LLNode? { + return head + } +} + +extension LLLinkedList: CustomStringConvertible { + var description: String { + var currentNode = head + var descString = "[" + while currentNode != nil { + descString += "\(String(describing: currentNode?.value))" + currentNode = currentNode?.next + if (currentNode != nil) { + descString += "," + } + } + return descString + } +} + +class StackUsingLL: CustomStringConvertible { + private var llList: LLLinkedList? + + init(llList: LLLinkedList) { + self.llList = llList + } + + func push(value: T) { + //append the first element at the start of the linked list + llList?.prepend(value: value) + } + + func pop() -> T? { + //remove the first node from the linked list and return it. + let removedItem = llList?.removeFirstNode() + return removedItem?.value + } + + func peek() -> T? { + return llList?.currentHead?.value + } + + func isEmpty() -> Bool { + return llList?.isEmpty ?? true + } + + var description: String { + var currentHead = llList?.currentHead + var descString = "[" + while (currentHead != nil) { + descString += "\(currentHead!.value)" + currentHead = currentHead!.next + if (currentHead != nil) { + descString += "," + } + } + return descString + } +} + +class LinkedListToStackAdapter { + + init() { + let stack = StackUsingLL(llList: LLLinkedList()) + stack.push(value: 2) + stack.push(value: 3) + stack.push(value: 6) + let poppedElement = stack.pop() + print("popped element \(poppedElement, default: "NA")") + let topElement = stack.peek() + print("topElement \(topElement, default: "NA")") + print("printed linked list \(stack.description)") + } +} diff --git a/Precourse1-Swift/SinglyLinkedList.swift b/Precourse1-Swift/SinglyLinkedList.swift new file mode 100644 index 000000000..b06282cc6 --- /dev/null +++ b/Precourse1-Swift/SinglyLinkedList.swift @@ -0,0 +1,73 @@ +// +// SinglyLinkedList.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 12/17/25. +// + +class SinglyLLNode { + var value: T + var next: SinglyLLNode? + + init(value: T, next: SinglyLLNode?) { + self.value = value + self.next = next + } +} + +class SinglyLinkedList { + + private var head: SinglyLLNode? + private var tail: SinglyLLNode? + + public init() { + + } + + public var isEmpty: Bool { + return head == nil + } + + //adds a new node at the fron tof the list O(1) operation + public func push(_ value: T) { + head = SinglyLLNode(value: value, next: head) + if tail == nil { + tail = head + } + } + + //Adds a new node at the end of the list with O(1) operation if tail reference is kept + func append(value: T) { + guard !isEmpty else { + push(value) + return + } + //the current tail's next pointer is set to the new node + tail?.next = SinglyLLNode(value: value, next: nil) + //the new node becomes the new tail + tail = tail?.next + } + + public func displayList() { + var currentHead = head + while currentHead != nil { + print("\(currentHead!.value) -> ") + currentHead = currentHead?.next + } + } + + public func currentHead() -> SinglyLLNode? { + return self.head + } +} + +class SinglyLinkedListImpl { + init() { + let linkedlist = SinglyLinkedList() + linkedlist.append(value: 1) + linkedlist.append(value: 2) + linkedlist.push(30) + print("Linked list contents:") + linkedlist.displayList() + } +} diff --git a/Precourse1-Swift/Stack.swift b/Precourse1-Swift/Stack.swift new file mode 100644 index 000000000..67cd4f19d --- /dev/null +++ b/Precourse1-Swift/Stack.swift @@ -0,0 +1,75 @@ +// +// Stack.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 12/16/25. +// + +//Implement Stack + +struct Stack { + private var storage: [T] = [] + + //checks if the stack is empty + var isEmpty: Bool { + return storage.isEmpty + } + + //returns the number of elements in the stack + var count: Int { + return storage.count + } + + //adds a new element to the top of the stack + mutating func push(element: T) { + storage.append(element) + } + + //pop - pops the last element and returns the last element + mutating func pop() -> T? { + return storage.popLast() + } + + func peek() -> T? { + return storage.last + } + + func printDescription() { + for element in storage { + print(element) + } + } +} + +struct StringStack { + // create a stack which contains strings + private var stringStack = Stack() + + init() { + stringStack.push(element: "first") + stringStack.push(element: "second") + stringStack.push(element: "third") + + //check the top element + if let topElement = stringStack.peek() { + print("the top element is \(topElement)") + } else { + print("The stack is empty") + } + + let poppedItem = stringStack.pop() + print("popped item is \(poppedItem ?? "NA")") + + print("is stack empty? \(stringStack.isEmpty)") + print("stack size \(stringStack.count) *** stack is \(stringStack.printDescription())") + + print("string stack \(stringStack)") + //Example with integers + var intStack = Stack() + intStack.push(element: 1) + intStack.push(element: 2) + print("stack count \(intStack.count)") + } + + +}