Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions Precourse1-Swift/LinkedList.swift
Original file line number Diff line number Diff line change
@@ -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<T> {
var value: T
var next: Node<T>? //refrence to the next node in the linkedlist.

init(value: T, next: Node<T>? = nil) {
self.value = value
self.next = next
}
}

//the linkedlist class
class LinkedList<T> {
private var head: Node<T>?
private var tail: Node<T>?

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<String>()
linkedList.append(value: "a")
linkedList.append(value: "b")
linkedList.append(value: "c")
print(linkedList)
}
}
159 changes: 159 additions & 0 deletions Precourse1-Swift/LinkedListToStackAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
//
// LinkedListToStackAdapter.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 12/16/25.
//

//Implement stack using linked list

class LLNode<T> {
var value: T
var next: LLNode<T>?

init(value: T, next: LLNode<T>?) {
self.value = value
self.next = next
}
}

class LLLinkedList<T> {
private var head: LLNode<T>?
private var tail: LLNode<T>?

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<T>? {
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<T>? {
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<T>: CustomStringConvertible {
private var llList: LLLinkedList<T>?

init(llList: LLLinkedList<T>) {
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<Int>(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)")
}
}
73 changes: 73 additions & 0 deletions Precourse1-Swift/SinglyLinkedList.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// SinglyLinkedList.swift
// DSA-Practice
//
// Created by Paridhi Malviya on 12/17/25.
//

class SinglyLLNode<T> {
var value: T
var next: SinglyLLNode<T>?

init(value: T, next: SinglyLLNode<T>?) {
self.value = value
self.next = next
}
}

class SinglyLinkedList<T> {

private var head: SinglyLLNode<T>?
private var tail: SinglyLLNode<T>?

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<T>? {
return self.head
}
}

class SinglyLinkedListImpl {
init() {
let linkedlist = SinglyLinkedList<Int>()
linkedlist.append(value: 1)
linkedlist.append(value: 2)
linkedlist.push(30)
print("Linked list contents:")
linkedlist.displayList()
}
}
Loading