 GFG App
Open App Browser
Continue

# Introduction to Linear Data Structures

Linear data structures are data structures in which data elements are stored in a linear sequence. They include:

1. Arrays: A collection of elements stored in contiguous memory locations.
2. Linked Lists: A collection of nodes, each containing an element and a reference to the next node.
3. Stacks: A collection of elements with Last-In-First-Out (LIFO) order.
4. Queues: A collection of elements with First-In-First-Out (FIFO) order.
5. Linear data structures are used in many computer science applications such as searching, sorting, and manipulating data. They offer efficient data access, but may require additional memory for maintaining pointers between elements.

A data structure is a particular way of organizing data in a computer so that it can be used effectively. The idea is to reduce the space and time complexities of different tasks. Below is an overview of some popular linear data structures.

Array

The array is a data structure used to store homogeneous elements at contiguous locations. The size of an array must be provided before storing data.

.An array is a linear data structure that store a sequence of elements.

.An array is defined as it is a collection of items stored at memory (contiguous memory locations).

.’We can also say that arrays are the set of homogeneous(it can hold only one type of data the data that is all floating numbers or all characters or all integers numbers); data elements stored multiple items of the same type together in one place in memory.

.Array use an index-based data structure which helps to identify each of the elements in array .makes it easier to calculate, what the position of each element is by simply adding an offset to a base value.

.Single sub-scripted values are called linear array or one- dimensional array and Array can also handle complex data structures by storing data in a two-subscripted variables are called as two-dimensional array.

```Let size of array be n.
Accessing Time: O(1) [This is possible because elements
are stored at contiguous locations]
Search Time:   O(n) for Sequential Search:
O(log n) for Binary Search [If Array is sorted]
Insertion Time: O(n) [The worst case occurs when insertion
happens at the Beginning of an array and
requires shifting all of the elements]
Deletion Time: O(n) [The worst case occurs when deletion
happens at the Beginning of an array and
requires shifting all of the elements]```

Example: For example, let us say, we want to store marks of all students in a class, we can use an array to store them. This helps in reducing the use of a number of variables as we don’t need to create a separate variable for marks of every subject. All marks can be accessed by simply traversing the array.

1. Constant-time Access: Arrays allow for constant-time access to elements by using their index, making it a good choice for implementing algorithms that need fast access to elements.
2. Memory Allocation: Arrays are stored in contiguous memory locations, which makes the memory allocation efficient.
3. Easy to Implement: Arrays are easy to implement and can be used with basic programming constructs like loops and conditionals.

1. Fixed Size: Arrays have a fixed size, so once they are created, the size cannot be changed. This can lead to memory waste if an array is too large or dynamic resizing overhead if an array is too small.
2. Slow Insertion and Deletion: Inserting or deleting elements in an array can be slow, especially if the operation needs to be performed in the middle of the array. This requires shifting all elements to make room for the new element or to fill the gap left by the deleted element.
3. Cache Misses: Arrays can suffer from cache misses if elements are not accessed in sequential order, which can lead to poor performance.
4. In summary, arrays are a good choice for problems where constant-time access to elements and efficient memory allocation are required, but their disadvantages should be considered for problems where dynamic resizing and fast insertion/deletion operations are important.

A linked list is a linear data structure (like arrays) where each element is a separate object. A linked list is made up of two items that are data and a reference to the next node. A reference to the next node is given with the help of pointers and data is the value of a node. Each node contains data and links to the other nodes. It is an ordered collection of data elements called a node and the linear order is maintained by pointers. It has an upper hand over the array as the number of nodes i.e. the size of the linked list is not fixed and can grow and shrink as and when required, unlike arrays.

1. Singly Linked List: In this type of linked list, every node stores the address or reference of the next node in the list and the last node has the next address or reference as NULL. For example 1->2->3->4->NULL

2. Doubly Linked List: In this type of Linked list, there are two references associated with each node, One of the reference points to the next node and one to the previous node. The advantage of this data structure is that we can traverse in both directions and for deletion, we don’t need to have explicit access to the previous node. Eg. NULL<-1<->2<->3->NULL

3. Circular Linked List: Circular linked list is a linked list where all nodes are connected to form a circle. There is no NULL at the end. A circular linked list can be a singly circular linked list or a doubly circular linked list. The advantage of this data structure is that any node can be made as starting node. This is useful in the implementation of the circular queues in the linked list. Eg. 1->2->3->1 [The next pointer of the last node is pointing to the first]

4. Circular Doubly Linked List: The circular doubly linked list is a combination of the doubly linked list and the circular linked list. It means that this linked list is bidirectional and contains two pointers and the last pointer points to the first pointer.

```Accessing time of an element : O(n)
Search time of an element : O(n)
Insertion of an Element : O(1) [If we are at the position
where we have to insert
an element]
Deletion of an Element : O(1) [If we know address of node
previous to the node to be
deleted] ```

Example: Consider the previous example where we made an array of marks of students. Now if a new subject is added to the course, its marks are also to be added to the array of marks. But the size of the array was fixed and it is already full so it can not add any new element. If we make an array of a size lot more than the number of subjects it is possible that most of the array will remain empty. We reduce the space wastage Linked List is formed which adds a node only when a new element is introduced. Insertions and deletions also become easier with a linked list.
One big drawback of a linked list is, random access is not allowed. With arrays, we can access i’th element in O(1) time. In the linked list, it takes Θ(i) time.

1. Dynamic Size: Linked lists are dynamic in size, so they can grow or shrink as needed without wasting memory.
2. Efficient Insertion and Deletion: Linked lists provide efficient insertion and deletion operations, as only the pointers to the previous and next nodes need to be updated.
3. Cache Friendliness: Linked lists can be cache-friendly, as they allow for linear access to elements, which can lead to better cache utilization and improved performance.

1. Slow Access: Linked lists do not allow for constant-time access to elements by index, so accessing an element in the middle of the list can be slow.
2. More Memory Overhead: Linked lists require more memory overhead compared to arrays, as each element in the list is stored as a node, which contains a value and a pointer to the next node.
3. Harder to Implement: Linked lists can be harder to implement than arrays, as they require the use of pointers and linked data structures.
4. In summary, linked lists are a good choice for problems where dynamic size and efficient insertion/deletion operations are important, but their disadvantages should be considered for problems where constant-time access to elements is necessary.

Stack

A stack or LIFO (last in, first out) is an abstract data type that serves as a collection of elements, with two principal operations: push, which adds an element to the collection, and pop, which removes the last element that was added. In stack both the operations of push and pop take place at the same end that is top of the stack. It can be implemented by using both array and linked list.

It is defined as ordered collection of elements represented by a real physical stack or pile. Linear data structure features insertion and deletion of items take place at one end called top of the stack. You can use these concepts or structures all throughout programming.

```Insertion : O(1)
Deletion :  O(1)
Access Time : O(n) [Worst Case]
Insertion and Deletion are allowed on one end. ```

Example: Stacks are used for maintaining function calls (the last called function must finish execution first), we can always remove recursion with the help of stacks. Stacks are also used in cases where we have to reverse a word, check for balanced parenthesis, and in editors where the word you typed the last is the first to be removed when you use undo operation. Similarly, to implement back functionality in web browsers.

Primary Stack Operations:

• void push(int data): When this operation is performed, an element is inserted into the stack.
• int pop():   When this operation is performed, an element is removed from the top of the stack and is returned.

Auxiliary Stack Operations:

• int top(): This operation will return the last inserted element that is at the top without removing it.
• int size(): This operation will return the size of the stack i.e. the total number of elements present in the stack.
• int isEmpty(): This operation indicates whether the stack is empty or not.
• int isFull(): This operation indicates whether the stack is full or not.

Types of Stacks:

• Register Stack: This type of stack is also a memory element present in the memory unit and can handle a small amount of data only. The height of the register stack is always limited as the size of the register stack is very small compared to the memory.
• Memory Stack: This type of stack can handle a large amount of memory data. The height of the memory stack is flexible as it occupies a large amount of memory data.

1. LIFO (Last-In, First-Out) Order: Stacks allow for elements to be stored and retrieved in a LIFO order, which is useful for implementing algorithms like depth-first search.
2. Efficient Operations: Stacks provide efficient push-and-pop operations, as only the top element needs to be updated.
3. Easy to Implement: Stacks can be easily implemented using arrays or linked lists, making them a simple data structure to understand and use.

1. Fixed Size: Stacks have a fixed size, so they can suffer from overflow if too many elements are added or underflow if too many elements are removed.
2. Limited Operations: Stacks only allow for push, pop, and peek (accessing the top element) operations, so they are not suitable for implementing algorithms that require constant-time access to elements or efficient insertion and deletion operations.
3. Unbalanced Operations: Stacks can become unbalanced if push and pop operations are performed unevenly, leading to overflow or underflow.
4. In summary, stacks are a good choice for problems where LIFO order and efficient push and pop operations are important, but their disadvantages should be considered for problems that require dynamic resizing, constant-time access to elements, or more complex operations.

Queue

A queue or FIFO (first in, first out) is an abstract data type that serves as a collection of elements, with two principal operations: enqueue, the process of adding an element to the collection. (The element is added from the rear side) and dequeue the process of removing the first element that was added. (The element is removed from the front side). It can be implemented by using both array and linked list. A queue is defined as a linear data structure that is open at both ends.

```Insertion : O(1)
Deletion  : O(1)
Access Time : O(n) [Worst Case]```

Example: Queue as the name says is the data structure built according to the queues of a bus stop or train where the person who is standing in the front of the queue(standing for the longest time) is the first one to get the ticket. So any situation where resources are shared among multiple users and served on a first come first serve basis. Examples include CPU scheduling, Disk Scheduling. Another application of queue is when data is transferred asynchronously (data not necessarily received at the same rate as sent) between two processes. Examples include IO Buffers, pipes, file IO, etc.

Basic Operations on Queue:

• void enqueue(int data): Inserts an element at the end of the queue i.e. at the rear end.
• int dequeue(): This operation removes and returns an element that is at the front end of the queue.

Auxiliary Operations on Queue:

• int front(): This operation returns the element at the front end without removing it.
• int rear(): This operation returns the element at the rear end without removing it.
• int isEmpty(): This operation indicates whether the queue is empty or not.
• int size(): This operation returns the size of the queue i.e. the total number of elements it contains.

Types of Queues:

• Simple Queue: Simple queue also known as a linear queue is the most basic version of a queue. Here, insertion of an element i.e. the Enqueue operation takes place at the rear end and removal of an element i.e. the Dequeue operation takes place at the front end.
• Circular Queue:  In a circular queue, the element of the queue act as a circular ring. The working of a circular queue is similar to the linear queue except for the fact that the last element is connected to the first element. Its advantage is that the memory is utilized in a better way. This is because if there is an empty space i.e. if no element is present at a certain position in the queue, then an element can be easily added at that position.
• Priority Queue: This queue is a special type of queue. Its specialty is that it arranges the elements in a queue based on some priority. The priority can be something where the element with the highest value has the priority so it creates a queue with decreasing order of values. The priority can also be such that the element with the lowest value gets the highest priority so in turn it creates a queue with increasing order of values.
• Dequeue: Dequeue is also known as Double Ended Queue. As the name suggests double ended, it means that an element can be inserted or removed from both the ends of the queue unlike the other queues in which it can be done only from one end. Because of this property it may not obey the First In First Out property.

•

1. FIFO (First-In, First-Out) Order: Queues allow for elements to be stored and retrieved in a FIFO order, which is useful for implementing algorithms like breadth-first search.
2. Efficient Operations: Queues provide efficient enqueue and dequeue operations, as only the front and rear of the queue need to be updated.
3. Dynamic Size: Queues can grow dynamically, so they can be used in situations where the number of elements is unknown or can change over time.

1. Limited Operations: Queues only allow for enqueue, dequeue, and peek (accessing the front element) operations, so they are not suitable for implementing algorithms that require constant-time access to elements or efficient insertion and deletion operations.
2. Slow Random Access: Queues do not allow for constant-time access to elements by index, so accessing an element in the middle of the queue can be slow.
3. Cache Unfriendly: Queues can be cache-unfriendly, as elements are retrieved in a different order than they are stored, which can lead to poor cache utilization and performance.

In summary, queues are a

### Advantages of Linear Data Structures :

• Efficient data access: Elements can be easily accessed by their position in the sequence.
• Dynamic sizing: Linear data structures can dynamically adjust their size as elements are added or removed.
• Ease of implementation: Linear data structures can be easily implemented using arrays or linked lists.
• Versatility: Linear data structures can be used in various applications, such as searching, sorting, and manipulation of data.
• Simple algorithms: Many algorithms used in linear data structures are simple and straightforward.

### Disadvantages of Linear Data Structures:

1. Limited data access: Accessing elements not stored at the end or the beginning of the sequence can be time-consuming.
3. Complex algorithms: Some algorithms used in linear data structures, such as searching and sorting, can be complex and time-consuming.
4. Inefficient use of memory: Linear data structures can result in inefficient use of memory if there are gaps in the memory allocation.
5. Unsuitable for certain operations: Linear data structures may not be suitable for operations that require constant random access to elements, such as searching for an element in a large dataset.
6.

### Importants Points:The following are some of the important points covered in an introduction to linear data structures:

Definition and Types: Linear data structures are a type of data structure where elements are stored in a linear sequence. The most common types of linear data structures are arrays, linked lists, stacks, and queues.

1. Arrays: Arrays are a collection of elements stored in contiguous memory locations. It provides constant-time access to elements, but slow insertion and deletion operations.
2. Linked Lists: Linked lists are a collection of elements where each element is stored as a node and is connected to the next node through a pointer. Linked lists are dynamic in size and provide efficient insertion and deletion operations.
3. Stacks: Stacks are a type of data structure where elements are stored and retrieved in a last-in, first-out (LIFO) manner. It is useful for implementing algorithms like depth-first search.
4. Queues: Queues are a type of data structure where elements are stored and retrieved in a first-in, first-out (FIFO) manner. It is useful for implementing algorithms like breadth-first search.
5. Time Complexity: The time complexity of operations like insertion, deletion, and search in linear data structures depends on the type of data structure being used. The time complexity of each operation should be considered when choosing a data structure for a particular problem.

### Reference :

A popular reference book for linear data structures is “Introduction to Algorithms” by Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein.

My Personal Notes arrow_drop_up