Data Structures
Data Structures
The simplest way to answer their question is by describing data structures as a way of organizing and
storing data so that operations can be performed efficiently. This leads us to the question, what kind of
operations are we talking about? Accessing, inserting, deleting, finding, and sorting the data are some of
the basic operations that one can perform using data structures. Not all data structures can perform
these operations efficiently, that’s what led to the development of different data structures. Let’s say
you are to find a specific book in an unorganized library, that task would take an enormous amount of
time. Just like a library organizes their books, we need to organize our data so that operations can be
performed efficiently.
If you have previous experience with programming, you might know what a pre-defined data type is. A
pre-defined data type such as Integer, Strings, Boolean is used to create the structure of data. The use of
data type is based on the user requirement and the kind of data they want to store. Now let’s dive into
the data structures that are used in our day to day programming, and we will also look into the support
for the data structures for different programming languages.
A basic data structure which one uses in a day to day programming is an array. An array can hold a fixed
number of containers to store data and operations could be performed on that data according to the
user’s needs.
In the picture above, an array is defined with the name arrayName and has an integer data type. The
number below in the bold shows the memory address each container of an array is assigned to. The
important thing here to remember is an array index always starts at 0 and ends at (total array size -1).
So, let’s just say you defined an array of length 5, arrayName[5], then the indexes of this array would
be arrayName[0], arrayName[1], arrayName[2], arrayName[3], arrayName[4].
Multidimensional Arrays
A multidimensional array is just an extension of the normal array, where we define an array with a row
of containers. In case of a multidimensional array, we have rows as well as columns. In order to access
an index, we need two numbers to get there.
In the picture above, we defined an arrayName[3][4] with 3 rows and 4 columns and in total of Row *
Column (3*4) indexes. Multidimensional arrays are sometimes referred to as tables or matrix because of
their structure.
Dynamic Arrays
Most of the programming languages allow you to define dynamic arrays, which means the memory is
allocated during program execution. Consider it this way, you defined an array with 10 indexes but, you
only need 3 indexes, thus the remaining 7 indexes are laid to waste, thereby consuming extra memory.
Dynamic arrays give you the flexibility to allocate memory according to the program requirement.
Java :- There are a couple of classes for arrays, but the best known one is ArrayList class.
C++ :- Vectors are used to represent the dynamic arrays in C++. It can be implemented using std::vector.
Python :- Python has a new data type known as list just like Boolean and Integers. The list data type can
be used to dynamically define arrays.
A linked list is a collection of nodes that are connected by links. Linked list contains node which store the
data items and the address to the next node. The first node is usually referred to as the head node and
the last node is referred to as the tail node. The pointer of the head node points to the next node and
the pointer of the tail node points to Null.
The dynamics of this data structure makes it easier to add or remove nodes from the end. In order to
add/remove a node, you just need to keep track of the previous node and the node after and adjust the
pointers accordingly.
A doubly linked list is not much different from a singly linked list, the only thing that sets them apart is
the pointer to the previous node. The picture below can give you a brief idea of what the structure
should look like.
In the case of a doubly linked list, the previous pointer of the head node points to Null and the next
pointer of the tail points to Null. The previous pointer makes it easier to traverse in either direction. So,
node addition and removal become super easy, all you need to do is keep track of the previous node
and the next node and adjust the pointer accordingly.
A circular linked list is a linked list where all the nodes are connected to form a circle. There is no head
or tail node. The advantage of having this type of linked list is any node can be used as a starting point.
A list is a different type of data structure from an array. Instead of storing data in chunks of memory the
array requires a contiguous memory space. If you add an element to an array, it might change the
memory location of the entire array, but the data remains intact. An array gives you the index number,
therefore, you can access it directly or sequentially. Whereas to access any data member you must
traverse through the entire list.
Java :- Java has an inbuilt class called LinkedList which can be used to implement a linked list.
C++ :- Like Java, C++ has also a Standard Template Library called list for linked list implementation.
Python :- Python also has an inbuilt module llist which implements linked lists.
Stack
You have probably heard this word in your day to day life, whether it is referring to a deck of cards or
books lying on top of a desk. Well, the data structure works in a similar manner as you would perform
actions on a real-world stack. For example, you can only add or remove books from the top of the stack.
A stack is a LIFO data structure which means Last In First Out, the last item to come is the first one to go
out. A stack can either be implemented using an array or a linked list. Consider a stack of books, the last
book would obviously be placed at the top and if you want to remove a book you will remove one from
the top. The three basic operations a stack could perform are:
· Push — to input data into stack and place it on top.
The picture below shows the effect of these operations on the structure
Java :- Java has an inbuilt class called Stack which can be used to implement stack data structures.
C++ :- Like Java, C++ has also a Standard Template Library called stackfor linked list implementation.
Python :- Python does not have an explicit stack class, but lists can be implemented as stacks.
Queue
Just like the word stack, the word queue is also derived from day to day activities. You have most likely
seen a queue of people in a supermarket at the billing counter where the last one to come stands at the
end and the first one to come is the first one to get their groceries check out. In the similar manner,
queue works where the operations are performed at both ends.
A stack is a FIFO data structure which elaborates to First In First Out. A queue, like stack, can either be
implemented using arrays or linked list. The three most commonly performed operations on queue are:
· enqueue — to input data into stack and place them at the bottom.
C++ :- Like Java, C++ has also a Standard Template Library called Queuefor queue implementation.
Python :- The queue module in python offers the functionality of the queueclass. Since queues can be
implemented using linked list therefore, llist can also be used.
Trees
The tree data structure resembles an upside tree, at the top we have a root node which is divided into a
left and a right node. They have links between them, which connect all the nodes. Unlike linked list
where a node can be connected to only one node, a tree could have a node connected to two or more
nodes.
Binary Trees
Binary trees are special kind of trees where the left node is always smaller than the parent node and the
right node is always bigger than the parent node. In order to add/delete a node we have to compare the
value with the root node and then traverse to a specific point to insert/delete.
Support for Linked Lists for different programming languages
Java :- Java doesn’t have any built-in class to implement tree data structure.
C++ :- Just like Java, C++ also doesn’t have any container in standard template library to implement
trees.
Python :- Python doesn’t have built-in data structures so in order to implement a tree you have to create
the structure manually.
Conclusion
There are some points you need to consider while deciding which data structure satisfies your need.
Unless you have a really big set of data, it doesn’t matter which data structure you use. The questions
you need to ask yourself before implementing a data structure is:
What is the purpose of the data? Do you need to access, insert, delete, or sort the data?
The algorithms work differently with different data structures and across different programming
languages, so you need to understand the respective syntax of the language before implementing a data
structure.
Stack is a concept mainly used in data structures and uses the order of LIFO
(Last-In-First-Out). Stacks are used with the help of array and linked list to push
and pop the new item in the memory stack for allocation of memory space. This
article explains all about the stack, its various operations and the areas where the
stacks are used as it’s generally referred to.
Stack
Stack is a concept mainly used in data structures. Stack is used with the array
concept and used for data inserting, modifying and recovering purpose. Stack use
the concept of LIFO (Last-In-First-Out). LIFO refers, as the stack operations will be
performed on the data that is in the last segment of the array. Stack can also be
used in linked-list but at the minimum level compared with array.
Stack Operations
Let us know see about the major operations performed by stack. Stack generally
performs three operations out of which the first two are the important ones. The
operations of the stack are as follows:
Push
Pop
Top
Push
Push operation is used to insert an item in the stack. Push operation also performs whether the
stack is empty and if it is empty then Push operation will add or insert an item in to the stack.
Once the stack is full and there is no memory space to add an item, the push operation will
inform that the stack is in overflow state. So, no new item can be inserted into the stack.
Pop
Pop operation is used to delete or remove an item from the stack. Pop operation also performs
whether the stack is full or not. If the stack is full, the Pop operation will delete the item one by
one from the stack till the stack reach empty. Once the stack is empty, Pop operation will return
the message as the stack is in underflow state. So, there is no item in the stack to delete or
remove.
Top
The Top operation checks whether the stack contains the item in the top-most position, so that it
will inform the item to the requestor.
Stack Applications
Prefix expression
Infix expression
Postfix expression
Memory management
The post expression contains the operators at the end of the operands.
Example: abc+-
Stack is used for the conversion of prefix to infix, prefix to postfix, infix to prefix, infix to
postfix, postfix to prefix, postfix to infix expressions. The operators and the operands will be
included in the stack as per the defined way used in the algorithm and then stack use the
operations Push and Pop according the expression conversion whether its being infix, prefix or
postfix.
Applications of Queue Data Structure
Queue is used when things don’t have to be processed immediately, but have to be processed
in First In First Out order like Breadth First Search. This property of Queue makes it also useful in
following kind of scenarios.
1) When a resource is shared among multiple consumers. Examples include CPU scheduling, Disk
Scheduling.
2) When data is transferred asynchronously (data not necessarily received at same rate as sent)
between two processes. Examples include IO Buffers, pipes, file IO, etc.
Simple Queue
Image Source
As is clear from the name itself, simple queue lets us perform the operations simply.
i.e., the insertion and deletions are performed likewise. Insertion occurs at the rear
(end) of the queue and deletions are performed at the front (beginning) of the queue
list.
All nodes are connected to each other in a sequential manner. The pointer of the first
node points to the value of the second and so on.
The first node has no pointer pointing towards it whereas the last node has no pointer
pointing out from it.
Circular Queue
Image Source
Unlike the simple queues, in a circular queue each node is connected to the next node
in sequence but the last node’s pointer is also connected to the first node’s address.
Hence, the last node and the first node also gets connected making a circular link
overall.
Priority Queue
Image Source
Priority queue makes data retrieval possible only through a pre determined priority
number assigned to the data items.
While the deletion is performed in accordance to priority number (the data item with
highest priority is removed first), insertion is performed only in the order.
Queues are an important concept of the data structures and understanding their types
is very necessary for working appropriately with them.
1. struct node {
2. int data;
3. struct node *next;
4. }
1. /* Initialize nodes */
2. struct node *head;
3. struct node *one = NULL;
4. struct node *two = NULL;
5. struct node *three = NULL;
6.
7. /* Allocate memory */
8. one = malloc(sizeof(struct node));
9. two = malloc(sizeof(struct node));
10. three = malloc(sizeof(struct node));
11.
12. /* Assign data values */
13. one->data = 1;
14. two->data = 2;
15. three->data = 3;
16.
17. /* Connect nodes */
18. one->next = two;
19. two->next = three;
20. three->next = NULL;
21.
22. /* Save address of first node in head */
23. head = one;
Doubly Linked List
We add a pointer to the previous node in a doubly linked list. Thus, we can go in either
direction: forward or backward.
A node is represented as
1. struct node {
2. int data;
3. struct node *next;
4. struct node *prev;
5. }
1. /* Initialize nodes */
2. struct node *head;
3. struct node *one = NULL;
4. struct node *two = NULL;
5. struct node *three = NULL;
6.
7. /* Allocate memory */
8. one = malloc(sizeof(struct node));
9. two = malloc(sizeof(struct node));
10. three = malloc(sizeof(struct node));
11.
12. /* Assign data values */
13. one->data = 1;
14. two->data = 2;
15. three->data = 3;
16.
17. /* Connect nodes */
18. one->next = two;
19. one->prev = NULL;
20.
21. two->next = three;
22. two->prev = one;
23.
24. three->next = NULL;
25. three->prev = two;
26.
27. /* Save address of first node in head */
28. head = one;
Circular Linked List
A circular linked list is a variation of linked list in which the last element is linked to the
first element. This forms a circular loop.
for singly linked list, next pointer of last item points to the first item
In doubly linked list, prev pointer of first item points to last item as well.
1. /* Initialize nodes */
2. struct node *head;
3. struct node *one = NULL;
4. struct node *two = NULL;
5. struct node *three = NULL;
6.
7. /* Allocate memory */
8. one = malloc(sizeof(struct node));
9. two = malloc(sizeof(struct node));
10. three = malloc(sizeof(struct node));
11.
12. /* Assign data values */
13. one->data = 1;
14. two->data = 2;
15. three->data = 3;
16.
17. /* Connect nodes */
18. one->next = two;
19. two->next = three;
20. three->next = one;
21.
22. /* Save address of first node in head */
23. head = one;