Published on

A Summary of The Most Used Ones

Authors
  • avatar
    Name
    Jonathan Juliani
    Twitter

Get to Know the Power of Data Structures and Algorithms

In daily basis of IT projects, when we are programming, we are always focused on delivering our products and features on time. Sometimes we forget the importance of algorithms and data structures that could make our code work more efficiently.

These concepts are like the pillars that support the efficiency of our work. Let's take a look together at some of the main algorithms and data structures that we usually see in interviews, challenges, etc., and understand how they work and where we can use them.

estrutura-de-dados

Commonly Used Algorithms and Data Structures

I want to show you some cool things: structures, algorithms, and how they are present in our daily lives, my idea here is to use very simple examples, nothing complicated (I'll try, I promise). This way, we can easily remember how and where to use these tools and enjoy these powerful resources without stress. Let's go!

1. Arrays: The Most Common Data Structure

Arrays são como listas que guardam elementos em sequência, facilitando guardar e acessar dados rapidamente por meio de índices. São super comuns na programação para várias necessidades, como listas de tarefas, compras ou produtos.

Basicamente, sempre que você tem uma coleção de itens organizados, provavelmente está usando um array. Pegou a ideia né?

Arrays are like lists that store elements in sequence, making it easier to store and access data quickly through indexes. They are super and probably you use them a lot, a few examples are: to-do lists, purchases or product lists.

Basically, whenever we have a collection of items, we're probably using (or will use) an array. You got the idea, right?

estrutura-de-dados-arrays

2. Linked Lists: Flexibility to Store Data

Linked lists are like a train where each train wagon, or “node”, not only carries the information we are storing, but also indicates which wagon is the next on the line.

Unlike arrays, each element is linked to the next, making it easy to add or remove items without touching the entire array. In double linked lists, each node knows both, its next and previous nodes, making it even more easier to navigate back and forth. This is great for tasks like quick insertions and deletions.

A simple example is the browser history, where each page visited is a node, allowing you to easily go back and forth between pages, so each node (or page) knows what is the previous one or the next one if it exists. Linked list:

estrutura-de-dados-lista-ligada

Double Linked List:

estrutura-de-dados-lista-duplamente-ligada

3. Stacks: LIFO (Last In, First Out)

Stacks follow the rule of “last in, first out” (LIFO). Stacks are ideal for controlling sequences of actions, such as change histories, where the most recent change is always the first to be accessed or viewed in a list.

So imagine a stack of plates: the last plate placed is at the top of the pile, so it is the first one to be removed. A change history follows the same principle, the last change is usually the first to be shown.

data structure - stacks

4. Queues: FIFO (First In, First Out)

Queues follow FIFO (First In, First Out) logic, so the first to enter is the first to leave. They are perfect for situations where order matters, such as task management or sequential process execution.

Imagine a queue of people waiting to be served: whoever arrives first is served first (I mean, in most cases - but you got the ideia, it's not a perfect example kkk).

So when developing software these same rules applies to various operations, such as processing steps in a purchase, where each step follows a specific order (checking the stock, creating the order, etc.). Queues ensure that everything happens in the right sequence.

data structure - queues

5. Trees: Hierarchy and Organization

Until now everything was fine, right? Did you hear/read the "tree" word and you started to sweat? Imposter syndrome? Hands shaking? Take a breath! It's not that bad, I'll try to explain it, okay?

Trees are data structures that organize information into hierarchies, unlike arrays which are linear. In a tree, each element, or “node”, can have “children”, creating a branch structure.

It's like the folders on your computer: a main folder can contain several other folders, and each one can contain more children folders, and so on. This kind of configuration is super useful in databases and file systems, where the relationship between data is not simply side by side, but rather one within or below the other, allowing you to organize and access information efficiently.

Think of the folders on your PC as a practical example of a tree structure in action, we see it as folders, but it's a tree structure, we're just not seeing it in the code.

Did that make sense?

trees

I won't lie to you, to complicate a little bit we can classify a tree based on it's structure, we will explore more about that in a future post, this is a mere introduction. So, nice to meet you tree!

6. Graphs: Modeling Complex Relationships

Hey, did impostor syndrome already hit? Let's see how we do with Graphs.

Graphs are structures that connect nodes (or memory points with data) in flexible ways, unlike arrays or trees, let me explain: In a graph, each node can have several connections with others, without following a fixed hierarchy as in trees, so, trees have a parent node with children but graphs in the other hand can have a bi-directional conection between its nodes, so you don't have childs or parent nodes, they are connected at the same hierarchy.

This allows you to represent complex relationships, like routes on a map. Imagine using a navigation app to get from point A to point B: there are many possible paths, each with its own streets and directions.

In graphs, this is how nodes relate to each other, allowing you to explore different connections until you find the desired information or the ideal path to it.

grafos

Graphs can be complex, and like Trees there are some sub-types depending on the shape and information of the graph. Have you ever coded a graph? Have you ever maintained any graph code? Tell me in the comments bellow.

7. Hash Tables: Search Efficiency

Hash Tables are structures that organize data efficiently, working with a key-value system, similar to Maps (similar, it's not a map).

The big deal with hash tables is that instead of searching directly for the key, we use a hash function that transforms this key into an index of an array where the value are stored. This may seem like an extra step, but it makes the search faster if we compare with common arrays. The trick is to deal well with situations where two different keys result in the same index, this is known as "collision".

Hash Tables are an excellent option when we need to quickly access information and maintain data where uniqueness is crucial. (keep in mind the uniqueness word here).

hash tables

For instance: if we need to analyze a text and count how many times a certain word or number is mentioned in the text, we can create a Hash Table and for each word or number we want to count, we map a counter and count the frequency that the elements appear in the text.

8. Heaps: One of The Special Types of Trees

Heaps are Trees. What happens is that Heaps are a special type of trees used to keep elements organized in a certain way, this facilitates operations such as ordering and priority queue management.

Imagine a tree that always knows who should be at the top (root level of the tree) based on certain rules — that's how heaps work. They are super useful in situations such as distributing tasks between servers or even recommending products online based on specific rules.

For instance: after doing a purchase at some website, the recommended products that appear may be sorted using a heap. This ordering is based on several different criteria such as popularity, relevance, etc., ensuring that people see what interests them most first.

heap-type trees

Heaps are also known by the classification of "Max Heap" and "Min Heap". Another cool aspect about Heaps is that they can help implement Priority Queues, which we will talk about now:

9. Priority Queues

Combining characteristics of queues and heaps, Priority Queues are structures that organize elements not in the order that they arrive, but rather by the priority of each one. Imagine a mix of ordinary queues and heaps, where what matters is how important an item is, not when it arrived.

This feature causes higher priority items to be served first, regardless of their position in the queue.

This is super useful in situations such as operating systems that need to decide which process to run first, recommendation systems that show more relevant content, or even in databases to prioritize queries. Basically, it's like having a shortcut whenever something really important needs to be done.

priority queues

10. Maps and Sets: Organization and Uniqueness

Maps store key-value pairs, so each block of information has a key and a value that you set. Maps are very similar to Hash Tables, but here we don't have a hash that points to an index and then we find the value, here in Map we have a key that points directly to the value.

![key-value maps](/static/images/pt/key-value maps.png)

Sets do not have a key-value structure like map, in terms of structure, sets are similar to Arrays but with a special rule, Sets have unique elements, that is, Sets don't allow you to have duplicated elements, it will give you an error if you try to include the same value twice.

set of values

Maps are widely used in caching systems, and also for instance in mapping data to requests, where a field "X" needs to be mapped to a field "Y" in an API call to other services.

Sets are widely used when we want to remove duplicate items from Arrays, another example would be data entry into an API, if you have an API that receives JSON for example, you can use a Set to ensure that this JSON does not come with duplicate fields.

11. Binary Search Trees

Trees again… Well at least if you learn one, you will easy remember the others, right?

Binary Search Tree is a tree, what happens here is the same that happens in Heaps: for a Binary Search Tree exist, it needs to have (or follow) some “special” characteristics.

Let's call "binary search tree" BST okay?! I don’t want to write “binary search tree” all the time… So, what characteristics should we note when looking at a BST? So all the values in the left nodes are smaller, while all the values in the right nodes are larger. Got it? Just that simple!.

binary search trees

I don't wanna be "cliche" here but when we talk about BSTs the best examples are maps and navigation systems, for instance storing points or paths to facilitate the search for specific points and/or locations. You can try and mention auto-complete features as good examples of BST but they become more interesting with a more specific implementation called Tries, and we gonna talk about "Tries":

12. Trie: Prefix Search Optimization

Trees once again... "Trie(s)" is a tree structure as well, and what happens here is similar to what happens in the others I mentioned above. For a Trie to exist, the tree needs to have some "special" characteristics, and in this case it is even more special. Tries are trees focused on working with text.

tries-tree structure

Tries store strings efficiently, generally each node has a character and the path (structure) of the Trie nodes forms a complete word (string). A good example of use is for dictionaries and complex auto-completion systems, like when you go to Google and enter the letter A and a bunch of words and complete phrases appear that start with the letter A.

13. Graphs Algorithms (Dijkstra, Bellman-Ford)

I'm not going to lie, this kind of algorithm is not on our daily basis, unless you're working on a very specific project. But if you paid attention from the first to 12th items above, most of what I'm going to say here you already have some basic understanding. When we are talking about Dijkstra or Bellman-Ford algorithms, we are talking about Graphs, so it's not a type of Graph here we are talking about algorithms that traverse graphs, and the main goal is to find the shortest path between points "A" and "G" for instance.

shortest path graphs

This kind of thing is not something you're going to implement every day, or change every day, again - unless you work on specific projects that deal with these types of structures for a specific reason - ,like GPS, navigation systems in general, communication systems and networks, etc. But hey, stay tuned, I will do a post implementing one of these and we gonna talk about it a little bit.

14. Sorting Algorithms (QuickSort, MergeSort, BubbleSort): The Art of Sorting Data

So, after Dijkstra and Bellman-Ford, sorting algorithms are easy peasy, right?!

When you have an array and need to sort it, there are several ways to do this. Although programming languages already come with sorting functions, sometimes we want to explore other ways to understand their efficiencies or by simple curiosity. Let's talk about three popular sorting algorithms, explaining them simply:

BubbleSort: One of the most basic methods, where you compare adjacent items and swap them if they are in the wrong order. It's like going through the array, changing pairs until everything is sorted.

QuickSort: Fast and efficient, uses the divide and conquer technique. Choose a “pivot” and organize the array so that smaller elements are before and larger ones are after, repeating the process in the sub-arrays.

MergeSort: It also follows the logic of divide and conquer, but always divides the array in half. Sort each half and then combine them in an orderly fashion. It is a process of dividing, ordering and joining. See an example of merge-sort:

merge sort

So, what about your programming language, do you know which algorithm is used when you do a sort? Did you know that some languages mix multiple algorithms to have better overall efficiency?

Common searchs usually go one by one in an array looking for the desired information. In binary search, it's different. Here we compare the element we are looking for with the element in the middle of the array, and then we divide the array in half. We repeat this process in the half of the promising array we just got, and we keep this process until we find the item or run out of options. It sounds complex, but it's simple. The key here is that the search is only effective in ordered(sorted) lists, only then does this algorithm shines.

binary search

A good example of binary search is when you have some kind of dictionary and you need to look up a word. Since this kind of thing is usually in order, binary search can make a difference depending on the size of the dictionary. Remember, the key here is that the list should be ordered.

Choosing the Best Tool for Each Task

As developers and engineers we have to choose the right data structure for each challenge, I know sometimes we forget about that, sometimes it doesn't worth to build a complex data structure to a simple project, and we also often forget how to implement and deal with all this data strutures, that's the main reason I did this post, to remember us, and to have a few examples and reminders on good places to use this knowledge. If you're looking for this data structures and algorithms for a interview, please, after you pass, comment bellow if the project really use complex data structures, I really wanna know how often other developers and engineers face this kind of code.

But keep in mind that understanding these structures and algorithms can help us build better software. Which data structure do you use most in your projects or in your company? Share it and let's learn together!