diff --git a/ImplementHashMapUsingLinearChaining.swift b/ImplementHashMapUsingLinearChaining.swift new file mode 100644 index 00000000..22bdd6f2 --- /dev/null +++ b/ImplementHashMapUsingLinearChaining.swift @@ -0,0 +1,100 @@ +// +// ImplementHashMapUsingLinearChaining.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 12/29/25. +// + +class MyHashMap { + class LCNode { + var key: Int + var value: Int + var next: LCNode? + + init(key: Int, value: Int, next: LCNode? = nil) { + self.key = key + self.value = value + self.next = next + } + } + + var storage: [LCNode?] + + private var buckets: Int + private func hash(key: Int) -> Int { + return key % buckets + } + + //storage will be an arry of linked lists. + init() { + //an array of 10000 elements while having range from 0 to 1 million (for input) + self.storage = Array(repeating: nil, count: 10000) + buckets = 10000 + } + + //for below three functions, this function will be used + private func find(head: LCNode, key: Int) -> LCNode { + //set previous pointer to head of the linked list + var prev = head //at head we will be having a dummy node. + var current = head.next + //Stop when the current reaches the length or we find the value + while (current != nil && current?.key != key) { + prev = current! + current = current?.next + } + return prev + } + + func put(key: Int, value: Int) { + let index = hash(key: key) + if (storage[index] != nil) { + //traverse through this linked list + //thers is no linked list, so initiate the linked list + storage[index] = LCNode(key: -1, value: -1) + } + //when linked list is already there + let prev = find(head: storage[index]!, key: key) + //if key is in the current linked list. + + //if current key is not there in the list + //it will tell us that the current node is not present in the node. + if (prev.next == nil) { + let newNode = LCNode(key: key, value: value) + prev.next = newNode + } else { + //current key is there. + prev.next?.value = value + } + } + + func get(key: Int) -> Int { + let index = hash(key: key) + if (storage[index] == nil) { + return -1 + } + let prev = find(head: storage[index]!, key: key) + if (prev.next == nil) { + return -1 + } + + return prev.next!.value + } + + //key is equal to the index of the array we took + func remove(key: Int) { + let index = hash(key: key) + //If linked list is not present then return + if (storage[index] == nil) { + return + } + + //otherwise traverse through the linked list + let prev: LCNode = find(head: storage[index]!, key: key) + if (prev.next == nil) { + return + } + let temp: LCNode = prev.next! + prev.next = prev.next?.next + temp.next = nil + } +} diff --git a/Implment queue using stacks/ImplementQueueUsingTwoStacks.swift b/Implment queue using stacks/ImplementQueueUsingTwoStacks.swift new file mode 100644 index 00000000..bfbaae20 --- /dev/null +++ b/Implment queue using stacks/ImplementQueueUsingTwoStacks.swift @@ -0,0 +1,53 @@ +// +// ImplementQueueUsingTwoStacks.swift +// DSA-Practice +// +// Created by Paridhi Malviya on 12/30/25. +// + +//Implment queue using 2 stacks. + +class QueueImpl { + var inStack = StackUsingLL(llList: LLLinkedList()) + var outStack = StackUsingLL(llList: LLLinkedList()) + + func push(element: Int) { + //push element in stack1 + inStack.push(value: element) + } + + func pop() -> Int? { + if (outStack.isEmpty()) { + while (!inStack.isEmpty()) { + //push all elements from stack1 to stack2 and then pop + outStack.push(value: inStack.pop()!) + } + } + return outStack.pop() + } + + func peek() -> Int? { + while (!inStack.isEmpty()) { + outStack.push(value: inStack.pop()!) + } + return outStack.peek() + } + + func isEmpty() -> Bool { + return (inStack.isEmpty() && outStack.isEmpty()) + } + + init() { + let inputArray: [Any] = [4, 2, 1, 3, 5, "P", 6, 7, "P", "P"] + for element in inputArray { + if (element as? String != "P") { + push(element: element as! Int) + } else { + let poppedElement = pop() + print("poppedElement \(poppedElement, default: "NA")") + } + } + print("stack1 \(inStack.description)") + print("stack2 \(outStack.description)") + } +} diff --git a/Implment queue using stacks/LinkedListToStackAdapter.swift b/Implment queue using stacks/LinkedListToStackAdapter.swift new file mode 100644 index 00000000..ce4cfb25 --- /dev/null +++ b/Implment queue using stacks/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)") + } +}