Python Training , study and exam guide
1 Introduction to Python
1.1 What is Python?
1.2 History of Python
1.3 Features of Python
1.4 Python Applications
1.5 Setting up the Python Environment
1.6 Running Your First Python Program
2 Python Basics
2.1 Python Syntax and Indentation
2.2 Variables and Data Types
2.2 1 Numbers
2.2 2 Strings
2.2 3 Lists
2.2 4 Tuples
2.2 5 Sets
2.2 6 Dictionaries
2.3 Operators
2.3 1 Arithmetic Operators
2.3 2 Comparison Operators
2.3 3 Logical Operators
2.3 4 Assignment Operators
2.3 5 Membership Operators
2.3 6 Identity Operators
2.4 Input and Output
2.4 1 Input Function
2.4 2 Output Function
2.5 Comments
2.5 1 Single-line Comments
2.5 2 Multi-line Comments
3 Control Flow
3.1 Conditional Statements
3.1 1 If Statement
3.1 2 If-Else Statement
3.1 3 Elif Statement
3.1 4 Nested If Statements
3.2 Loops
3.2 1 For Loop
3.2 2 While Loop
3.2 3 Nested Loops
3.3 Loop Control Statements
3.3 1 Break Statement
3.3 2 Continue Statement
3.3 3 Pass Statement
4 Functions
4.1 Defining Functions
4.2 Function Arguments
4.2 1 Positional Arguments
4.2 2 Keyword Arguments
4.2 3 Default Arguments
4.2 4 Variable-length Arguments
4.3 Return Statement
4.4 Lambda Functions
4.5 Scope of Variables
4.5 1 Local Variables
4.5 2 Global Variables
4.6 Recursion
5 Data Structures
5.1 Lists
5.1 1 List Operations
5.1 2 List Methods
5.1 3 List Comprehensions
5.2 Tuples
5.2 1 Tuple Operations
5.2 2 Tuple Methods
5.3 Sets
5.3 1 Set Operations
5.3 2 Set Methods
5.4 Dictionaries
5.4 1 Dictionary Operations
5.4 2 Dictionary Methods
5.5 Advanced Data Structures
5.5 1 Stacks
5.5 2 Queues
5.5 3 Linked Lists
6 Modules and Packages
6.1 Importing Modules
6.2 Creating Modules
6.3 Standard Library Modules
6.3 1 Math Module
6.3 2 Random Module
6.3 3 DateTime Module
6.4 Creating Packages
6.5 Installing External Packages
7 File Handling
7.1 Opening and Closing Files
7.2 Reading from Files
7.2 1 read()
7.2 2 readline()
7.2 3 readlines()
7.3 Writing to Files
7.3 1 write()
7.3 2 writelines()
7.4 File Modes
7.5 Working with CSV Files
7.6 Working with JSON Files
8 Exception Handling
8.1 Try and Except Blocks
8.2 Handling Multiple Exceptions
8.3 Finally Block
8.4 Raising Exceptions
8.5 Custom Exceptions
9 Object-Oriented Programming (OOP)
9.1 Classes and Objects
9.2 Attributes and Methods
9.3 Constructors and Destructors
9.4 Inheritance
9.4 1 Single Inheritance
9.4 2 Multiple Inheritance
9.4 3 Multilevel Inheritance
9.5 Polymorphism
9.6 Encapsulation
9.7 Abstraction
10 Working with Libraries
10.1 NumPy
10.1 1 Introduction to NumPy
10.1 2 Creating NumPy Arrays
10.1 3 Array Operations
10.2 Pandas
10.2 1 Introduction to Pandas
10.2 2 DataFrames and Series
10.2 3 Data Manipulation
10.3 Matplotlib
10.3 1 Introduction to Matplotlib
10.3 2 Plotting Graphs
10.3 3 Customizing Plots
10.4 Scikit-learn
10.4 1 Introduction to Scikit-learn
10.4 2 Machine Learning Basics
10.4 3 Model Training and Evaluation
11 Web Development with Python
11.1 Introduction to Web Development
11.2 Flask Framework
11.2 1 Setting Up Flask
11.2 2 Routing
11.2 3 Templates
11.2 4 Forms and Validation
11.3 Django Framework
11.3 1 Setting Up Django
11.3 2 Models and Databases
11.3 3 Views and Templates
11.3 4 Forms and Authentication
12 Final Exam Preparation
12.1 Review of Key Concepts
12.2 Practice Questions
12.3 Mock Exams
12.4 Exam Tips and Strategies
5 5 Advanced Data Structures Explained

5 5 Advanced Data Structures Explained

Key Concepts

Advanced data structures in Python provide more complex and efficient ways to manage and manipulate data. The key concepts include:

1. Stacks

A stack is a collection of elements with two principal operations: push (add an element to the top) and pop (remove the top element). It follows the Last In, First Out (LIFO) principle.

Example:

class Stack:
    def __init__(self):
        self.items = []

    def push(self, item):
        self.items.append(item)

    def pop(self):
        return self.items.pop()

    def is_empty(self):
        return len(self.items) == 0

stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.pop())  # Output: 3
print(stack.pop())  # Output: 2
    

Analogy: Think of a stack as a stack of plates. The last plate you put on top is the first one you take off.

2. Queues

A queue is a collection of elements with two principal operations: enqueue (add an element to the end) and dequeue (remove the front element). It follows the First In, First Out (FIFO) principle.

Example:

from collections import deque

class Queue:
    def __init__(self):
        self.items = deque()

    def enqueue(self, item):
        self.items.append(item)

    def dequeue(self):
        return self.items.popleft()

    def is_empty(self):
        return len(self.items) == 0

queue = Queue()
queue.enqueue(1)
queue.enqueue(2)
queue.enqueue(3)
print(queue.dequeue())  # Output: 1
print(queue.dequeue())  # Output: 2
    

Analogy: Think of a queue as a line of people waiting for a bus. The first person in line is the first one to get on the bus.

3. Deques

A deque (double-ended queue) is a collection of elements that allows insertion and deletion at both ends. It is more flexible than both stacks and queues.

Example:

from collections import deque

deque = deque()
deque.append(1)
deque.append(2)
deque.appendleft(0)
print(deque)  # Output: deque([0, 1, 2])
deque.pop()
deque.popleft()
print(deque)  # Output: deque([1])
    

Analogy: Think of a deque as a train where you can add or remove cars from either end.

4. Heaps

A heap is a specialized tree-based data structure that satisfies the heap property. In a min-heap, the key at the root is the smallest, and in a max-heap, the key at the root is the largest.

Example:

import heapq

heap = []
heapq.heappush(heap, 3)
heapq.heappush(heap, 1)
heapq.heappush(heap, 2)
print(heapq.heappop(heap))  # Output: 1
print(heapq.heappop(heap))  # Output: 2
    

Analogy: Think of a heap as a pile of items where the smallest (or largest) item is always on top.

5. Graphs

A graph is a collection of nodes (vertices) and edges connecting these nodes. Graphs are used to represent relationships between objects.

Example:

class Graph:
    def __init__(self):
        self.graph = {}

    def add_edge(self, u, v):
        if u in self.graph:
            self.graph[u].append(v)
        else:
            self.graph[u] = [v]

    def show_graph(self):
        return self.graph

graph = Graph()
graph.add_edge(0, 1)
graph.add_edge(0, 2)
graph.add_edge(1, 2)
graph.add_edge(2, 0)
graph.add_edge(2, 3)
graph.add_edge(3, 3)
print(graph.show_graph())  # Output: {0: [1, 2], 1: [2], 2: [0, 3], 3: [3]}
    

Analogy: Think of a graph as a network of cities connected by roads. Each city is a node, and each road is an edge.

Putting It All Together

By understanding and using these advanced data structures effectively, you can solve complex problems in various domains such as computer science, data analysis, and network theory. These structures provide efficient ways to manage and manipulate data, making your code more powerful and versatile.

Example:

# Using a stack to reverse a string
def reverse_string(s):
    stack = Stack()
    for char in s:
        stack.push(char)
    reversed_string = ''
    while not stack.is_empty():
        reversed_string += stack.pop()
    return reversed_string

print(reverse_string("hello"))  # Output: olleh