Table of Contents
Candidates for software engineering must show that they understand data structures as well as their applications. Almost every issue necessitates a thorough understanding of data structures on the part of the applicant. It makes no difference whether you’ve recently graduated from a university or a coding boot camp or have decades of experience.
“Given a binary tree” is an example of an interview query that directly mentions a data structure. Often it’s stated explicitly, such as “we want to keep track of the number of books associated with each author.” Even if you’re only trying to get better at your current work, learning data structures is important.
When choosing the best data structure for a given job, it’s important to consider how different data structures behave at lower levels.
Let’s begin by learning the fundamentals.
What is the concept of a data structure?
Consider a data structure as a container for data that is organized in a particular way.
This “style” permits a data structure to be effective in some operations while being inefficient in others.
You aim to learn about data structures to select the best for the problem at hand.
What is the purpose of Data Structures?
Since data structures are used to organize data and because data is the most important thing in computer science, their true value is obvious.
Whatever issue you’re trying to solve, you’ll have to deal with data in some way — whether it’s an employee’s wage, stock rates, a shopping list, or even a basic phone directory.
Depending on the situation, storage of data has to be stored in a certain format.
We have a few data structures that cover our requirements for storing data in various formats.
Data Structures that are widely used:
Let’s start with a list of the most widely used data structures and then go through each individually.
Below is the list of the widely used data structures:
- Linked Lists
The most common and commonly used data structure is an array. A selection of objects of the same variable type stored sequentially in memory is known as an array.
It’s one of the most popular and straightforward data structures, and it’s often used in the implementation of other data structures. An array’s items are indexed from 0 to 1, and each object is referred to as an element. It’s also worth remembering that you can’t adjust the size of an array in Java. It is recommended that you use a List for dynamic sizes. Arrays are used to create other data structures such as stacks and queues.
Here’s an example of a simple four-dimensional array of components (1, 2, 3, and 4).
Each data element is given a positive numerical value called the index, representing the item’s location in the collection.
The majority of languages set the array’s starting index to 0.
The two forms of arrays are as follows:
- arrays of just one dimension
- Arrays of multiple dimensions (arrays within arrays)
Array Operations at a Simple Level
Inserts an element at a defined index.
Get —Returns the element of the index that has been provided.
Delete — Removes an element from a list at a particular index.
Size — Returns the array’s total number of elements.
Array interview questions that are often asked
- Find the array’s second smallest piece.
- The array’s first non-repeating integers
- Combination of two sorted arrays
- Rearrange the list so that it is in decreasing order.
- Rotate the array to the right by one index.
- Divide and conquer full sum subarray
- In an array, rearrange the positive and negative values.
Application of arrays
Multi-dimensional arrays are possible (array of arrays). As a result, arrays are an excellent alternative for storing matrices and vectors. Other data structures such as lists, heaps, stacks, and queues are often implemented using arrays.
The popular Undo option, which is present in almost every application, is well-known.
Have you ever wondered how it all works?
The principle is that you save the previous states of your work (which are limited to a certain number) in memory in the order that they appear, with the most recent one appearing first. Arrays cannot solely implement the latter. As a result, the Stack comes in handy in this situation.
A stack of books stacked vertically may be a real-life example of Stack.
Getting the book in the center entails removing the books that have been put on top of it.
The LIFO (Last In First Out) system works in this way.
Here’s an illustration of a stack of three data elements (1, 2, and 3), with 3 at the top and removed first:
Stack operations are as follows:
Push — Adds a new feature to the top of the list.
Pop — Recovers the top element from the Stack after it has been removed.
Top — Returns the top part of the Stack without removing it.
Stack interview questions that are often asked
- Using a stack, evaluate the postfix expression.
- In a stack, sort the values.
- Create an array of two stacks.
- Using a stack as the next greater element
- In an expression, make sure the parentheses are balanced.
Applications of stacks
- Mathematical expressions are handled and evaluated using stacks.
- They’re also used in algorithms that use a backtracking process.
- Another application is recursive function calls in recursive programming.
Queue, like Stack, is a linear data structure that stores elements in sequential order.
The only major difference between Stack and Queue is that Queue implements the FIFO method, which stands for First In First Out, rather than the LIFO method.
A great real-life example of a Queue is a line of people in line for a ticket booth.
Someone enters the line from the end, then the person at the front will be the first to collect the ticket and exit the line.
Consider a Queue of four data elements (1, 2, 3, and 4), with 1 at the top and the first to be removed:
Queue’s fundamental operations include:
Enqueue() — Adds a new feature to the Queue’s edge.
Dequeue() — Removes an element from the Queue’s beginning.
Empty() — If the Queue is empty, it returns valid.
Top () — Returns the Queue’s first element.
Queue interview questions that are often asked
- Using a queue to implement a stack.
- Reverse a queue’s first k elements
- Using a queue, generate binary numbers from 1 to n.
Application of Queues
- Buffers are implemented using queues
- Sharing a resource with a group of people
- Make a directory
- When data is transmitted asynchronously between two resources, it is called asynchronous data transfer.
- Queues are used in multi-threading to handle tasks that are waiting to be executed by threads.
A linked list is not just a vital data structure, but it resembles arrays at first glance. It differs in terms of the internal structure, memory allocation, and how simple insertion and deletion operations are performed.
A linked list is similar to a network of nodes. Because each node containing data and a pointer to the next node in the chain.
There’s a head pointer that points to the first element of the linked list, and it simply points to null or zeroes if the list is empty.
File structures, hash tables, and adjacency lists are all implemented using linked lists.
The types of linked lists are as follows:
- Singly Linked List is a form of a list that has only one component (Unidirectional)
- Doubly Linked List – has Two Links (Bi-directional)
- Circular linked list – This is where instead of the tail pointing to null, it points to the head. Overall, there is no tail. Instead, there is one head.
The following are the basic operations of a Linked List:
InsertAtEnd — Adds a defined element to the linked list’s end.
InsertAtHead — Inserts a given element at the linked list’s start/head.
Delete — Removes a particular item from a related list.
DeleteAtHead — Removes the linked list’s first portion.
isEmpty — Checks to ascertain if the linked list is empty.
Search — Checks for the presence of a given element in a linked list and returns true if found. Otherwise, it returns false.
Linked List interview questions that are often asked
- Reverse the order of a connected list
- In a connected list, find a loop.
- In a connected list, return the Nth node from the top.
Finding the middle value in a linked list
- Duplicates in a related list should be excluded.
Applications of Linked Lists
- Data structures such as hash tables, stacks, queues, and graphs are implemented using linked lists.
- Allocation of memory dynamically
- Creation of directories
- Related lists are used to store constants when performing polynomial algebra operations.
When more nodes come together to form a linked network, we get what we call a graph.
Vertices are another name for nodes.
An edge is a pair(x,y) that indicates that vertex x is connected to vertex y. It can also contain weight/cost, which indicates how much it costs to traverse from vertex x to vertex y.
Graphs come in a variety of shapes and sizes. They consist of:
- Graph with no direction
- Graph with Directions
Graphs can be interpreted in two ways in programming languages:
- Matrix of Adjacency
- Adjacency List Algorithms for traversing graphs:
Graph interview questions that are often asked
- Implement a first-search approach that involves both scope and depth.
- Determine whether or not a graph is a tree. Then get the count of the edges in a graph.
- The shortest path between two vertices must be found.
Applications of Graphs
- Graphs are used in social media applications like Facebook to portray users as vertices and friendships as edges.
- Graphs were used to represent web pages and the ties that linked them in the Google Page Ranking Algorithm.
- In its transportation networks, Google Maps uses graphs to reflect the road network.
A tree is made up of nodes forming a hierarchical data structure. These include vertices and edges, which are connections between vertices. Trees are similar to graphs, but the main difference is that a loop cannot occur in a tree.
Trees are widely used in Artificial Intelligence and complex algorithms to provide an effective problem-solving storage mechanism.
Here’s an example of a simple tree, along with some common tree data structure terminology:
The forms of trees are as follows:
- N-ary Tree
- Binary Tree
- Binary Search Tree
- 2–3 Tree AVL Tree
- Red Black Tree
The Binary Tree and Binary Search Tree are the most widely used trees among those mentioned above.
A directed graph and a binary tree have certain similarities. The distinction between the two is that data is stored in a hierarchical structure in a binary tree, with upper-level nodes referred to as parents and lower-level nodes referred to as children. Besides, in a binary tree, each node can only have one parent and two children.
Let’s take a look at some binary tree terminology.
- The node at the top of the tree is known as the root, and it does not have a parent node.
- A leaf is a node at the base of a branch. Further, it does not have any children nodes.
- The data value stored in a node is referred to as the key.
- A subtree is a tree that contains all of a node’s descendants.
Binary Search Tree, Treap, Binary Tries, and Heap are only a few examples of unique binary trees.
Binary Search Tree
The data values are stored in sorted order in a binary search tree. However, in a binary search tree, the left child of a node must have a value less than the parent, while the right child must have a value greater than the parent.
As the name implies, the key benefit of a BST is the ability to search for stored data quickly. In fact, the quest for a stored element in a BST has an O time complexity (log n).
Tree interview questions that are often asked
- Calculate the height of a binary tree
- In a binary search tree, find the kth maximum value
- Locate nodes at a distance of “k” from the source
- In a binary tree, find the ancestors of a given node
Application of Trees
- In programming languages, binary search trees are used to implement map and set properties.
- Treaps are a form of wireless networking protocol.
Tries are all effectively trees, but it’s always useful to distinguish them. In that regard, a Trie is also known as “Prefix Trees” and is a tree-like data structure that has proved to be very useful in solving string problems. It allows for fast retrieval and is widely used to search terms in dictionaries, provide auto recommendations in search engines, and even IP routing.
Here’s an example of how Trie stores the three terms “ball”, “bat”, “doll”, “do”, “dork”, “dorm”, “send”, “sense”:
The words are organized from top to bottom.
Trie interview questions that are often asked include:
- Count how many words there are in Trie
- Obtain a list of all words stored in Trie
- Using Trie, sort the elements of an array
- Using Trie, construct terms from a dictionary
- Create a T9 dictionary
Application of Tries
- Router tables are stored using binary tries
- Creating a Trie Search Tree
Hashing is a method of uniquely identifying objects and storing them at a pre-calculated unique index known as their “key.” As a result, the object is saved as a “key-value” pair. And a “dictionary” is a list of such objects.
On a huge dataset, we want to keep scanning and inserting operations as fast as possible.
Any data value stored in a hash table has a key that allows us to access the value quickly if we know the key. Consider a student registration system in which each student has a unique student ID that can be used as a key in a hash table to store their information. In that case, the key can be used to search for each item.
Hashing can create a variety of data structures, but the hash table is the most common.
Arrays are widely used to implement hash tables by storing data values in hash tables. Thus, the key determines the index within the array where the value is stored. Hash tables, on the other hand, map these keys to their values in a unique way.
Direct addressing is one of the approaches that can be used. It employs one-to-one mapping, with each key pointing to the precise location where its data is stored. However, as the number of key-value pairs increases and the keys increase in size, this method does not use memory effectively. Hash tables, on the other hand, depend on hash functions as a result.
Role of hashing
A hash function is used to map data values to their keys in hash tables, i.e., it transforms a set of key values into a set of array indexes. In this case, the hash value is the index or value provided by passing the key to the hash function.
A collision occurs when the hash values generated by two keys are identical. To deal with collisions, hash tables employ techniques such as chaining and open addressing.
The searching and insertion time complexity of hash tables is O (1).
These three factors influence the efficiency of hashing data structures:
- Collision Handling Method
- Hash Function
- Size of the Hash Table
A Hash Function is used to determine the array’s index.
Hashing interview questions that are often asked
- In an array, find symmetric pairs
- Trace a journey’s entire course
- Determine if one collection is a subset of another
- Determine if the given arrays are disjoint
Application of hash tables
- Database indexes are implemented using hash tables
- Compilers use hash tables to classify keywords in programming languages
- Hashing is used in the union and intersection of lists
- Computers use hash tables to connect file names to their routes
Another kind of binary tree is the heap. In heaps, the root’s key is compared to the children’s keys to organize them in a particular order.
There are two different kinds of heaps as follows:
Max heap: The parent’s key is greater than or equal to the child’s key. Thus, the maximum value in the given dataset is stored in the root node.
Min heap: The parent’s key is less than or equal to the child’s key. As a result, the minimum value in the given dataset is stored in the root node.
Consider the following dataset: integer values (16, 14, 10, 8, 7, 9, 3). From this info, we can create a separate max heap and min-heap as follows:
The time complexity of adding, removing, and extracting the full (or minimum) functions in a heap is O(log n). However, finding the limit (or minimum) takes just O minutes (1).
applications of heaps
- The heapsort algorithm is implemented using heaps.
- Priority queues are implemented using heaps because the heap’s first element always stores the value with the highest (or lowest) priority.
The use of maps
A map is a data structure in which data is stored in key/value pairs, with each key being unique. Map implementations include using arrays, linked-list, hash tables, and binary search trees. Besides, an associative array or dictionary is another name for a map.
It’s often used for quick data lookup in circumstances where the key can be termed as a unique identifier for the given object. In this case, the key determines where the object is stored in the structure. If you prefer to put it otherwise, then the key associated with the given object is viewed as the object’s address.
Common methods in maps
size() – returns the size of the map
isEmpty() – establishes if the given map is empty
Get (K) – this method searches for a key k and returns an entry with k if it is contained in the map and null if it is not found.
Put (k, v) – If the map does not have an entry k, this method is responsible for adding key k with an associated entry value v. If the key already exists. The new entry v will replace the existing value.
remove(k) – deletes an entry in the map with the key k
The following are some of the things that maps help you to do:
- a new pair has been added to the set
- the deletion of a pair from the collection the alteration of a pair already in the collection
- the quest for a value associated with a specific key
- Maps are applicable in searching
This article offered a brief introduction to the underlying logic of ten data structures that programmers encounter daily. These are primarily the data structures you should know before walking into any coding interview.
With this understanding of various data structures’ distinct properties, you will be more deliberate in selecting the most suitable data structure for your programming task starting today.