### ASCII Character Encoding Example Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/string/README.md This snippet illustrates how characters are represented in the ASCII encoding standard. Each character is mapped to a unique integer code point, which is then converted into its binary bit representation for computer processing. This example shows the mapping for the word 'Jireh'. ```text // character = code point (int) = bit representation J = 74 = 1001010 i = 105 = 1101001 r = 114 = 1110010 e = 101 = 1100101 h = 104 = 1101000 ``` -------------------------------- ### Map Get Operation Pseudocode and Time Complexity Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/map/README.md This snippet explains the `get` operation for a Map, outlining the process to retrieve a value associated with a key. It involves generating a hash, handling collisions by traversing buckets, and retrieving the value. The time complexity is O(1) for finding the address, but can be O(N) or O(LogN) in the worst case for traversing buckets (List/LinkedList vs. Binary Search Tree), with an amortized time of O(1). ```Pseudocode Pseudocode: * Generate hash (a.k.a memory address) for **key**, using a hash function * If there's a collision, traverse bucket to find the correct object and get it * If there's no collision, get **value** at hash ``` -------------------------------- ### Slice Dynamic Array by Range Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md This operation creates a new list containing a sub-section of the original array, from a 'start' index to an 'end' index. It traverses the specified range of the original list and inserts those elements into the newly created list. The worst-case time complexity is O(N), where N is the size of the original list, as the slice can be as large as the entire list. ```Pseudocode * Create a new list that is the size of the slice being requested * Insert all elements from start to end in existing list to new list ``` -------------------------------- ### API Documentation for firstOperation Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/TEMPLATE-ONE.md Documents the `firstOperation()` of the data structure, including its pseudocode steps and detailed analysis of its time and space complexities. ```APIDOC firstOperation(): Pseudocode: Step 1 Step 2 Step 3 Time Complexity: Description: Small description of what is involved Sample operation: Constant Time/O(1) Worst Case: Constant Time/O(1) Space Complexity: Description: Small description of what is involved Sample operation: Constant Space/O(1) Worst Case: Constant Space/O(1) ``` -------------------------------- ### API Documentation for secondOperation Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/TEMPLATE-ONE.md Documents the `secondOperation()` of the data structure, including its pseudocode steps and detailed analysis of its time and space complexities. ```APIDOC secondOperation(): Pseudocode: Step 1 Step 2 Step 3 Time Complexity: Description: Small description of what is involved Sample operation: Constant Time/O(1) Worst Case: Constant Time/O(1) Space Complexity: Description: Small description of what is involved Sample operation: Constant Space/O(1) Worst Case: Constant Space/O(1) ``` -------------------------------- ### Doubly Linked List Core Operations Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/doubly/README.md Common operations supported by a Doubly Linked List (DLL), including adding and removing elements at various positions within the list. ```APIDOC addFirst(e): Add item to the front of the list addLast(e): Add item to the back of the list addAtPosition(n, e): Add item at specific position n in the list removeFirst(): Remove item from front of the list removeLast(): Remove item at the end of the list removeAtPosition(n): Remove item at specific position n in the list ``` -------------------------------- ### Push Operation for Array-based Stack Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/stack/README.md Describes the `push(e)` operation for a Stack implemented using an array. It includes checking for size limits, resizing the array if necessary, and inserting the item at the next available index. Time complexity analysis is also provided, highlighting both worst-case and amortized time. ```Pseudocode Pseudocode: * Check if size limit of underlying array has been reached * If it has, copy all elements in the current underlying array to a bigger array * Insert item in next available index in underlying array ``` -------------------------------- ### Implement firstOperation with Structure 2 Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/TEMPLATE-TWO.md Details the pseudocode steps for `firstOperation` when using Structure 2 as the underlying data structure. This operation has a worst-case time complexity of O(1) and a worst-case space complexity of O(1). ```Pseudocode Step 1 Step 2 Step 3 ``` -------------------------------- ### Implement firstOperation with Structure 1 Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/TEMPLATE-TWO.md Details the pseudocode steps for `firstOperation` when using Structure 1 as the underlying data structure. This operation has a worst-case time complexity of O(1) and a worst-case space complexity of O(1). ```Pseudocode Step 1 Step 2 Step 3 ``` -------------------------------- ### findNeighbours(vertex) Complexity Analysis Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Performance characteristics for the `findNeighbours` operation. ```APIDOC findNeighbours(vertex): Time Complexity: Worst Case: O(|E|) (Linear Time) Space Complexity: Worst Case: O(|E|) (Linear Space) ``` -------------------------------- ### addEdge(vertex1, vertex2) Complexity Analysis Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Performance characteristics for the `addEdge` operation. ```APIDOC addEdge(vertex1, vertex2): Time Complexity: Worst Case: O(|E|) (Linear Time) Amortized Time: O(1) (Constant Time) Space Complexity: Worst Case: O(|E|) (Linear Space) Amortized Space: O(1) (Constant Space) ``` -------------------------------- ### Peek Operation Pseudocode for Doubly Linked List-based Queue Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/queue/README.md Pseudocode for retrieving the item at the front of a queue implemented using a doubly linked list without removing it. This is a constant time operation. ```Pseudocode * Return the element at the front of the doubly linkedlist ``` -------------------------------- ### Implement secondOperation with Structure 1 Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/TEMPLATE-TWO.md Details the pseudocode steps for `secondOperation` when using Structure 1 as the underlying data structure. This operation has a worst-case time complexity of O(1) and a worst-case space complexity of O(1). ```Pseudocode Step 1 Step 2 Step 3 ``` -------------------------------- ### hasVertex(vertex) Complexity Analysis Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Performance characteristics for the `hasVertex` operation. ```APIDOC hasVertex(vertex): Time Complexity: Worst Case: O(|E|) (Linear Time) Space Complexity: Worst Case: O(1) (Constant Space) ``` -------------------------------- ### Implement secondOperation with Structure 2 Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/TEMPLATE-TWO.md Details the pseudocode steps for `secondOperation` when using Structure 2 as the underlying data structure. This operation has a worst-case time complexity of O(1) and a worst-case space complexity of O(1). ```Pseudocode Step 1 Step 2 Step 3 ``` -------------------------------- ### Add Element to the Beginning of a Doubly Linked List Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/doubly/README.md This operation inserts a new element 'e' at the beginning of the doubly linked list. It involves creating a new node, linking it to the current head, and updating the head pointer. This operation has a constant time complexity of O(1). ```Pseudocode * Create new node to wrap element **e** * Set the new node's **next** pointer to the current head, if current head exists * Set the current head's **previous** pointer to new node, if current head exists * Set new node as head ``` -------------------------------- ### hasEdge(vertex1, vertex2) Complexity Analysis Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Performance characteristics for the `hasEdge` operation. ```APIDOC hasEdge(vertex1, vertex2): Time Complexity: Worst Case: O(|E|) (Linear Time) Space Complexity: Worst Case: O(1) (Constant Space) ``` -------------------------------- ### Optimized Graph Operations with Sorted Edge List Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Notes on improving the efficiency of `findEdge` and `findNeighbours` operations by sorting the edge list. ```APIDOC To find edge and all the neighbours for an edge in a more efficient manner, we can sort the edge list. The time complexity for findEdge(vertex1, vertex2) and findNeighbours(vertex) will reduce to O(log|E|), where |E| = set of edges ``` -------------------------------- ### Enqueue Operation Pseudocode for Doubly Linked List-based Queue Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/queue/README.md Pseudocode for adding an item to the back of a queue implemented using a doubly linked list. This operation offers constant time complexity due to the efficient insertion capabilities of DLLs. ```Pseudocode * Add item to back of doubly linkedlist ``` -------------------------------- ### Peek Operation for Array-based Stack Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/stack/README.md Describes the `peek()` operation for a Stack implemented using an array. It involves retrieving the item from the last filled index without removing it. Time complexity analysis is also provided, indicating constant time performance. ```Pseudocode Pseudocode: * Retrieve item from the last filled index in the underlying array ``` -------------------------------- ### Map Put Operation Pseudocode and Time Complexity Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/map/README.md This snippet details the `put` operation for a Map, outlining the steps to add a key-value mapping. It includes generating a hash, handling collisions, and storing the value. The time complexity is O(1) for finding the address, but can be O(N) or O(LogN) in the worst case for traversing buckets (List/LinkedList vs. Binary Search Tree), with an amortized time of O(1). ```Pseudocode Pseudocode: * Generate a hash (a.k.a memory address) for **key**, using a hash function * Handle collision, if necessary * Store **value** at the hash (a.k.a memory address) ``` -------------------------------- ### List All Elements from Hash-based Data Structure Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/set/README.md This operation retrieves all elements stored in the data structure by traversing each index of the underlying array and collecting elements from their respective buckets into a list. It's important to note that the elements are listed according to their storage location based on their hash, not their insertion order, reinforcing the unordered nature of sets. Time complexity is linear, as it involves traversing the entire array and all buckets. ```Pseudocode * Traverse each index in the underlying array * At each index's bucket and add each element found to a list * Return list ``` -------------------------------- ### Peek Operation Pseudocode for Array-based Queue Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/queue/README.md Pseudocode for retrieving the item at the front of a queue implemented using an array without removing it. This is a constant time operation as it only requires accessing the element at index 0. ```Pseudocode * Retrieve item at index 0 in the underlying array ``` -------------------------------- ### Peek Operation for Doubly Linked List-based Stack Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/stack/README.md Describes the `peek()` operation for a Stack implemented using a doubly linked list. It involves returning the element at the head of the linked list without removing it. Time complexity analysis is also provided, indicating constant time performance. ```Pseudocode Pseudocode: * Return element at the head of the linkedlist ``` -------------------------------- ### Push Operation for Doubly Linked List-based Stack Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/stack/README.md Describes the `push(e)` operation for a Stack implemented using a doubly linked list. It involves adding the element to the head of the linked list. Time complexity analysis is also provided, indicating constant time performance. ```Pseudocode Pseudocode: * Add element to head of the linkedlist ``` -------------------------------- ### Calculating Node Relationships in Array-Based Heaps Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/tree/heap/README.md These formulas provide a way to navigate an array-based heap, which is a common and efficient implementation for complete binary trees. They allow for direct calculation of parent, child, and sibling indices given a node's index, for both 0-indexed and 1-indexed array representations. These relationships are crucial for heap operations like insertion and removal, which involve 'heapifying' or re-balancing the tree. ```Pseudocode * parent(z) = `(z - 1)/2`, if z > 0 * leftChild(z) = `2z + 1`, if 2z + 1 < n * rightChild(z) = `2z + 2`, if 2z + 2 < n * leftSibling(z) = `z - 1`, if z is even and z > 0 * rightSibling(z) = `z + 1`, if z is odd and z + 1 < n ``` ```Pseudocode * parent(z) = `z/2`, if z > 0 * leftChild(z) = `2z`, if 2z < n * rightChild(z) = `2z + 1`, if 2z + 1 < n * leftSibling(z) = `z - 1`, if z is even and z > 0 * rightSibling(z) = `z + 1`, if z is odd and z + 1 < n ``` -------------------------------- ### Conceptual: Hash Function Principles in Map Implementations Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/map/README.md This section provides a conceptual explanation of hash functions, their role in generating unique memory addresses for map values, and the significance of prime numbers in their algorithms and initial array sizing for optimal distribution and collision avoidance. ```APIDOC Hash Function: Description: A function that generates a smaller code (hash) for a given value using a known algorithm. This hash doubles as the memory location for the value in the map. Properties: - Uniqueness: Aims to generate unique hashes for different keys. - Deterministic: Always produces the same hash for the same input key. Usage of Prime Numbers: - In Algorithms: Many language implementations (e.g., Java, C#) use prime numbers in their hash algorithms to increase the chance of generating unique hashes. - For Array Sizes: Prime numbers are often used as initial sizes for internal arrays to ensure better distribution of remainder values for each key, leading to fewer collisions. ``` -------------------------------- ### Dequeue Operation Pseudocode for Doubly Linked List-based Queue Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/queue/README.md Pseudocode for removing the item from the front of a queue implemented using a doubly linked list. This operation also provides constant time complexity due to the efficient removal capabilities of DLLs. ```Pseudocode * Remove item from front of doubly linkedlist ``` -------------------------------- ### Add First Element to Linked List (addFirst) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/singly/README.md Inserts a new element 'e' at the beginning of the linked list. This operation involves creating a new node, setting its pointer to the current head, and then updating the head to the new node. It has a constant time complexity, O(1). ```Pseudocode * Create new node to wrap element **e** * Set the new node's pointer to the current head * Set new node as head ``` -------------------------------- ### Enqueue Operation Pseudocode for Array-based Queue Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/queue/README.md Pseudocode for adding an item to the back of a queue implemented using an array. This operation checks for size limits and may involve copying elements to a larger array, impacting its worst-case time complexity. ```Pseudocode * Check if size limit of underlying array has been reached * If it has, copy all elements in the current underlying array to a bigger array * Insert item in next available index in underlying array ``` -------------------------------- ### Defining Strings in C Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/string/README.md This snippet demonstrates two common ways to define strings in C: as a mutable character array and as an immutable pointer to a character array. Both methods are used to store sequences of characters, but they differ in their mutability and memory handling. ```c char name[] = "Ogbeni Owolabi"; char *name = "Ogbeni Owolabi"; ``` -------------------------------- ### Add Element to the End of a Doubly Linked List Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/doubly/README.md This operation appends a new element 'e' to the end of the doubly linked list. If the list is empty, it delegates to `addFirst(e)`. Otherwise, it creates a new node, links it to the current tail, and updates the tail pointer. This operation has a constant time complexity of O(1). ```Pseudocode * If there is no tail node (i.e. the DLL is empty), call `addFirst(e)` * Else, - Get stored tail node reference - Create a new node to wrap element **e** - Set the current tail node's **next** pointer to the new node - Set the new node's **previous** pointer to current tail node - Set new node as tail ``` -------------------------------- ### Pop Operation for Array-based Stack Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/stack/README.md Describes the `pop()` operation for a Stack implemented using an array. It involves retrieving and removing the item from the last filled index. Time complexity analysis is also provided, indicating constant time performance. ```Pseudocode Pseudocode: * Retrieve item from the last filled index in the underlying array and remove the reference to it ``` -------------------------------- ### Add Element at a Specific Position in a Doubly Linked List Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/doubly/README.md This operation inserts a new element 'e' at a specified position 'n' within the doubly linked list. It requires traversing the list to find the insertion point. Special handling is applied if the new node becomes the head. The time complexity is linear, O(N), due to traversal. ```Pseudocode * Starting at head node, traverse the linkedlist until position **n** is reached. * Create a new node to wrap element **e** * Follow the insertion step for the condition that applies: - If there will be no node preceding the new node at position **n**, it means new node is the new head. Therefore, follow steps to `addFirst(e)` above - If there will be a preceding node and a following node for the new node at position **n**, then: * Set the preceding node's **next** pointer to the new node * Set new node's **previous** pointer to the preceding node * Set the following node's **previous** pointer to the new node * Set the new node's **next** pointer to the following node ``` -------------------------------- ### Generic Set Operations API Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/set/README.md Common operations available for a Set data structure, applicable across various programming languages, ensuring uniqueness and managing elements. These operations define the core interface of a Set. ```APIDOC Set Interface: add(e): description: Add an item to the set or produce an error if the item is already in the set. parameters: e: The item to add. returns: void (or error if item exists) contains(e): description: Checks if an item exists in a set. parameters: e: The item to check. returns: boolean list(): description: List the items in the set. returns: array of items remove(e): description: Remove an item from the set. parameters: e: The item to remove. returns: void ``` -------------------------------- ### Dequeue Operation Pseudocode for Array-based Queue Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/queue/README.md Pseudocode for removing the item from the front of a queue implemented using an array. This operation requires shifting all remaining elements to the left, resulting in linear time complexity. ```Pseudocode * Remove item at index 0 in the underlying array * Shift all the elements left by one index * Return removed item ``` -------------------------------- ### Remove the First Element from a Doubly Linked List Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/doubly/README.md This operation removes the element at the beginning of the doubly linked list. It updates the head pointer and nullifies the previous head's links. If the head is the only node, the list becomes empty. This operation has a constant time complexity of O(1). ```Pseudocode * If current head is the only node in the DLL, then set head to null * Else, - Let's call current head's next node newHead (because it will be the new head node) - Set current head's **next** pointer to null - Set newHead's **previous** pointer to null - Set newHead as head ``` -------------------------------- ### Singly Linked List Core Operations Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/singly/README.md This section outlines the fundamental operations available for managing elements within a Singly Linked List, including adding and removing items at the beginning, end, or a specific position. ```APIDOC SinglyLinkedList: addFirst(e): description: Add item to the front of the list parameters: e: The element to add addLast(e): description: Add item to the back of the list parameters: e: The element to add addAtPosition(n, e): description: Add item at specific position n in the list parameters: n: The position (integer) e: The element to add removeFirst(): description: Remove item from front of the list removeLast(): description: Remove item at the end of the list removeAtPosition(n): description: Remove item at specific position n in the list parameters: n: The position (integer) ``` -------------------------------- ### Graph Common Operations API Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Defines common operations that can be performed on a graph data structure, including adding/checking vertices and edges, and finding neighbors. ```APIDOC addVertex(vertex) hasVertex(vertex) addEdge(vertex1, vertex2) hasEdge(vertex1, vertex2) findNeighbours(vertex) ``` -------------------------------- ### Add Element to Hash-based Data Structure Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/set/README.md This operation adds an element `e` to the data structure. It involves generating a hash for `e` to determine its index, checking for existing elements at that index (to ensure uniqueness in a set), storing the element, and handling collisions if necessary. The time complexity varies based on the bucket's data structure, with amortized constant time for typical hash table implementations. ```Pseudocode * Generate a hash (a.k.a index for the underlying array) for the object (or element) **e**, using a hash function * Check if object (or element) **e** exists at index. See `contains(e)`'s description for more info * Store object (or element) **e** at the index generated * Handle collision, if necessary ``` -------------------------------- ### Retrieve Element from Specific Index in Dynamic Array Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md This operation retrieves the element located at a specified index 'n'. It first checks if the index is valid; if not, it throws an exception. This is a direct access operation, resulting in a constant time complexity of O(1). ```Pseudocode * Check if index exists, if it doesn't, throws an Exception * Return element at index **n** ``` -------------------------------- ### Java: Memory Allocation for Integer Arrays Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/array/README.md This Java code demonstrates how memory is allocated for a fixed-size integer array. The compiler calculates the total memory by multiplying the number of elements by the size of each integer (e.g., 4 bytes), ensuring contiguous storage for primitive types. ```Java // The below will require 4 * 10 == 40 bytes of memory int[] intArr = new int[10]; ``` -------------------------------- ### Heap Peek Operation Pseudocode and Complexity Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/tree/heap/README.md The `peek()` operation allows inspection of the heap's root element without removing it. This element represents either the minimum or maximum value in the heap, depending on its type (min-heap or max-heap). This operation directly accesses the element at index 0 of the underlying array. It has a constant time complexity of O(1) and a constant space complexity of O(1) as no extra space is used. ```Pseudocode * return the node at index 0 (this will be the min or max value depending on the type of heap it is) ``` -------------------------------- ### Map Delete Operation Pseudocode and Time Complexity Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/map/README.md This snippet describes the `delete` operation for a Map, detailing how to remove a key and its associated value. It involves generating a hash, traversing buckets to handle collisions, and deleting the object. The time complexity is O(1) for finding the address, but varies for deleting from the bucket (O(N) for List, O(1) for LinkedList, O(LogN) for Binary Search Tree), with an amortized time of O(1). ```Pseudocode Pseudocode: * Generate hash (a.k.a memory address) for **key**, using a hash function * If there's a collision, traverse bucket to find the correct object and delete it * If there's no collision, delete **value** at hash ``` -------------------------------- ### Find Neighbours of a Vertex (Edge List) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Finds all vertices connected to a given vertex by traversing the array of edges. If an edge contains the specified vertex, its counterpart is added to a list. The method returns this list of neighbours. It operates with O(|E|) time and O(|E|) space complexity. ```Pseudocode Pseudocode: * Traverse array of edges - If an edge contains a the passed-in vertex, add it to a list * Return the list ``` -------------------------------- ### Insert Element at Specific Index in Dynamic Array Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md This operation inserts an element 'e' at a specified index 'n'. It handles array resizing if necessary and shifts all elements from index 'n' onwards by one position to accommodate the new element. The worst-case time complexity is O(N) due to potential array resizing and element shifting. ```Pseudocode * Check if the underlying array is filled * If it is, copy all elements in the current underlying array to a bigger array * Move elements from index **n** forward by one index * Insert element **e** at index **n** ``` -------------------------------- ### Pop Operation for Doubly Linked List-based Stack Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/stack/README.md Describes the `pop()` operation for a Stack implemented using a doubly linked list. It involves removing the element from the head of the linked list. Time complexity analysis is also provided, indicating constant time performance. ```Pseudocode Pseudocode: * Remove element from head of the linkedlist ``` -------------------------------- ### Heap Insert Operation Pseudocode and Complexity Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/tree/heap/README.md The `insert()` operation for a heap involves two main steps: `insertAtNextIndex()` and `heapifyUp()`. `insertAtNextIndex()` adds the new element to the next available position in the underlying array, which is an O(1) operation. `heapifyUp()` (also known as bubble-up or sift-up) then ensures the heap property is maintained by repeatedly swapping the newly inserted node with its parent if the heap property is violated, moving it upwards until its correct position is found or it reaches the root. This process has a worst-case time complexity of O(logN), making the overall insert operation O(logN). Space complexity is O(1) for primary data types or objects storing primary data types, and O(N) for objects storing anything else due to pointer storage. ```Pseudocode 1. add element to next available index in array ``` ```Pseudocode 1. get the parent of the newly insert node 2. if the node > parent, then swap their positions 3. repeat 1 and 2, until we get to the top or the condition fails ``` -------------------------------- ### Check for Element Existence in Hash-based Data Structure Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/set/README.md This operation checks if an element `e` exists within the data structure. It generates a hash for `e` to find its potential index, then traverses the bucket at that index to locate the element. This step is crucial for ensuring uniqueness in set implementations and highlights the importance of immutability for hashable objects. Time complexity depends on the bucket's traversal efficiency. ```Pseudocode * Generate a hash (a.k.a index for the underlying array) for the object (or element) **e**, using a hash function * Check if object (or element) **e** exists at index. It is this step that ensure uniqueness in a set. It is for this step that immutability is important. - To check if an object exists at an element, we traverse the bucket until we find it. ``` -------------------------------- ### Java String Immutability and Internal Structure Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/string/README.md This snippet illustrates how strings are defined in Java and highlights their immutable nature. It also shows a simplified internal structure of the `String` class, revealing that it contains a final character array, which is key to enforcing its immutability. ```java String name = "Ogbeni Owolabi"; public final class String { private final char value[]; } ``` -------------------------------- ### Check for Vertex Existence (Edge List) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Checks if a given vertex exists in the graph by traversing the array of edges. Returns true if the vertex is found on any edge, false otherwise. It operates with O(|E|) time and O(1) space complexity. ```Pseudocode Pseudocode: * Traverse the array of edges - If either vertex on an edge matches the vertex being sought for, return true * Return false if no match is found ``` -------------------------------- ### Find Neighbors of a Vertex (Adjacency Map Pseudocode) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md This operation retrieves all direct neighbors of a specified vertex. Using an adjacency map, this is a constant-time operation that simply returns the list of edges (neighbors) associated with the given vertex's key. It provides immediate access to the vertex's direct connections. ```Pseudocode * Return list return by key vertex key from map ``` -------------------------------- ### Heap Remove Operation Pseudocode and Complexity Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/tree/heap/README.md The `remove()` operation typically removes the root element (min or max value) from the heap. It consists of three steps: `swapRootAndLastIndex()`, `removeLastIndex()`, and `heapifyDown()`. First, the root element is swapped with the last element in the heap (O(1)). Then, the last element (which was the original root) is removed (O(1)). Finally, `heapifyDown()` (also known as sift-down) restores the heap property by repeatedly swapping the new root with its largest (for max heap) or smallest (for min heap) child, moving it downwards until its correct position is found. This process has a worst-case time complexity of O(logN), making the overall remove operation O(logN). Space complexity is O(1) as no new nodes are added. ```Pseudocode 1. Swap element at index 0 with last element ``` ```Pseudocode 1. Remove element at last index ``` ```Pseudocode 1. get the left and right children of the root node using the relevant formulas 2. if left and right children are null, we're done 3. if root node < left && left > right, then swap with left. else swap with right 4. repeat 1 - 3 until we get to the last index or a condition fails ``` -------------------------------- ### Demonstrating Java String Pool Behavior Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/string/README.md This Java snippet demonstrates the string pool mechanism, a memory optimization technique. When identical string literals are declared, Java reuses the existing string object from the pool, causing them to reference the same memory address, as shown by the `==` operator returning true. ```java String name = "Ogbeni Owolabi"; String name1 = "Ogbeni Owolabi"; // This statement is comparing the addesses of both strings // They both have the same address in memory because of the string pool mechanism sout(name == name1); // True ``` -------------------------------- ### Java: Initial Memory Consideration for String Arrays Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/array/README.md This Java snippet declares a String array, highlighting the initial challenge in determining its exact memory footprint. Unlike primitive types, the memory for String objects themselves is not directly part of the array's contiguous block, leading to a question about 'x' bytes. ```Java // 10 * x bytes. What is x? String[] strArr = new String[10]; ``` -------------------------------- ### Add Vertex to Graph (Adjacency Map Pseudocode) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md This operation describes how to add a new vertex to a graph. When using an adjacency map representation, the vertex is simply added as a new key in the map. This ensures the vertex is recognized within the graph structure. ```Pseudocode * Add vertex as a key in the map ``` -------------------------------- ### Check for Edge Existence (Edge List) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Determines if an edge exists between two specified vertices by traversing the array of edges and comparing each until a match is found. Returns true if the edge is found, false otherwise. It operates with O(|E|) time and O(1) space complexity. ```Pseudocode Pseudocode: * Traverese array of edges and compare each one until edge is found - if edge is, return true * Return false if edge is not found ``` -------------------------------- ### Add Element at Specific Position in Linked List (addAtPosition) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/singly/README.md Inserts a new element 'e' at a specified position 'n' within the linked list. The operation involves traversing to the desired position, keeping track of the preceding node, and then adjusting pointers to insert the new node. Special handling is included for insertion at the head (delegating to `addFirst`). The time complexity is linear, O(N), due to traversal. ```Pseudocode * Starting at head node, traverse the linkedlist until position **n** is reached. Keep track of the **preceding node** * Create a new node to wrap element **e** * Follow the insertion step for the condition that applies: - If there will be no node preceding the new node at position **n**, it means new node is the new head. Therefore, follow steps to `addFirst(e)` above - If there will be a preceding node and a following node for the new node at position **n**, then: * Set the preceding node's pointer to the new node * Set the new node's pointer to the following node * The two steps above perform the **insertion** ``` -------------------------------- ### Remove Element at a Specific Position in a Doubly Linked List Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/doubly/README.md This operation removes an element from a specified position 'n' within the doubly linked list. It involves traversing the list to find the node to remove. It delegates to `removeFirst()` or `removeLast()` if the node is at an extremity, otherwise it relinks the preceding and succeeding nodes. The time complexity is linear, O(N), due to traversal. ```Pseudocode * Starting at head node, traverse the DLL until position **n** is reached * Follow the removal step for the condition that applies: - If node to be removed is the head, call `removeFirst()` above - If node to be removed is the tail, call `removeLast()` above - If node is a middle node (i.e. is has both previous and next nodes), then * Set the previous node's **next** pointer to the next node * Set the next node's **previous** pointer to the previous node ``` -------------------------------- ### Definition of Comparator in Programming Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md A comparator is a function or object that compares two entities (e.g., voltages, objects) and outputs a value indicating their relative order or relationship. In programming, it typically returns an integer to signify which of the two compared objects is 'larger' or comes first in a defined order. ```APIDOC Comparator: In programming, a comparator is a function that compares two objects and outputs an integer indicating which is larger. ``` -------------------------------- ### Add Edge Operation (Edge List) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Adds a new edge between two specified vertices to the graph's list of edges. This involves creating a new array for the vertices and inserting it into the 2-D array or list of edges. It has O(|E|) worst-case time and O(1) amortized time, with O(|E|) worst-case space and O(1) amortized space. ```Pseudocode Pseudocode: * Create a new array containing both vertices * Insert new array into 2-D array or list of edges ``` -------------------------------- ### Add Edge Between Vertices (Adjacency Map Pseudocode) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md This operation adds an edge connecting two specified vertices in an undirected graph. It first ensures both vertices exist in the map, adding them if necessary. Then, it establishes the bidirectional connection by adding each vertex as a neighbor to the other's adjacency list. ```Pseudocode * Check if both vertices exist in the map as keyx - If they don't exist, add them * Add vertex1 as a neighbour to vertex2 * Add vertex2 as a neighbour to vertex1 ``` -------------------------------- ### Adjacency Matrix Graph Representation Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Describes the Adjacency Matrix representation for graphs. For a graph with |V| vertices, it's a |V| × |V| matrix where entry (i,j) is 1 if edge (i,j) exists, and 0 otherwise. ```APIDOC For a graph with |V| vertices, an adjacency matrix is a |V| × |V| matrix of 0s and 1s, where the entry in row_i and column_j is 1 if and only if the edge (i,j) is in the graph. The amount of space used for this implementation is O(|V|^2), where |V| = set of vertices. This implementation uses a lot of space that is especially inefficient if the graph has a small number of edges. ``` -------------------------------- ### Remove the Last Element from a Doubly Linked List Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/doubly/README.md This operation removes the element at the end of the doubly linked list. It updates the tail pointer and nullifies the previous tail's links. If the tail is the only node, the list becomes empty. This operation has a constant time complexity of O(1). ```Pseudocode * Get stored tail node reference * If tail node is the only node in the DLL, then set tail to null & head to null (because head == tail here) * Else, - Let's call current tails's previous node newTail (because it will be the new tail node) - Set current tail's **previous** pointer to null - Set newTail's **next** pointer to null - Set newTail as tail ``` -------------------------------- ### Check Vertex Existence in Graph (Adjacency Map Pseudocode) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md This operation verifies if a given vertex exists within the graph. For undirected graphs, it's a constant-time check if the vertex is a map key. For directed graphs, it might require a full graph traversal (BFS or DFS) if the vertex is not guaranteed to be a key, as it could be a destination without being a source. ```Pseudocode Pseudocode (Undirected Graph): * Check if vertex exists as a key in the map Pseudocode (Directed Graph): Breadth-first Search (Iterative) * Define a Queue * Define a Set (to store visited vertices) * Add all the keys from the map into the Queue * For each vertex in the Queue, - Retrieve all its neighbours and add them to the Queue (to be visited too) - If any neighbour has been visited before, don't add it to the Queue again - Add all neighbours that haven't been visited before to the Set * During traversal, check if vertex is seen - If yes, return true * Return false if traversal is complete and vertex was not found Depth-first Search (Iterative) * Define a Stack * Define a Set (to store visited vertices) * Add all the keys from the map into the Stack * For each vertex in the Stack, - Retrieve all its neighbours and add them to the Stack (to be visited too) - If any neighbour has been visited before, don't add it to the Stack again - Add all neighbours that haven't been visited before to the Set * During traversal, check if vertex is seen - If yes, return true * Return false if traversal is complete and vertex was not found ``` -------------------------------- ### Add Vertex to Adjacency Matrix Graph Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Adds a new vertex to the graph represented by an adjacency matrix. This involves expanding the matrix by adding a new row and column, and initializing all new cells with 0, as the new vertex initially has no edges. The worst-case time and space complexity is O(|V|^2) if a new, larger matrix must be created. ```Pseudocode * Add a new row and a new column to the matrix * Fill all new empty cells with 0, because new vertex has no edges yet ``` -------------------------------- ### Add Element to Dynamic Array (End) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md This operation adds an element 'e' to the next available index in the array. If the underlying array is full, it first copies all existing elements to a new, larger array before inserting the new element. The worst-case time complexity is O(N) due to potential array resizing and copying. ```Pseudocode * Check if the underlying array is filled * If it is not, - insert element **e** in the next available index in the array * If it is, - copy all elements in the current underlying array to a bigger array - insert element **e** in the next available index in the new, bigger array ``` -------------------------------- ### Java: Memory Allocation for String Arrays via References Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/array/README.md This Java code illustrates the actual memory allocation for a String array. Instead of storing the String objects directly, the array stores references (pointers) to them. The total memory for the array itself is determined by the number of elements multiplied by the size of a reference (e.g., 4 or 8 bytes). ```Java // 10 * 4 bytes = 40 bytes (32-bit) // 10 * 8 bytes = 80 bytes (64-bit) String[] strArr = new String[10]; ``` -------------------------------- ### Check for Vertex Existence in Adjacency Matrix Graph Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Checks if a given vertex exists within the graph's current size. This operation has a constant time complexity of O(1) as it primarily involves a simple comparison against the matrix's dimensions. ```Pseudocode * Check if vertex < matrix's size - If true, then vertex exists - If false, then vertex does not exist ``` -------------------------------- ### Add Last Element to Linked List (addLast) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/singly/README.md Appends a new element 'e' to the end of the linked list. This requires traversing the list from the head to find the current tail, creating a new node, and then updating the tail's pointer to the new node. The time complexity is linear, O(N), due to the traversal. ```Pseudocode * Starting at head node, traverse the linkedlist until tail node is reached * Create a new node to wrap element **e** * Set the current tail node's pointer to the new node * Set new node as tail ``` -------------------------------- ### Remove Element from Specific Index in Dynamic Array Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md This operation removes an element at a specified index 'n'. It sets the reference at index 'n' to null and then shifts all subsequent elements (from index 'n+1' to the end) backward by one position to fill the gap. The worst-case time complexity is O(N) due to the element shifting. ```Pseudocode * Remove reference to item by setting index **n** to null * Move elements from index **n+1** to the end backward by one index ``` -------------------------------- ### Find Neighbors of a Vertex in Adjacency Matrix Graph Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Retrieves all direct neighbors of a given vertex by accessing and traversing its corresponding row in the adjacency matrix. If a cell's value is 1, its index represents a valid neighbor, which is then added to a list. The operation has a linear time complexity of O(|E|) and requires linear space O(|E|) to store the list of neighbors. ```Pseudocode * Assume the 2-D array shown in the image above is called `graph` * Access row associated with vertex by calling graph[vertex] * Traverse this row - If the value at index is 1, then the index is a valid neighbour. Add to a list - If the value at index is 0, ignore it * Return list ``` -------------------------------- ### Check Edge Existence Between Vertices (Adjacency Map Pseudocode) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md This operation determines if an edge exists between two given vertices. It involves accessing the adjacency list associated with the first vertex and then traversing that list to ascertain if the second vertex is present as a neighbor. This check is typically linear in the number of edges connected to the first vertex. ```Pseudocode * Access list of edges associated with vertex1 key * Traverse list of edges to look for vertex2 ``` -------------------------------- ### Remove Element from Hash-based Data Structure Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/set/README.md This operation removes a specified element `e` from the data structure. It begins by generating a hash for `e` to locate its index. If there's no collision, the element is directly deleted. In case of collisions, the bucket at the index is traversed to find and delete the correct object. The time complexity for deletion depends on the efficiency of removal from the bucket's underlying data structure. ```Pseudocode * Generate a hash (a.k.a index for the underlying array) for the object (or element) **e**, using a hash function * Delete object (or element) **e** at the index, if there's no collision * If there's a collision, traverse bucket at index to find the correct object and delete it ``` -------------------------------- ### Check for Edge Existence in Adjacency Matrix Graph Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Determines if an edge exists between two specified vertices by checking the value in the corresponding cell of the adjacency matrix. If `graph[vertex1][vertex2]` is 1, an edge exists; otherwise, it does not. This is a constant time operation, O(1). ```Pseudocode * Assume the 2-D array shown in the image above is called `graph` * Get graph[vertex1][vertex2] - Return true if it equals 1 - Return false otherwise ``` -------------------------------- ### Add Edge to Undirected Adjacency Matrix Graph Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/graph/README.md Adds an undirected edge between two specified vertices. If either vertex does not already exist, the `addVertex` method is called to create it. For an undirected graph, the corresponding cells `graph[vertex1][vertex2]` and `graph[vertex2][vertex1]` are both set to 1. The time complexity is O(1) if both vertices exist, or O(|V|^2) if `addVertex` is invoked. ```Pseudocode * Check vertex1 exists - If it doesn't, call addVertex(vertex1) * Check vertex2 exists - If it doesn't, call addVertex(vertex2) * graph[vertex1][vertex2] = 1 * graph[vertex2][vertex1] = 1 (This is necessay because the graph is undirected) ``` -------------------------------- ### Remove First Element from Linked List (removeFirst) Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/linkedlist/singly/README.md Removes the first element from the linked list. This is achieved by simply updating the head to point to the next node in the list. The previous head node will then be eligible for garbage collection. This operation has a constant time complexity, O(1). ```Pseudocode * Set head as the node the current head node points to ``` -------------------------------- ### Reverse Elements in Dynamic Array Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md This operation reverses the order of all elements within the underlying array. It iterates through the array to swap elements from opposite ends until the entire array is reversed. The time complexity for this operation is linear, O(N). ```Pseudocode * Reverse elements in the underlying array ``` -------------------------------- ### Sort Elements in Dynamic Array Source: https://github.com/oyekanmiayo/dsa-all-langs/blob/main/data-structures/list/README.md This operation sorts the elements within the underlying array in either ascending or descending order. For complex objects, custom comparators are used to define the sorting logic. Utilizing efficient sorting algorithms, the worst-case time complexity is O(NlogN). ```Pseudocode * Sort elements in ascending or descending order ```