-
Notifications
You must be signed in to change notification settings - Fork 132
feat(python): Added Data Structures in Python #1038 #1055
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 3 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
32bb3bd
Added Core Data Structure Linked List, Queue, Stack
steam-bell-92 29d77dc
Corrected .md file paths in sidebars.ts
steam-bell-92 77b28e7
Corrected table structure in queue and stack .md files
steam-bell-92 198b311
Update docs/python/Data_Structures/python-queue.md
steam-bell-92 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| # Linked List in Python | ||
|
|
||
| A **Linked List** is a fundamental **linear data structure** where elements are **not** stored at contiguous memory locations (unlike arrays or Python lists). Instead, the elements, called **Nodes**, are linked together using **pointers** or **references**. | ||
|
|
||
| This structure allows for highly efficient **insertions** and **deletions** compared to arrays, where these operations can be slow. | ||
|
|
||
| --- | ||
|
|
||
| ## Structure of a Linked List | ||
|
|
||
| The linked list is built upon two core concepts: | ||
|
|
||
| 1. **Node:** The basic building block, which contains: | ||
| * **Data:** The value stored. | ||
| * **Next Pointer (`next`):** The reference to the next node in the sequence. | ||
| 2. **Head:** A pointer to the very first node in the list. It is the entry point for all operations. The last node's `next` pointer always points to **`None`**. | ||
|
|
||
| ### Real-Life Analogy | ||
|
|
||
| Think of a **treasure hunt or a chain of clues**. Each clue (**Node**) holds the information (**Data**) and a direction to the next clue (**Next Pointer**). You must follow the chain from the beginning (**Head**) to find the end. | ||
|
|
||
| --- | ||
|
|
||
| ## Python Implementation: The Node Class | ||
|
|
||
| Since Python doesn't have a built-in linked list type, we define its structure using classes. | ||
|
|
||
| The `Node` class defines the element structure. | ||
|
|
||
| ```python | ||
| class Node: | ||
| """Represents a single element in the linked list.""" | ||
| def __init__(self, data): | ||
| # Store the data | ||
| self.data = data | ||
| # Initialize the pointer to the next node | ||
| self.next = None | ||
| ``` | ||
|
|
||
| ## Python Implementation: The LinkedList Class | ||
|
|
||
| The `LinkedList` class manages the list, primarily by keeping track of the `head`. | ||
|
|
||
| ```python | ||
| class LinkedList: | ||
| """Manages the linked list and its head pointer.""" | ||
| def __init__(self): | ||
| # Initialize the list's entry point | ||
| self.head = None | ||
| ``` | ||
|
|
||
| ### Traversal: Printing the List | ||
|
|
||
| To traverse, we start at the head and loop until the current node becomes None, updating the current node with its next pointer in each iteration. | ||
|
|
||
| ```python | ||
| class LinkedList: | ||
| # __init__ and Node class definition here | ||
|
|
||
| def print_list(self): | ||
| current_node = self.head | ||
| print("List:", end=" ") | ||
| while current_node is not None: | ||
| print(current_node.data, end=" -> ") | ||
| current_node = current_node.next | ||
| print("None") | ||
| ``` | ||
| ***Example*** | ||
|
|
||
| ```python | ||
| my_list = LinkedList() | ||
| my_list.head = Node(10) | ||
| second = Node(20) | ||
| third = Node(30) | ||
|
|
||
| # Linking the nodes: 10 -> 20 -> 30 -> None | ||
| my_list.head.next = second | ||
| second.next = third | ||
| my_list.print_list() | ||
| ``` | ||
|
|
||
| **Output:** | ||
|
|
||
| ``` | ||
| List: 10 -> 20 -> 30 -> None | ||
| ``` | ||
|
|
||
| ### Insertion Operations | ||
|
|
||
| #### 1. Insertion at the Beginning (Prepend) | ||
|
|
||
| It only requires updating the head pointer. | ||
|
|
||
| ```python | ||
| def insert_at_beginning(self, new_data): | ||
| # Create a new node | ||
| new_node = Node(new_data) | ||
|
|
||
| # Make the new node's next pointer point to the current head | ||
| new_node.next = self.head | ||
|
|
||
| # Update the list's head to point to the new node | ||
| self.head = new_node | ||
| ``` | ||
|
|
||
| ***Example*** | ||
|
|
||
| ```python | ||
| my_list.insert_at_beginning(5) | ||
| my_list.print_list() | ||
| ``` | ||
|
|
||
| **Output:** | ||
|
|
||
| ``` | ||
| List: 5-> 10 -> 20 -> 30 -> None | ||
| ``` | ||
|
|
||
| #### 2. Insertion After a Node | ||
|
|
||
| ```python | ||
| def insert_after(self, prev_node, new_data): | ||
| if prev_node is None: | ||
| print("Previous node cannot be None.") | ||
| return | ||
|
|
||
| # Create the new node | ||
| new_node = Node(new_data) | ||
|
|
||
| # Set new node's next to the previous node's next | ||
| new_node.next = prev_node.next | ||
|
|
||
| # Set the previous node's next to the new node | ||
| prev_node.next = new_node | ||
| ``` | ||
|
|
||
| ***Example*** | ||
|
|
||
| ```python | ||
| my_list.insert_after(my_list.head, 15) | ||
| my_list.print_list() | ||
| ``` | ||
|
|
||
| **Output:** | ||
|
|
||
| ``` | ||
| List: 5-> 15-> 10 -> 20 -> 30 -> None | ||
| ``` | ||
|
|
||
| ### Deletion Operation | ||
|
|
||
| Deleting the Head | ||
|
|
||
| ```python | ||
| def delete_head(self): | ||
| if self.head is None: | ||
| return | ||
|
|
||
| # Move the head to the next node, which effectively "deletes" the old head | ||
| self.head = self.head.next | ||
| ``` | ||
|
|
||
| ***Example*** | ||
|
|
||
| ```python | ||
| my_list.delete_head() # Deletes head (5) | ||
| my_list.print_list() | ||
| ``` | ||
|
|
||
| **Output:** | ||
|
|
||
| ``` | ||
| List: 15-> 10 -> 20 -> 30 -> None | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| # Queue in Python | ||
|
|
||
| A **Queue** is a linear data structure that follows a specific order for all operations. This order is based on the **First-In, Last-Out (FILO)** principle. | ||
|
|
||
| Imagine a ticket line: the first person to join the line is the first person to be served and leave. | ||
|
|
||
| --- | ||
|
|
||
| ## Queue Operations | ||
|
|
||
| Queues have two distinct ends where operations occur: the **Rear** (for insertion) and the **Front** (for removal). | ||
|
|
||
| | Operation | Description | Analogy | | ||
| | :--- | :--- | :--- | | ||
| | **Enqueue** | Adds an element to the **Rear**. | Joining the back of the line. | | ||
| | **Dequeue** | Removes an element from the **Front**. | Leaving the front of the line. | | ||
| | **Peek** | Returns the front element without removing it. | Looking at the person next in line. | | ||
|
|
||
| --- | ||
|
|
||
| ## Queue Operations Using Python List | ||
|
|
||
| In the simplest Python implementation, we use a built-in **`list`** as the underlying storage. For a true FIFO queue: | ||
|
|
||
| * **Enqueue** is performed using `list.append()` (at the rear/end). | ||
| * **Dequeue** is performed using `list.pop(0)` (from the front/start). | ||
| * **Peek** is performed using list indexing `list[0]` (at the fromt/start). | ||
|
|
||
| ### The Queue Class | ||
|
|
||
| ```python | ||
| class Queue: | ||
| """Implements a Queue using the FIFO principle with a Python list.""" | ||
| def __init__(self): | ||
| # The storage container for the queue elements | ||
| self._items = [] | ||
|
|
||
| def is_empty(self): | ||
| """Check if the queue is empty.""" | ||
| return not self._items | ||
|
|
||
| def enqueue(self, data): | ||
| """Adds an element to the rear of the queue (list.append()). (O(1))""" | ||
| self._items.append(data) | ||
| print(f"Enqueued: {data}") | ||
|
|
||
| def dequeue(self): | ||
| """Removes and returns the front element (list.pop(0)). (O(N))""" | ||
| if self.is_empty(): | ||
| raise IndexError("Error: Cannot dequeue from an empty queue.") | ||
|
|
||
| # pop(0) removes the first item (the front of the queue) | ||
| return self._items.pop(0) | ||
|
|
||
| def peek(self): | ||
| """Returns the front element without removing it.""" | ||
| if self.is_empty(): | ||
| raise IndexError("Error: Cannot peek at an empty queue.") | ||
|
|
||
| # Access the first item (0 index) | ||
| return self._items[0] | ||
| ``` | ||
|
|
||
| ***Example*** | ||
|
|
||
| ```python | ||
| my_queue = Queue() | ||
| my_queue.enqueue("Task 1") | ||
| my_queue.enqueue("Task 2") | ||
| my_queue.enqueue("Task 3") | ||
|
|
||
| print("\nFront element (Peek):", my_queue.peek()) | ||
|
|
||
| served_item = my_queue.dequeue() | ||
| print("Dequeued element:", served_item) | ||
|
|
||
| print("Queue Status:", my_queue._items) | ||
|
|
||
| my_queue.dequeue() | ||
| my_queue.dequeue() | ||
|
|
||
| # my_queue.dequeue() # Uncommenting this line will raise an IndexError | ||
| ``` | ||
|
|
||
| **Output**: | ||
|
|
||
| ``` | ||
| Enqueued: Task 1 | ||
| Enqueued: Task 2 | ||
| Enqueued: Task 3 | ||
|
|
||
| Front element (Peek): Task 1 | ||
| Dequeued element: Task 1 | ||
| Queue Status: ['Task 2', 'Task 3'] | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| # Stack in Python | ||
|
|
||
| A **Stack** is a linear data structure that follows a specific order for all operations. This order is based on the **Last-In, First-Out (LIFO)** principle. | ||
|
|
||
| Imagine a stack of plates: you can only add a new plate to the top, and you can only remove the plate that is currently on the top. | ||
|
|
||
| --- | ||
|
|
||
| ## Stack Operations | ||
|
|
||
| A stack has three primary operations, all of which occur at the **Top** of the stack: | ||
|
|
||
| 1. `Push`: **Adds** an element to the top of the stack. | ||
| 2. `Pop`: **Removes** and returns the element from the top of the stack. | ||
| 3. `Peek`: **Returns** the element at the top. | ||
|
|
||
| | Operation | Description | Analogy | | ||
| | :--- | :--- | :--- | | ||
| | **Push** | Add element to the **Top** | Placing a plate on top of the stack | | ||
| | **Pop** | Remove element from the **Top** | Taking the top plate off the stack | | ||
| | **Peek** | View the element at the **Top** | Looking at the top plate | | ||
|
|
||
| --- | ||
|
|
||
| ## Stack Operations Using Python | ||
| ListIn the simplest Python implementation, we use a built-in list as the underlying storage. For a true LIFO stack, all primary operations are performed at the end of the list: | ||
|
|
||
| * **Push** is performed using `list.append()`. | ||
| * **Pop** is performed using `list.pop()`. | ||
| * **Peek** is performed using list indexing `list[-1]`. | ||
|
|
||
| --- | ||
| ## The Stack Class | ||
|
|
||
| ```python | ||
| class Stack: | ||
| """Implements a Stack using the LIFO principle with a Python list.""" | ||
| def __init__(self): | ||
| # The storage container for the stack elements | ||
| self._items = [] | ||
|
|
||
| def is_empty(self): | ||
| """Check if the stack is empty.""" | ||
| return not self._items | ||
|
|
||
| def push(self, data): | ||
| """Adds an element to the top of the stack (list.append()).""" | ||
| self._items.append(data) | ||
| print(f"Pushed: {data}") | ||
|
|
||
| def pop(self): | ||
| """Removes and returns the top element (list.pop()).""" | ||
| if self.is_empty(): | ||
| raise IndexError("Error: Cannot pop from an empty stack.") | ||
|
|
||
| # Pop removes the last item (the top of the stack) | ||
| return self._items.pop() | ||
|
|
||
| def peek(self): | ||
| """Returns the top element without removing it.""" | ||
| if self.is_empty(): | ||
| raise IndexError("Error: Cannot peek at an empty stack.") | ||
|
|
||
| # Access the last item (-1 index) | ||
| return self._items[-1] | ||
| ``` | ||
|
|
||
| ***Example*** | ||
|
|
||
| ```python | ||
| my_stack = Stack() | ||
| my_stack.push("A") | ||
| my_stack.push("B") | ||
| my_stack.push("C") | ||
|
|
||
| print("\nTop element (Peek):", my_stack.peek()) | ||
|
|
||
| removed_item = my_stack.pop() | ||
| print("Popped element:", removed_item) | ||
|
|
||
| print("Current size:", len(my_stack._items)) | ||
|
|
||
| my_stack.pop() | ||
| my_stack.pop() | ||
|
|
||
| # my_stack.pop() # Uncommenting this line will raise an IndexError | ||
| ``` | ||
|
|
||
| **Output**: | ||
|
|
||
| ``` | ||
| Pushed: A | ||
| Pushed: B | ||
| Pushed: C | ||
|
|
||
| Top element (Peek): C | ||
| Popped element: C | ||
| Current size: 2 | ||
| ``` |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.