Python: A Beginner's Guide to Data Structures and Algorithms
Tags: beginners, python, algorithms
Published: 2022-02-21 06:36:28



## **What are Data Structures?**
A data structure is a specialized data format that is used to store, organize, and manage data for efficient access and modification.

To understand data structures better, it is vital to see what drives the concept, and how it is an evolution from daily living. Organized storage is evident all around us, right from how phone books are recorded, arrangement in closets, car-parking lots, and even restaurant seating spaces. The idea behind the structuring storage is to allow ease of access and manipulation as necessary.

Just as every human ordered storage has features that differ from another, every data structure has different information that is unique to it, concerning information on the data values allowed, relationships between the data, and applicable functions.


**Why are Data Structures Needed?**

Data structures provide the right way to organize data, and ensure that a lot of data is accessed, used or, processed in a short interval of time. In this way, the ordered storage comes in handy to ensure no repetition, and ordered access, all of which are vital in big data systems such as Artificial Intelligence.

**Types of Data Structures in Python**
![Data Structures in Python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngqsnm5vj90z4qt2u435.png)
 

 

## Built-In Data Structures

Python has four built-in data structures:

**1. Lists**
Python lists are a versatile type of data structure that allow more than one data type to be stored at a time.
You can initialize and define a list by placing a sequence of items in squared brackets, and separating the elements by commas as below:

```
#initializing a list
list1= []

#initializing and defining lists with different data types
listNumbers= [1,2,3,4,5]

listNames=["Charlotte","Magdalene"]

listMixed=[1,2,"Charlotte"]
```
The order in a list follows indexing positions, whereby the first index position (index 0) is the first element in the list, and the second index position (index 1) is the second element in the list, and so on. Therefore, to **access list elements**, use the index operator `[]`, as below:

```
listNumbers= [1,2,3]

#print first number
print(listNumbers[0])

#print second number
print(listNumbers[1])

#print third number
print(listNumbers[2])
```
Other exciting features that list allows include: 
`print(listNumbers[0:2])` which prints object at index 0 and 1, but reject object[2].
`print(listNumbers[0:4:2])` which prints objects from index 0 to 4, in steps of 2, but reject object[4].
`print(listNumbers[0:4:2])` which prints objects from index 0 to 4, in steps of 2, but reject object[4].
`print(listNumbers[::-1])` which prints objects from the last index to the first index position.
`print(sorted[listNumbers])` which prints objects in ascending order, without changing the original list.
If you want to print your list in descending order, the code that can be used is `listNumbers.sort(reverse=true)`


Take note that the last index position is the total number of elements minus 1, to take care of the first index position beginning at 0, and not 1.

The three functions that can be used to **add more objects** into `listNumbers` are `append()`, `extend()`, and `insert()`, as shown below.

```
#add 4 to the end of the list
listNumbers.append(4)

#add 5 at the 4th index position
listNumbers.insert(4,5)
```
To **remove/delete objects from the list**, the following functions can be used:

- `del()`

- `pop()`

- `remove()`

```

#delete the object at index 3 from the list
del listNumbers(3)

#to remove objects at a specified index position, and store the objects that have been deleted.
a= listNumbers.pop(4)
print(a)

#to remove a specific object from known objects in a list.
b= listNumbers.pop(2)

#to know the index of a particular element in the list
print(listNumbers(3))
```

**2. Tuples**
A Tuple in python is a finite ordered list of objects separated by commas. Unlike lists, tuples are immutable, and are much faster. This means that its value cannot be updated.
You can initialize and define a tuple by placing a sequence of items in brackets, and separating the elements by commas as below:

```
tupleNumbers= (1,2,3)

#print first number
print(tupleNumbers[0])

#print second number
print(tupleNumbers[1])

#print third number
print(tupleNumbers[2])
```
Once a tuple is assigned, you cannot change data in it.

**3. Sets**
A set is an un-ordered collection of unique elements that is mutable. A set is initialized and defined as follows:

```
set1={1,2,3,4,5}
```
When a value is repeated in the definition of a set, upon printing it, the repeated value is done away with.

To **add elements **, use the function add(), for example, `set1.add(0)`.

Other operations that sets have are explored in the code below:

```
#union() combines two unions and eliminates repetitive values in the set.
set1.union(set2)

#intersection() prints the values that are repeated between sets that are being compared.
set1.intersection(set2)

#difference() prints the values that are unique for the first set in comparison to those in the set to which it is being compared.
set1.difference(set2)

#symmetricdifference() prints the values that are unique between sets that are being compared.
set1.symmetricdifference(set2)
```

**4. Dictionaries**
A dictionary is a mutable structure that holds key value pairs. A key value-pair associates a key with values, for example, a key could be last_Name, and it could be populated with different last names as its values.
A dictionary is initialized and defined as below:

```
dict1= {1: 'Javascript', 2: 'Java'}
```
In this case, 1 is the key for which Python is the value, and 2 is the key for which Java is the value.
Because it is mutable, trying to change a value in the dictionary will not throw an error, for example:

```
dict1= {1: 'Javascript', 2: 'Java'}
print(dict1)
dict1[1] = 'Python'
print(dict1)
```
Upon printing this, the output will be as below:
![Dictionary in Python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22xb48k306wrylk4emx0.png)

To **delete a value in a dictionary**, we use : `del dict1[1]`
You can also use `dict1.pop(1)` for the same purpose of deleting a value. Since pop() has a return value, you can print this to indicate the exact value that has been deleted.
`dict1.popitem()`can be used to remove the last value in a dictionary.

Other important functions are shown in the code snippet below:

```
#show all keys in the dictionary
print(dict1.keys())

#show all values in the dictionary
print(dict1.values())

#show all key-value pairs in the dictionary
print(dict1.items())
```



## User-Defined Data Structures

**1. Arrays**
Arrays are structures used to store data of a single type. This makes them almost similar to lists, with the difference that arrays are homogenous, and not heterogenous.

```
import array

arrayNumbers= array.array('i',[1,2,3,4,5])

for i in sample_array:

print (i)
```

**2. Stacks**
Stacks are made from arrays, and they follow the Last In First Out (LIFO) principle. They have a pointer called TOP that is used to track the top of the element. Below is an image showing how TOP keeps track of the top most element as elements are being pushed into a stack.

![TOP pointer in Stacks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5yd4yrs4nji5pqd260tp.png)

```
#initializing a stack
stack1=[]

val1= 1
val2 = 2

#appending values to the stack
stack1.append(val1)
stack1.append(val2)

#removing values from the stack in order of LIFO
stack.pop()
```
**3. Queues**
Queues are similar to stacks, but they follow the FIFO principle( First In First Out) Principle.
Additionally, operations can be performed from the beginning and the end of the queue.The En-Queue Operation keeps note of the head as the first element and the tail as the last element in that order as they are added:

![En-Queue Operation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/59wqszrjtt7dpkn601u0.png)

De-Queueing deletes elements in the order that they were stored in the queue.

```
from collections import deque
q = deque()

#adds elements in the order of the 1st one in
q.append(1)
q.append(2)

#removes elements in the order of the 1st one out
q.popleft()
q.popleft()
```

**4. Trees**
Trees are used in defining hierarchy, and start with a root/parent node as they move further down into child nodes. Trees are particularly useful in html code, where tags are defined from the parent node to leaves(child nodes).Leaves are the final nodes in the hierarchical chain. 

**5. Graphs**
In Python, graphs are used to store data in the form of edges and vertices. A graph is easily presented using the python dictionary data types, whereby the vertices are represented as keys of the dictionary, and the connection between the vertices( also known as edges) are represented as the values in the dictionary, as shown in the example below:

```
# To create a dictionary that displays graph elements
graphExample = { 
   "a" : ["b","c"],
   "b" : ["a", "d"],
   "c" : ["a", "d"],
   "d" : ["e"],
   "e" : ["d"]
}
# Print the graph 		 
print(graphExample)
```
This can represent the graph below:
![Graph in Python](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h6hbw6i7oxsb19ozu0cr.png)

Now that we understand data structures, let us move to algorithms.

## **What are Algorithms ?**

An algorithm is a pre-meditated set of steps that are used to complete a certain task for a desired output. It forms the building blocks through which programming of devices enables them to communicate or do other functions smoothly.
Taking the example of a GPS locator, with two use cases: locating a car, and avoiding traffic, there will be two separate algorithms to fulfill each task. If there is an error in the coding of any, the locator will not function correctly. This means that algorithms are in-built in machines to enable them make fast decisions efficiently.

Some important programming algorithms include:

- **Sort Algorithm**, that is used to rearrange a given array or list elements according to a comparison operator on the elements. The comparison operator is used to decide the new order of element in the respective data structure.
- **Searching Algorithm**, that is designed to check for an element or retrieve an element from any data structure where it is stored.
- **Recursive algorithm**, whereby a function calls itself with smaller input values and returns the result for the current input by carrying out basic operations on the returned value for the smaller input. 

**

## The Relationship between Data Structures and Algorithms
**
Data structures and algorithms interrelate to and complement each other, and when used with this in mind, an algorithm that is applied to the correct data structure can drastically improve the performance of the algorithm.

Some examples of algorithms that enhance the performance of data structures are:

1. **Search**- Helps find an item in a data structure.
2. **Insert**-Helps insert an item in a data structure.
3. **Sort**-Helps sort items in a data structure in the required order.
4. **Update**- Useful in updating/adding a data item in an existing data structure.