### Learning journey ->

Let’s begin with the basics.

**What are Data Structures?**

Data structures are a way to organize and store data efficiently in a computer’s memory. They are fundamental building blocks in programming and are essential for tasks like searching, sorting, and managing data in various applications, including game development and website management.

Here are some common data structures you should start with:

- An array is a collection of elements of the same data type, stored in contiguous memory locations. It’s indexed by integers, making it easy to access elements by their position.

Example (in Python):

my_array = [1, 2, 3, 4, 5]

- A linked list is a linear data structure where elements (nodes) are connected through pointers. There are singly linked lists (each node points to the next) and doubly linked lists (each node points to both the next and the previous).

Example (in Python):

class Node: def __init__(self, data): self.data = data self.next = None # Create nodes and establish links node1 = Node(10) node2 = Node(20) node3 = Node(30) node1.next = node2 node2.next = node3 # Display the original linked list def display_linked_list(head): current = head while current is not None: print(current.data, end=" -> ") current = current.next print("None") print("Original Linked List:") display_linked_list(node1) # Remove the element with value 20 current = node1 while current is not None: if current.next and current.next.data == 20: current.next = current.next.next break current = current.next # Display the updated linked list print("\nLinked List after Removing 20:") display_linked_list(node1)

There’s a more efficient and generalized way to remove nodes from a linked list while preserving the integrity of the list.

To handle the case where the first, specific value and last node (tail) needs to be removed from a singly linked list, you can modify the `remove_node`

function to account for this situation.

In this function:

- We introduce a
`prev`

variable to keep track of the previous node while traversing the list. - When we find the node with the value to remove, we update the
`next`

pointer of the previous node (`prev.next`

) to skip the node to be removed. This covers the case where the last node is the one to be removed.

Please see below:-

class Node:

def __init__(self, data):

self.data = data

self.next = None

# Creating nodes

node1 = Node(10)

node2 = Node(20)

node3 = Node(30)

node4 = Node(40)

# Connecting nodes

node1.next = node2

node2.next = node3

node3.next = node4

# Display

def display_linked_list(head):

current = head

while current is not None:

print(current.data, end=" | ")

current = current.next

print("None")

print("Original List")

display_linked_list(node1)

def remove_node(head, value_to_remove):

if head is None:

return None

# Handle the case where the first node needs to be removed

if head.data == value_to_remove:

return head.next

current = head

while current.next is not None:

if current.next.data == value_to_remove:

current.next = current.next.next

return head

prev = current # Keep track of the previous node

current = current.next

# Handle the case where the last node needs to be removed

if current.data == value_to_remove:

prev.next = None

return head

# Remove node with value 10

node1 = remove_node(node1, 10)

# Remove node with value 20

node1 = remove_node(node1, 20)

# Remove node with value 40

node1 = remove_node(node1, 40)

print("\nRemove List")

display_linked_list(node1)

# Append nodes

new_node = Node(55)

current = node1

while current.next is not None:

current = current.next

current.next = new_node

new_node = Node(88)

current = node1

while current.next is not None:

current = current.next

current.next = new_node

print("\nAppend List")

display_linked_list(node1)

- A stack is a linear data structure with a last-in, first-out (LIFO) order. It’s used for tasks like tracking function calls, parsing expressions, and undo operations.

Example (in Python):

my_stack = []

my_stack.append(1)

my_stack.append(2)

my_stack.append(3)

# Now the stack is [1, 2, 3]

===> Another example <===

class Stack:

def __init__(self):

self.items = []

def is_empty(self):

return len(self.items) == 0

def push(self, item):

self.items.append(item)

def pop(self):

if not self.is_empty():

return self.items.pop()

else:

return "Stack is empty"

def peek(self):

if not self.is_empty():

return self.items[-1]

else:

return "Stack is empty"

def size(self):

return len(self.items)

# Create a stack

stack = Stack()

# Push elements onto the stack

stack.push(10)

stack.push(20)

stack.push(30)

# Peek at the top element

top_element = stack.peek()

print(f"Top element: {top_element}")

# Pop elements from the stack

popped_element = stack.pop()

print(f"Popped element: {popped_element}")

# Check if the stack is empty

print(f"Is the stack empty? {stack.is_empty()}")

# Get the size of the stack

stack_size = stack.size()

print(f"Stack size: {stack_size}")

Output ===>>>

Top element: 30

Popped element: 30

Is the stack empty? False

Stack size: 2

———->

In this example:

We define a Stack class with push, pop, peek, size, and is_empty methods.

We create a stack, push elements onto it, peek at the top element, pop elements off it, check if it’s empty, and get its size.

The output will demonstrate the basic functionality of a stack. You’ll notice that the last element pushed (30) is the first one popped, confirming the Last-In, First-Out (LIFO) behavior of a stack.

- A queue is a linear data structure with a first-in, first-out (FIFO) order. It’s used for tasks like managing tasks in a printer queue or handling requests in a web server.

Example (in Python):

from collections import deque

my_queue = deque()

my_queue.append(1)

my_queue.append(2)

my_queue.append(3)

# Now the queue is [1, 2, 3]

- Trees are hierarchical data structures with a root node and child nodes. They are used in many algorithms and are the basis for more complex data structures like binary trees and heaps.

Example (a simple binary tree in Python):

class TreeNode:

def __init__(self, data):

self.data = data

self.left = None

self.right = None

root = TreeNode(1)

root.left = TreeNode(2)

root.right = TreeNode(3)

These are some of the foundational data structures. Start by understanding how each works, how to perform basic operations on them (insertion, deletion, traversal), and when to use them in different scenarios.