0% found this document useful (0 votes)
20 views

Text

Data structures

Uploaded by

b2513621
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views

Text

Data structures

Uploaded by

b2513621
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 9

Unit-1

Here’s an in-depth explanation of the requested topics:

Abstract Data Types (ADTs)

An Abstract Data Type (ADT) is a logical description of how data can be


manipulated, focusing on the operations supported rather than implementation
details. ADTs provide a blueprint for creating data structures that abstract away
internal complexities.

Characteristics of ADTs:

1. Define operations (e.g., insert, delete,


search) without specifying how they are implemented.
2. Focus on what operations do, not how they are performed.
3. Examples of ADTs: List, Stack, Queue, Set, Map.

The List ADT

A List is a collection of elements arranged in a specific order. Elements can be


added, removed, or accessed by their position (index). Lists allow duplicates and
are often used to store ordered data.

Operations Supported by List ADT:

• Insert: Add an element at a specified position.


• Delete: Remove an element at a specified position.
• Traverse: Visit each element sequentially.
• Search: Find the position of a given element.
• Update: Modify the value of an element.

Implementation of Lists

1. Simple Array Implementation

• Structure: A contiguous block of memory where elements are stored


sequentially.
• Indexing: Allows random access (constant time for accessing elements).

Advantages:

• Fast access to elements using indices (O(1)).


• Simple to implement.

Disadvantages:

• Fixed size (requires resizing for dynamic lists).


• Inserting or deleting elements can be costly (O(n)) due to shifting
elements.

2. Simple Linked List

• Structure: A collection of nodes where each node contains:


• Data.
• A pointer to the next node.

Advantages:
• Dynamic size: No need for pre-allocating memory.
• Efficient insertion and deletion (O(1) at the head or tail).

Disadvantages:

• Sequential access only (O(n) for searching).


• Extra memory for storing pointers.

3. Doubly Linked List

• Each node contains:


• Data.
• A pointer to the next node.
• A pointer to the previous node.

Advantages:

• Easier backward traversal.


• Simplified deletion when a reference to a specific node is given.

Disadvantages:

• More memory usage due to an extra pointer.

4. Circularly Linked List

• Similar to a linked list, but the last node points back to the first
node.
• Can be implemented for both singly and doubly linked lists.

Advantages:

• Continuous traversal in a loop.


• Useful for applications like buffering and scheduling.

The Stack ADT

A Stack is a linear data structure that follows the LIFO principle (Last In, First
Out). It means the last element added to the stack is the first one to be removed.

Operations Supported by Stack ADT:

1. Push: Add an element to the top of the stack.


2. Pop: Remove the top element of the stack.
3. Peek/Top: Access the top element without removing it.
4. IsEmpty: Check if the stack is empty.
5. IsFull: Check if the stack is full (for array-based implementation).

Implementation of Stacks

1. Array Implementation

• Use a fixed-size array to store elements.


• Maintain an index (top) pointing to the last inserted element.

Advantages:

• Simple and efficient for small stacks.


Disadvantages:

• Limited size (requires resizing for dynamic stacks).

2. Linked List Implementation

• Use a linked list where:


• Each node represents a stack element.
• The top of the stack is the head of the linked list.

Advantages:

• Dynamic size.
• Efficient memory usage for large stacks.

Disadvantages:

• Overhead of managing pointers.

Applications of Stacks

1. Expression Evaluation:
• Convert infix expressions to postfix/prefix.
• Evaluate postfix expressions.
2. Function Calls:
• Used in recursion to store function calls.
3. Undo/Redo:
• Maintain previous states of data in applications.
4. Parsing:
• Check for balanced parentheses in expressions.

The Queue ADT

A Queue is a linear data structure that follows the FIFO principle (First In, First
Out). The first element added is the first one to be removed.

Operations Supported by Queue ADT:

1. Enqueue: Add an element to the rear of the queue.


2. Dequeue: Remove an element from the front of the queue.
3. Peek/Front: Access the front element without removing it.
4. IsEmpty: Check if the queue is empty.
5. IsFull: Check if the queue is full (for array-based implementation).

Implementation of Queues

1. Array Implementation

• Use a fixed-size array with two pointers:


• Front: Points to the first element.
• Rear: Points to the last element.
• Circular Queues address unused space by wrapping around when the end of
the array is reached.

Advantages:

• Simple to implement.

Disadvantages:
• Fixed size (requires resizing for dynamic queues).

2. Linked List Implementation

• Use a linked list where:


• The front of the queue is the head of the linked list.
• The rear of the queue is the tail of the linked list.

Advantages:

• Dynamic size.
• Efficient memory usage.

Disadvantages:

• Overhead of managing pointers.

Applications of Queues

1. Task Scheduling:
• Operating system processes.
• Print jobs in a printer queue.
2. Breadth-First Search (BFS):
• Used in graph traversal algorithms.
3. Simulations:
• Real-world queues (e.g., ticket counters, call centers).

Stacks and Queues Using Linked Lists

Stack Using Linked List:

• The top of the stack is implemented as the head of the linked list.
• Push:
• Create a new node and make it the head.
• Pop:
• Remove the head node.

Queue Using Linked List:

• The front of the queue is the head of the linked list.


• The rear of the queue is the tail of the linked list.
• Enqueue:
• Add a new node at the rear.
• Dequeue:
• Remove the node at the front.

1.Explain the insertion operation in linked list. How nodes are inserted after a
specified node?

Insertion in a Linked List

Insertion in a linked list involves adding a new node at a specific position. It


requires updating the pointers of the nodes to maintain the structure of the list.
Depending on the type of insertion, the operation can vary.

Types of Insertion Operations in a Linked List

1. Insertion at the Beginning: Adds a new node as the first node.


2. Insertion at the End: Adds a new node as the last node.
3. Insertion After a Specified Node: Adds a new node after a given node in
the list.
4. Insertion at a Specific Position: Adds a new node at a given position.

Insertion After a Specified Node

To insert a node after a specific node in a singly linked list, the steps are as
follows:

Algorithm

1. Create the New Node:


• Allocate memory for the new node.
• Assign the value (data) to the new node.
2. Locate the Specified Node:
• Traverse the linked list to find the node after which the new node will
be inserted.
3. Update Pointers:
• Set the next pointer of the new node to point to the next of the
specified node.
• Set the next pointer of the specified node to point to the new node.

Time Complexity

• Best Case: O(1) (if the specified node is the head).


• Worst Case: O(n) (if the specified node is near the end).

Example (Singly Linked List)

#include <stdio.h>
#include <stdlib.h>

// Define a node structure


struct Node {
int data;
struct Node* next;
};

// Function to insert a new node after a given node


void insertAfter(struct Node* prevNode, int newData) {
// Check if the specified node is NULL
if (prevNode == NULL) {
printf("The given previous node cannot be NULL.\n");
return;
}

// Allocate memory for the new node


struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));

// Assign data to the new node


newNode->data = newData;

// Update pointers
newNode->next = prevNode->next;
prevNode->next = newNode;
}

// Function to print the linked list


void printList(struct Node* head) {
while (head != NULL) {
printf("%d -> ", head->data);
head = head->next;
}
printf("NULL\n");
}

int main() {
// Create a linked list: 10 -> 20 -> 30
struct Node* head = (struct Node*)malloc(sizeof(struct Node));
struct Node* second = (struct Node*)malloc(sizeof(struct Node));
struct Node* third = (struct Node*)malloc(sizeof(struct Node));

head->data = 10;
head->next = second;

second->data = 20;
second->next = third;

third->data = 30;
third->next = NULL;

// Insert a new node with data 25 after the second node


insertAfter(second, 25);

// Print the updated list


printList(head);

return 0;
}

Output:

10 -> 20 -> 25 -> 30 -> NULL

Insertion in Doubly Linked List

For a doubly linked list, you need to update both the next and prev pointers.

Steps for Insertion After a Specified Node:

1. Create the New Node:


• Allocate memory and assign the value.
2. Update Pointers:
• Set the next pointer of the new node to the next of the specified node.
• Set the prev pointer of the new node to the specified node.
• Update the prev pointer of the next node (if it exists) to point to the
new node.
• Set the next pointer of the specified node to the new node.

Key Points

• Always check for NULL pointers to avoid runtime errors.


• For circular linked lists, ensure the loop is maintained by correctly
updating the pointers.
• Time complexity remains O(n) in the worst case for locating the
specified node.
2. Define ADT and Mention the features of ADT.

Definition of Abstract Data Type (ADT)

An Abstract Data Type (ADT) is a high-level description of a data structure that


defines a set of operations and their behavior, without specifying how the
operations are implemented. It focuses on the what rather than the how, allowing
flexibility in choosing the underlying implementation.

Features of ADT

1. Encapsulation:
• ADTs encapsulate the data and operations into a single unit.
• The implementation details (e.g., data structures and algorithms) are
hidden from the user.
2. Abstraction:
• Only the functionality (interface) of the ADT is exposed, while
internal details remain hidden.
• Users interact with the ADT through defined operations, without needing
to know how they are implemented.
3. Modularity:
• ADTs allow separation between the interface (operations) and the
implementation.
• This improves code reusability, maintainability, and readability.
4. Flexibility:
• Different implementations can be used for the same ADT, depending on
performance requirements or constraints.
5. Data Independence:
• ADTs abstract the underlying data storage, allowing changes in the
implementation without affecting the external interface.
6. Well-defined Operations:
• Each ADT provides a clear set of operations with specific behaviors,
such as:
• Insertion
• Deletion
• Traversal
• Search
• Update
7. Mathematical Model:
• ADTs are often described using a mathematical model, defining the set
of values (data) and the operations on those values.

Examples of ADTs

• List ADT:
• Operations: Insert, delete, access elements, traverse the list.
• Stack ADT:
• Operations: Push, pop, peek, check if empty/full.
• Queue ADT:
• Operations: Enqueue, dequeue, check front/rear, check if empty/full.
• Set ADT:
• Operations: Union, intersection, difference, membership testing.

By focusing on the interface rather than the implementation, ADTs make it easier to
design and develop complex systems. Let me know if you’d like examples or further
details!

3. a) Discuss the merge operation in circular linked lists.


b) When doubly linked list can be represented as circular linked list?
c) Mention the merits and demerits of linked list.

a) Discuss the Merge Operation in Circular Linked Lists

The merge operation in circular linked lists involves combining two circular linked
lists into a single circular linked list.

Steps to Merge Two Circular Linked Lists

1. Identify the Tail Nodes:


• Find the last node of the first list (tail1).
• Find the last node of the second list (tail2).
2. Update Pointers:
• Link the next pointer of tail1 to the head of the second list.
• Link the next pointer of tail2 to the head of the first list.
3. Adjust the Circular Links:
• Ensure the merged list remains circular by maintaining the pointer from
the last node to the first node.

Time Complexity:

• Finding the tail nodes: , where and are the lengths of the two lists.
• Merging the lists: .

Example:

Given two circular linked lists:


• List 1: 10 -> 20 -> 30 -> 10 (back to head)
• List 2: 40 -> 50 -> 40 (back to head)

After merging:
10 -> 20 -> 30 -> 40 -> 50 -> 10 (back to head)

b) When Can a Doubly Linked List Be Represented as a Circular Linked List?

A doubly linked list can be represented as a circular linked list when:


1. Both Ends Are Connected:
• The next pointer of the last node points to the head of the list.
• The prev pointer of the head node points to the tail of the list.
2. Use Case Justification:
• Circular doubly linked lists are used when:
• Continuous traversal in both directions is required.
• It is necessary to efficiently handle cyclic operations, such as
buffering or scheduling.

Advantages:

• Simplified traversal since the list has no clear end.


• Eliminates the need for null checks during traversal.

Example:

For a doubly linked list:


10 <-> 20 <-> 30
Represented as circular:
10 <-> 20 <-> 30 <-> 10

c) Merits and Demerits of Linked Lists


Merits of Linked Lists

1. Dynamic Size:
• Memory is allocated as needed, unlike arrays that require pre-
allocation.
2. Efficient Insertions and Deletions:
• Inserting or deleting elements is if the position is known, as there
is no need to shift elements.
3. No Memory Wastage:
• Nodes are allocated only when required, avoiding unused memory.
4. Implementation of Complex Data Structures:
• Forms the basis for stacks, queues, graphs, and dynamic hash tables.
5. Flexible Memory Allocation:
• Suitable for situations where the size of the data structure is unknown
or frequently changes.

Demerits of Linked Lists

1. Sequential Access:
• Accessing an element requires traversal from the head, making it ,
unlike arrays which provide random access.
2. Memory Overhead:
• Extra memory is needed for storing pointers, especially in doubly or
circular linked lists.
3. Complex Implementation:
• Managing pointers increases the complexity of the code and potential
for errors like memory leaks or dangling pointers.
4. Cache Unfriendliness:
• Due to non-contiguous memory allocation, linked lists are less cache-
efficient compared to arrays.
5. Difficult Debugging:
• Errors related to pointers, such as loops or null pointer
dereferencing, are harder to debug.

Summary

• The merge operation in circular linked lists involves linking the tail
of one list to the head of the other.
• Doubly linked lists can be circular when both ends are connected,
enabling continuous traversal in both directions.
• Linked lists provide dynamic memory management and efficient insertions
but lack random access and have higher memory overhead due to pointer .

You might also like