# Common Data Structures

·

5 min read

## Table of contents

Data structures are the basic building blocks of programming. They offer distinct methods of organizing data to ensure efficient access based on your specific needs.

### List

• It is `mutable`, which means its elements can be modified after creation.

• Lists can contain elements of `different data types` and can be accessed, modified, and iterated upon easily.

``````  list_value = [2,3,5,7,11]

print(list_value[0]) # output = 2
print(list_value[1]) # output = 3
print(list_value[-1]) #output = 11
print(list_value[-2]) #output = 7
``````

Methods

``````  '''Various list methods'''

list_value = [0, 1, 2, 3, 4]
list_value.append(5)
print(list_value)  # Output: [0, 1, 2, 3, 4, 5]

list_value.clear()
print(list_value)  # Output: []

list_value = [0, 1, 2, 3, 4]
new_list = list_value.copy()
print(new_list)  # Output: [0, 1, 2, 3, 4]

list_value = [0, 1, 2, 3, 4, 1, 2, 1]
count = list_value.count(1)
print(count)  # Output: 3

list_value.extend([5, 6, 7])
print(list_value)  # Output: [0, 1, 2, 3, 4, 1, 2, 1, 5, 6, 7]

index = list_value.index(3)
print(index)  # Output: 3

list_value.insert(2, "hello")
print(list_value)  # Output: [0, 1, 'hello', 2, 3, 4, 1, 2, 1, 5, 6, 7]

popped_element = list_value.pop(3)  # Removes and returns the element at index 3
print(popped_element)  # Output: 2
print(list_value)  # Output: [0, 1, 'hello', 3, 4, 1, 2, 1, 5, 6, 7]

list_value.remove(1)  # Removes the first occurrence of 1
print(list_value)  # Output: [0, 'hello', 3, 4, 1, 2, 1, 5, 6, 7]

list_value.reverse()
print(list_value)  # Output: [7, 6, 5, 1, 2, 1, 4, 3, 'hello', 0]

list_value.sort()
print(list_value)  # Output: [0, 1, 1, 2, 3, 4, 5, 6, 7]
``````

Slicing

• Python allows you to extract a portion of a list by specifying a `start` index, an `end` index, and an optional `step` value.For instance, (list_name`[start:end:step]`)

``````  list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# Basic slicing examples
print(list[2:6])     # Output: [2, 3, 4, 5]
print(list[:4])      # Output: [0, 1, 2, 3]
print(list[6:])      # Output: [6, 7, 8, 9]
print(list[1:8:2])   # Output: [1, 3, 5, 7]

# Negative indices slicing examples
print(list[-5:-2])   # Output: [5, 6, 7]
print(list[-4:])     # Output: [6, 7, 8, 9]
print(list[:-3])     # Output: [0, 1, 2, 3, 4, 5, 6]

# Step value slicing examples
print(list[::2])     # Output: [0, 2, 4, 6, 8]
print(list[1:8:3])   # Output: [1, 4, 7]
``````

### Tuples

• Tuples are `immutable`, meaning their elements cannot be modified after creation.

• They are used to represent fixed collections of related values.

``````  # Creating a tuple
my_tuple = (1, 2, 'a', 'b')

# Accessing elements
print(my_tuple[0])    # Output: 1
print(my_tuple[2])    # Output: 'a'

# Trying to modify elements (results in an error)
my_tuple[1] = 'x'    # TypeError: 'tuple' object does not support item assignment
``````

### Dictionary

• Dictionaries are associative data structures that store data as `key-value` pairs.

• They provide fast and efficient access to values based on their corresponding `keys`.

• Keys within a dictionary must be `unique`, and they are typically `immutable` data types, such as strings or numbers.

``````  # Creating a dictionary
my_dict = {'name': 'Nirmal', 'age': 23, 'city': 'Butwal'}

# Accessing elements
print(my_dict['name'])    # Output: 'Nirmal'
print(my_dict['age'])     # Output: 23

# Modifying elements
my_dict['age'] = 26
print(my_dict['age'])     # Output: 26

# Adding new elements
my_dict['occupation'] = 'Engineer'
print(my_dict) # Output: {'name': 'Nirmal', 'age': 26, 'city': 'Butwal', 'occupation': 'Engineer'}

# Iterating over the dictionary
for key, value in my_dict.items():
print(key, ':', value)
``````

### Sets and Frozenset

• Sets are unordered collections of `unique elements`, while frozenset is an `immutable version` of a set in Python.

• Sets are used to perform mathematical set operations like `union`, `intersection`, and `difference`.

``````  set_value = {1, 2, 3, 4, 5}# Creating a set
set_value.add(6)# Adding elements to a set
set_value.remove(3)# Removing elements from a set

# Checking membership
print(2 in set_value)  # Output: True

set1 = {1, 2, 3}
set2 = {3, 4, 5}

print(set1.union(set2))         # Output: {1, 2, 3, 4, 5}
print(set1.intersection(set2))  # Output: {3}
print(set1.difference(set2))    # Output: {1, 2}
``````
``````   '''Implementing frozenset'''
#Set is mutable
s = {1,2,3,4}
s.add(5) # s = {1,2,3,4,5}

#Making immutable using frozenset
value = frozenset(s)
value.add(6) # raise error
``````

### Array

• Unlike lists, arrays are fixed in size and can only hold elements of the same data type.

• Arrays provide faster access and better memory efficiency compared to lists when working with large amounts of data.

``````  import array

# Creating an array of integers
int_array = array.array('i', [1, 2, 3, 4, 5])

# Creating an array of floating-point numbers
float_array = array.array('f', [1.0, 2.5, 3.7, 4.2])

print(int_array)      # Output: array('i', [1, 2, 3, 4, 5])
print(float_array)    # Output: array('f', [1.0, 2.5, 3.7, 4.2])
``````

### Stacks(LIFOS)

• A stack is a linear data structure that follows the First-In-Last-Out (FILO) principle.

• It operates in a similar way to a stack of objects, where the last object placed on top is the first one to be removed.

``````  # Create an empty stack
stack_value = []

# Push elements onto the stack
stack_value.append(10)
stack_value.append(20)
stack_value.append(30)

# Pop elements from the stack
print(stack_value.pop())  # Output: 30
print(stack_value.pop())  # Output: 20

# Check if the stack is empty
print(len(stack_value) == 0)  # Output: False

# Get the size of the stack
print(len(stack_value))  # Output: 1
``````

### Queues(FIFOS)

• A queue is a linear data structure that follows the `First-In-First-Out (FIFO)` principle.

• It works similarly to a real-world queue, where the person who arrives first is served first.

• In a queue, elements are added at the tail(end) and removed from the head(front).

``````  import queue

queue_value = queue.Queue()# Create a queue object

# Enqueue(add) elements into the queue
queue_value.put(10)
queue_value.put(20)
queue_value.put(30)
print(queue_value)#<queue.Queue object at 0x7fb483786b80>

# Dequeue(get and remove) elements from the front of the queue
print(queue_value.get())  # Output: 10
print(queue_value.get())  # Output: 20

# Check if the queue is empty
print(queue_value.empty())  # Output: False

# Get the size of the queue
print(queue_value.qsize())  # Output: 1
``````

### Priority Queues

• A priority queue is a data structure where elements are assigned priorities and the element with the highest priority is dequeued first.

• Elements are enqueued with a priority value, and the queue automatically sorts the elements based on their priorities.

``````  import queue

priority_queue = queue.PriorityQueue()# Create a priority queue object

# Enqueue elements into the priority queue
priority_queue.put((3, "Apple"))
priority_queue.put((1, "Banana"))
priority_queue.put((2, "Orange"))

# Dequeue elements from the priority queue
print(priority_queue.get())  # Output: (1, 'Banana')
print(priority_queue.get())  # Output: (2, 'Orange')

# Check if the priority queue is empty
print(priority_queue.empty())  # Output: False

# Get the size of the priority queue
print(priority_queue.qsize())  # Output: 1
``````