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
Empty file added Data_Structure/README.md
Empty file.
4 changes: 4 additions & 0 deletions Data_Structure/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

pytest
mypy
flake8
4 changes: 4 additions & 0 deletions Data_Structure/src/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

from .stack_reverse import reverse_string
from .queue_with_stacks import QueueWithStacks
from .linked_list_max import LinkedList
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
86 changes: 86 additions & 0 deletions Data_Structure/src/linked_list_max.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
class Node:
"""Represents a node in the LinkedList."""

def __init__(self, data):
"""
Initialize a node with data and a reference to the next node.

Args:
data (int or float): The data to be stored in the node.
"""
self.data = data
self.next = None

class LinkedList:
"""LinkedList class to manage the linked list operations."""

def __init__(self):
"""Initialize an empty LinkedList."""
self.head = None

def append(self, value):
"""
Append a new node with the given value to the end of the list.

Args:
value (int or float): The value to be added to the list.
"""
new_node = Node(value)
if not self.head:
self.head = new_node
else:
current = self.head
while current.next:
current = current.next
current.next = new_node

def find_max(self):
"""
Find the maximum value in the linked list.

Returns:
int or float: The maximum value in the linked list.

Raises:
ValueError: If the list is empty.
"""
if not self.head:
raise ValueError("The linked list is empty.")

max_value = self.head.data
current = self.head.next

while current:
if current.data > max_value:
max_value = current.data
current = current.next

return max_value

def print_list(self):
"""
Print all the values in the linked list.

Returns:
list: A list of all values in the linked list.
"""
values = []
current = self.head
while current:
values.append(current.data)
current = current.next
return values


if __name__ == "__main__":
ll = LinkedList()
ll.append(5)
ll.append(10)
ll.append(25)
ll.append(65)

# Print all items in the linked list
print("LinkedList items:", ll.print_list()) # Output: LinkedList items: [3, 1, 4, 2]

# Find and print the maximum value
print("Maximum Value in LinkedList:", ll.find_max()) # Output: Maximum Value in LinkedList: 4
71 changes: 71 additions & 0 deletions Data_Structure/src/queue_with_stacks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
class QueueWithStacks:
def __init__(self):
"""
This class implements a queue using two stacks. The enqueue operation is performed on stack1,
and the dequeue operation is performed on stack2. When stack2 is empty, elements are transferred
from stack1 to stack2 to ensure the correct order of elements.
"""
# Initialize two stacks: stack1 for enqueue operations, stack2 for dequeue operations
self.stack1 = []
self.stack2 = []

def enqueue(self, x: int):
"""
Adds an element to the back of the queue.

Parameters:
x (int): The element to be added to the queue.

Returns:
None: This method does not return any value. It modifies the queue by adding the given element.
"""
# Push the element onto stack1
self.stack1.append(x)

def dequeue(self) -> int:
"""
Removes and returns the front element of the queue.

The dequeue operation is performed on stack2. If stack2 is empty, elements are transferred
from stack1 to stack2 to ensure the correct order of elements.

Raises:
IndexError: If both stacks are empty, indicating that the queue is empty.

Returns:
int: The element at the front of the queue.
"""
# If both stacks are empty, raise an IndexError
if not self.stack1 and not self.stack2:
raise IndexError("Dequeue from an empty queue")

# If stack2 is empty, transfer elements from stack1 to stack2
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())

# Pop the element from stack2 (which is the front of the queue)
return self.stack2.pop()

def __str__(self):
"""
Returns a string representation of the queue's current state.

If stack2 is not empty, it represents the front of the queue in reverse order.
Otherwise, stack1 represents the back of the queue.

Returns:
str: A string representation of the queue.
"""
if not self.stack2:
return str(self.stack1)
return str(self.stack2[::-1] + self.stack1)

# Example usage:
if __name__ == "__main__":
q = QueueWithStacks()
q.enqueue("Lesson1")
q.enqueue("Lesson2")
q.enqueue("Lesson3")
print(q.dequeue()) # Output: 1
print(q.dequeue()) # Output: 2
85 changes: 85 additions & 0 deletions Data_Structure/src/stack_reverse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
class Stack:

"""
A class representing a stack data structure.

Attributes:
stack (list): A list to store the elements of the stack.

Methods:
push(item): Adds an item to the top of the stack.
pop(): Removes and returns the top item from the stack.
is_empty(): Checks if the stack is empty.
"""
def __init__(self):
"""
Initializes an empty list to represent the stack.
"""
self.stack = []

def push(self, item):
"""
Adds an item to the top of the stack.

Parameters:
item (any): The item to be added to the stack.
"""
self.stack.append(item)

def pop(self):
"""
Removes and returns the top item from the stack.

Returns:
any: The top item from the stack, or None if the stack is empty.
"""
return self.stack.pop() if not self.is_empty() else None

def is_empty(self):
"""
Checks if the stack is empty.

Returns:
bool: True if the stack is empty, False otherwise.
"""
return len(self.stack) == 0


def reverse_string(s: str) -> str:
"""
Reverses a given string using a stack.

Parameters:
s (str): The input string to be reversed.

Returns:
str: The reversed string.

Raises:
ValueError: If the input is not a string.
"""
# Check if the input is a string, raise an error if not
if not isinstance(s, str):
raise ValueError("Input must be a string")

# Initialize a stack object to store characters
stack = Stack()

# Iterate over each character in the string
for char in s:
# Push each character onto the stack
stack.push(char)

# Initialize an empty string to store the reversed string
reversed_str = ""

# While the stack is not empty
while not stack.is_empty():
# Pop characters from the stack and append to the reversed string
reversed_str += stack.pop()

# Return the reversed string
return reversed_str


print(reverse_string("Wellcome To My Data Structure Class Let's Have Fun Together!"))
Empty file.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
49 changes: 49 additions & 0 deletions Data_Structure/tests/test_linked_list_max.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from src.linked_list_max import LinkedList

def test_linked_list_find_max():
"""
This function tests the find_max method of a LinkedList class.

The LinkedList class is assumed to have the following methods:
- append(value): Adds a new node with the given value to the end of the list.
- find_max(): Returns the maximum value in the list. If the list is empty, raises a ValueError.

Raises:
AssertionError: If the find_max method does not return the expected maximum value
or does not raise a ValueError for an empty list.
"""

# Create and populate a LinkedList
ll = LinkedList()
ll.append(5)
ll.append(10)
ll.append(25)
ll.append(65)

# Print appended items
def print_list(linked_list):
items = []
current_node = linked_list.head
while current_node:
items.append(current_node.data)
current_node = current_node.next
return items

print(f"LinkedList items: {print_list(ll)}")

# Find and print the maximum value
max_value = ll.find_max()
print(f"Maximum Value in LinkedList: {max_value}") # Display maximum value
assert max_value == 65, f"Expected 65 but got {max_value}"

# Test find_max with an empty LinkedList
try:
empty_ll = LinkedList()
empty_ll.find_max()
assert False, "Did not raise ValueError for empty linked list"
except ValueError as e:
print(f"Error for empty LinkedList: {e}") # Display error message

if __name__ == "__main__":
test_linked_list_find_max()
print("All LinkedList find_max tests passed!")
94 changes: 94 additions & 0 deletions Data_Structure/tests/test_queue_with_stacks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from src.queue_with_stacks import QueueWithStacks

class QueueWithStacks:
def __init__(self):
"""
This class implements a queue using two stacks. The enqueue operation is performed on stack1,
and the dequeue operation is performed on stack2. When stack2 is empty, elements are transferred
from stack1 to stack2 to ensure the correct order of elements.
"""
self.stack1 = [] # enqueue operations
self.stack2 = [] # dequeue operations

def enqueue(self, x: int):
"""
Adds an element to the back of the queue.

Parameters:
x (int): The element to be added to the queue.
"""
self.stack1.append(x)

def dequeue(self) -> int:
"""
Removes and returns the front element of the queue.

Raises:
IndexError: If both stacks are empty, indicating that the queue is empty.

Returns:
int: The element at the front of the queue.
"""
if not self.stack1 and not self.stack2:
raise IndexError("Dequeue from an empty queue")

if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop())

return self.stack2.pop()

def __str__(self):
"""
Returns a string representation of the queue's current state.
"""
if not self.stack2:
return str(self.stack1)
return str(self.stack2[::-1] + self.stack1)


def test_queue_with_stacks():
"""
This function tests the functionality of a Queue implemented using two Stacks.

The QueueWithStacks class has two methods:
- enqueue(value): Adds an element to the end of the queue.
- dequeue(): Removes and returns the element at the front of the queue.

Raises:
IndexError: If the dequeue method is called on an empty queue.
"""
q = QueueWithStacks()
q.enqueue("Lesson1")
q.enqueue("Lesson2")

# Test first dequeue
first_out = q.dequeue()
print(f"Dequeued: {first_out} | Queue state: {q}")
assert first_out == "Lesson1"

# Test second and third dequeues
q.enqueue("Lesson3")
print(f"Queue after enqueueing 3-Lessons: {q}")

second_out = q.dequeue()
print(f"Dequeued: {second_out} | Queue state: {q}")
assert second_out == "Lesson2"

third_out = q.dequeue()
print(f"Dequeued: {third_out} | Queue state: {q}")
assert third_out == "Lesson3"

# Test dequeue on an empty queue
try:
empty_queue = QueueWithStacks()
empty_queue.dequeue()
assert False, "Did not raise IndexError for empty queue"
except IndexError:
print("IndexError raised as expected for empty queue")
assert True


if __name__ == "__main__":
test_queue_with_stacks()
print("All QueueWithStacks tests passed!")
Loading