Thanks to visit codestin.com
Credit goes to www.scribd.com

0% found this document useful (0 votes)
4 views15 pages

Module 3-1

Uploaded by

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

Module 3-1

Uploaded by

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

INTRODUCTION TO DATA STRUCTURES

Table of contents
Module 3

Linked Lists: Introduction, Singly Linked List, Self-Referential Structures,

Operations on Singly Linked Lists: Insert-Delete-Display,

Circular Singly Linked List: Introduction, Operations: Insert-Delete-Display.

Implementation of Stacks and Queues using Linked List,

Concatenate two Lists,

Reverse a List without Creating a New Node,

Static Allocation Vs Linked Allocation.

Textbook 2: Ch. 9.1 to 9.2, 9.3 (Only 9.3.1 to 9.3.5, 9.3.11 to 9.3.12), 9.4 to 9.5.

1
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Linked List Data Structure


Introduction

Like arrays, Linked List is a linear data structure. Unlike arrays, linked list elements are not stored at a
contiguous location; the elements are linked using pointers.

Why Linked List?


Arrays can be used to store linear data of similar types, but arrays have the following limitations.
• The size of the arrays is fixed: So we must know the upper limit on the number of
elements in advance. Also, generally, the allocated memory is equal to the upper limit
irrespective of the usage.
• Inserting a new element in an array of elements is expensive because the room has to
be created for the new elements and to create room existing elements have to be
shifted.
Advantages over arrays
1) Dynamic size
2) Ease of insertion/deletion
Drawbacks:
1) Random access is not allowed. We have to access elements sequentially starting from
the first node. So we cannot do binary search with linked lists efficiently with its default
implementation.
2) Extra memory space for a pointer is required with each element of the list.
3) Not cache friendly. Since array elements are contiguous locations, there is locality of
reference which is not there in case of linked lists

Key Differences Between Array and Linked List


1. An array is the data structure that contains a collection of similar type data elements
whereas the Linked list is considered as a non-primitive data structure contains a
collection of unordered linked elements known as nodes.
2. In the array the elements belong to indexes, i.e., if you want to get into the fourth
element you have to write the variable name with its index or location within the
square bracket while in a linked list though, you have to start from the head and work
your way through until you get to the fourth element.
3. 3. Accessing an element in an array is fast, while Linked list takes linear time, so it is
quite a bit slower.
4. Operations like insertion and deletion in arrays consume a lot of time. On the other
hand, the performance of these operations in Linked lists are fast.
5. Arrays are of fixed size. In contrast, Linked lists are dynamic and flexible and can
expand and contract its size.
6. In an array, memory is assigned during compile time while in a Linked list it is
allocated during execution or runtime.
7. Elements are stored consecutively in arrays whereas it is stored randomly in Linked
lists.
8. The requirement of memory is less due to actual data being stored within the index in
the array. As against, there is a need for more memory in Linked Lists due to storage
of additional next and previous referencing elements.

2
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

9. In addition memory utilization is inefficient in the array. Conversely, memory


utilization is efficient in the linked list.
Singly Linked List

Insertion at the beginning in singly linked list

STEP 1: IF POINTER = NULL (GO STEP 7 MEANS EXIT OTHERWISE FOLLOW STEP2)
STEP 2: SET NEW_NODE = POINTER
STEP 3: SET POINTER = POINTER → NEXT
STEP 4: SET NEW_NODE → DATA= VALUE
STEP 5: SET NEW_NODE →NEXT =HEAD
STEP 6: SET HEAD = NEW_NODE
STEP 7: RETURN

#include <stdio.h>
#include <stdlib.h>
struct Node{
int data;
struct Node *next;
}*head;
void Insert_B(int);
void Display();

void main(void){
int count=5,val,i;
head =NULL;
for(i=0;i<count;i++){
printf("Enter a bigning value\n");
scanf("%d",&val);
Insert_B(val); }
Display();
}

void Insert_B (int x){


struct Node *temp;
temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = x;
temp->next = head;
head = temp;
}

void Display(){
struct Node *p;
p=head;
while(p!=NULL){
printf("%d",p->data);

3
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

p=p->next;
} }

Add a node at the end:

Step 1: IF Pointer = NULL (Write overflow and Go to Step 2)


[End of IF]
Step 2: SET new_node = Pointer
Step 3: SET Pointer = Pointer – > next
Step 4: SET new_node – > Ddat = val
Step 5: SET new_node – > next = NULL
Step 6: SET Pointer = head
Step 7: Repeat Step 8 while Pointer – > next != NULL
Step 8: SET Pointer = Pointer – > next
[End of Loop]
Step 9: SET Pointer – > next = new_node
Step 10: EXIT

void Insert_L(int x){


//create a new node
struct Node *temp = malloc(sizeof(struct Node));
temp->data = x;
temp->next = NULL;
//if head is NULL, it is an empty list
if(head == NULL)
head = temp;
//Otherwise, find the last node and add the new Node
else{
struct Node *p = head;
//last node's next address will be NULL.
while(p->next != NULL)
p = p->next;
//add the new Node at the end of the linked list
p->next = temp;
}
}

4
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Add a node at a given position:

STEP 1: SET NEW_NODE = PTR


STEP 2: NEW_NODE → DATA
STEP 3: SET TEMP = HEAD
STEP 4: SET I = 0
STEP 5: REPEAT STEP 5 AND 6 UNTIL I
STEP 6: TEMP = TEMP → NEXT
STEP 7: IF TEMP = NULL
WRITE DESIRED NODE NOT FOUND
GOTO STEP 11
END OF IF
END OF LOOP
STEP 8: PTR → NEXT = TEMP → NEXT
STEP 9: TEMP → NEXT=PTR
STEP 10: SET PTR=NEW_NODE
STEP 11: EXIT

void InsertAtPosition(int x,int pos){


int i;
struct Node *p,*temp;
temp = (struct Node*)malloc(sizeof(struct Node));
temp->data=x;
p=head;
if (pos==0){
temp->next=head;
head=temp;}
else{
for(i=0;i<pos-1;i++){
p=p->next;}
temp->next = p->next;
p->next = temp; }
}

5
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Deletion of a node in singly linked list

Algorithm:- DELETION AT BEGINNING(INFO,NEXT,START)


STEP 1: IF(START=NULL)
STEP 2: SET PTR = START
STEP 3: SET TEMP = INFO[PTR]
STEP 4: SET START = NEXT[PTR]
STEP 5: FREE(PTR)
STEP 6: RETURN(TEMP)
STEP 7: EXIT

void Delete(int pos){


struct Node *p,*q;
int i;
p=head;
if (pos==0){
head=p->next;
printf("\n Deleted data: %d",p->data);
free(p);}
else{
for (i=0;i<pos-1;i++){
p=p->next;
}
q=p;
q=q->next;
p->next=q->next;
printf("\n Deleted data: %d",q->data);
free(q);
}
}

Search An Element In A Linked List Using C


Steps needed
• Enter the element to search from user. Store it in some variable say ele_Search.
• Initialize two variable one to store index of found element and other to iterate through
list that is:- index = 0 and struct node *current_Node = head;
• If current_Node is not NULL and its data is not equal to ele_Search. Then, increment
index and move current_Node to its next node.
• Repeat step 3 till current_Node != NULL and element is not found, otherwise move to
5th step.

6
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

• If current_Node is not NULL, then element is found hence return index otherwise -1.

Algorithm for Search an element in a linked list:-


Step 1: ASSIGN POINTER = HEAD.
Step 2: ASSIGN S = 0.
Step 3: IF POINTER = NULL.
Step 4: REPEAT STEP 5 TO 7 UNTIL POINTER != NULL.
Step 5: IF POINTER → DATA = ITEM
Step 6: S = S + 1.
Step 7: POINTER = POINTER → NEXT
Step 8: EXIT.

int found(int key){


int index;
struct node *cur_Node;
index = 0;
cur_Node = head;
while (cur_Node != NULL && cur_Node->data != key) // Iterate till last
element until element is not found
{
index++;
cur_Node = cur_Node->next;
}
return (cur_Node != NULL) ? index : -1;
}

Circular Linked List

What is circular linked ?

In a singly circular linked list, the address of the last node’s next pointer rather than being
NULL is pointed towards the address of the head node.
Advantages
• Any node can be starting point and we can still traverse the whole list
• It can also deem to be useful for implementation as queues as rather than maintaining
the Front and Rear, we can use a circular linked list and just maintain the pointer to the
first inserted node and it can simply be the next node to the last node.
• Circular linked lists are commonly used in OS’es for the task that requires repeatedly to
be executed by OS.
Disadvantages
• Doubly Linked List is faster in getting previous node information due to previous pointer.
• Doubly Linked List can traverse in both forward and backward direction.
• Finding end of list and loop control is harder (no NULL to mark beginning and end).
• The entire list can be traversed starting from any node (traverse means visit every node
just once).

7
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Circular linked list and add an element in nth position

Step 1: ASSIGN NEW NODE AND CURRENT NODE


Step 2: IF HEAD == NULL ( GOTO STEP 9 )
Step 3: ELSE NEW NODE → DATA = DATA
Step 4: CURRENT NODE = HEAD
Step 5: FOR I=2 TO POS-1
Step 6: CURRENT NODE=CURRENT NODE → NEXT (END OF FOR LOOP)
Step 7: NEW NODE → NEXT=CURRENT NODE → NEXT
Step 8: CURRENT NODE → NEXT = NEW NODE
Step 9: EXIT

#include <stdio.h>
#include<stdlib.h>
struct Node{
int data;
struct Node *next;
}*head,*tail;
void Create(int x[],int num);
void Display ();
void Insert (int x, int pos);
void main (void){
int A[6]={1,2,3,4,5,6};
Create(A,6);
Display();
Insert(9,3);
Display();
}
void Create(int x[], int num){
int i;
struct Node *temp;
head =(struct Node*)malloc(sizeof(struct Node));
head->data=x[0];
head->next=head;
tail=head;
for (i=1;i<num;i++){
temp=(struct Node*)malloc(sizeof(struct Node));
temp->data=x[i];
temp->next=head;
tail->next=temp;
tail=tail->next; }
}

void Display(void){
struct Node *p;
p=head;
do{

8
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

printf("%d\n ",p->data);
p=p->next;
} while (head!=p);
}

void Insert(int x, int pos){


struct Node *temp;
struct Node *p;
int i;
temp =(struct Node *)malloc(sizeof(struct Node));
p=head;
for (i=0; i<pos; i++){
p=p->next;
}
temp->data=x;
temp->next=p->next;
p->next = temp;
}

Circular linked list and delete an element in nth position

Step 1: MAKE A TWO NEW NODE U AND V


Step 2: SET VALUE OF W = 0
Step 3: THEN SET DELETE = POSITION-1
Step 4: MAKE U = HEAD
Step 5: MAKE A LOOP WHILE (W != DELETE)
Step 6: SET VALUE EQUAL TO V = U
Step 7: THEN U = U → NEXT
Step 8: INCREMENT VARIABLE VALUE W++
Step 9: AT LAST V → NEXT = U →NEXT
Step 10: FREE NODE U

void Delete(int pos){


struct Node *p,*q;
int i;
if (pos==0){
p=head;
head=head->next;
free(p);}
else{
for(i=0;i<pos-1;i++){
p=p->next;}
q=p->next;
p->next=q->next;
free(q);

9
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Stack using Linked List


Instead of using array, we can also use linked list to implement stack. Linked list allocates the
memory dynamically. However, time complexity in both the scenario is same for all the
operations i.e. push, pop and peek.
In linked list implementation of stack, the nodes are maintained non-contiguously in the
memory. Each node contains a pointer to its immediate successor node in the stack. Stack is
said to be overflown if the space left in the memory heap is not enough to create a node.

Push / Pop operation at the beginning of the Linked List is much faster than end of the list
insertion and deletion as Pushing a new node at the beginning of a linked list takes place in
constant time. When inserting the new node the number of traversals that occur is equal to 1,
i.e time complexity of inserting a new node at the beginning of the linked list is O(1).

Adding a node to the stack (Push operation)


• Create a node first and allocate memory to it.
• If the list is empty then the item is to be pushed as the start node of the list. This
includes assigning value to the data part of the node and assign null to the address
part of the node.
• If there are some nodes in the list already, then we have to add the new element in the
beginning of the list (to not violate the property of the stack). For this purpose, assign
the address of the starting element to the address field of the new node and make the
new node, the starting node of the list.
Deleting a node from the stack (POP operation)
• Check for the underflow condition: The underflow condition occurs when we try to pop
from an already empty stack. The stack will be empty if the head pointer of the list
points to null.
• Adjust the head pointer accordingly: In stack, the elements are popped only from one
end, therefore, the value stored in the head pointer must be deleted and the node
must be freed. The next node of the head node now becomes the head node.

Display the nodes (Traversing)


• Copy the head pointer into a temporary pointer.
• Move the temporary pointer through all the nodes of the list and print the value field
attached to every node.

10
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Implementation of stack using Linked List

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

// Node structure for the linked list


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

// Stack structure
typedef struct {
Node *top; // Pointer to the top node of the stack
} Stack;

// Function to initialize the stack


void initStack(Stack *stack) {
stack->top = NULL;
}

// Function to push an element onto the stack


void push(Stack *stack, int value) {
Node *newNode = (Node *)malloc(sizeof(Node)); // Allocate memory for the
new node
if (!newNode) {
printf("Memory allocation failed! Unable to push %d.\n", value);
return;
}
newNode->data = value; // Set the node's data
newNode->next = stack->top; // Point to the current top
stack->top = newNode; // Update the top pointer
printf("Pushed %d onto the stack.\n", value);
}

// Function to pop an element from the stack


int pop(Stack *stack) {
if (stack->top == NULL) { // Check if the stack is empty
printf("Stack underflow! No elements to pop.\n");
return -1;
}
Node *temp = stack->top; // Store the top node
int value = temp->data; // Retrieve the data
stack->top = stack->top->next; // Move the top pointer to the next node
free(temp); // Free the memory of the old top node
return value;
}

// Function to view the top element of the stack


int peek(Stack *stack) {
if (stack->top == NULL) { // Check if the stack is empty
printf("Stack is empty.\n");
return -1;
}
return stack->top->data;
}

// Function to free all nodes in the stack


void freeStack(Stack *stack) {
while (stack->top) {

11
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Node *temp = stack->top;


stack->top = stack->top->next;
free(temp);
}
}

int main() {
Stack stack;
initStack(&stack); // Initialize the stack

// Example operations on the stack


push(&stack, 10);
push(&stack, 20);
push(&stack, 30);
printf("Top element is: %d\n", peek(&stack));
printf("Popped element: %d\n", pop(&stack));
printf("Popped element: %d\n", pop(&stack));
printf("Popped element: %d\n", pop(&stack));
printf("Popped element: %d\n", pop(&stack)); // Attempt to pop from an
empty stack

freeStack(&stack); // Clean up memory


return 0;
}

Concatenate two Lists

Reverse a List without Creating a New Node,

Static Vs Dynamic Allocation


Static Allocation
Definition: Static allocation uses fixed-size arrays to store the linked list nodes. The memory for all
nodes is allocated at compile time, and the size cannot be changed during program execution.
Characteristics
Memory Management: Memory is allocated during compile time.
Size: Fixed size; the number of elements must be declared in advance.
Flexibility: Limited flexibility due to the fixed size of the array.
Memory Utilization: May result in wastage of memory since the size is predefined, and unused
space cannot be reused.
Performance: Faster as memory is pre-allocated, but can cause inefficiency if size requirements are
underestimated or overestimated.
Implementation: Uses arrays to store the data and links (indices act as pointers).
Example:
#define MAX 100
typedef struct {
int data;
int next; // Index of the next node
} Node;

Node list[MAX];

12
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Dynamic/Linked Allocation
Definition: Linked allocation dynamically allocates memory for each node during runtime. Each
node contains data and a pointer to the next node.
Characteristics
Memory Management: Memory is allocated during runtime using functions like malloc or calloc.
Size: Dynamic size; the list can grow or shrink based on the requirements.
Flexibility: Highly flexible as memory is allocated and deallocated dynamically.
Memory Utilization: Efficient as memory is used only when required. No predefined limits.
Performance: May be slower due to dynamic memory management overhead, but provides
adaptability for varying sizes.
Implementation: Uses pointers to link the nodes in memory.
Example:
typedef struct Node {
int data;
struct Node *next;
} Node;

Node *head = NULL; // Initialize an empty list

Comparison Table
Aspect Static Allocation Linked Allocation

Memory
Compile-time (fixed) Runtime (dynamic)
Allocation
Flexible, grows/shrinks as
Size Fixed, predefined
needed
Memory
May waste memory Efficient, no memory wastage
Utilization

Flexibility Limited Highly flexible

Faster due to no allocation Slightly slower due to runtime


Speed
overhead allocation
Requires understanding of
Complexity Easier to implement
pointers
Best when size is known Best for dynamic and
Use Case
beforehand unpredictable sizes

1. When to Use Static Allocation:


If the size of the list is known and won’t change.
If you need fast and predictable memory access.
Example: Embedded systems with strict memory constraints.
2. When to Use Linked Allocation:
If the size of the list is unknown or dynamic.
If you want the list to adapt to different inputs.
Example: Applications with variable or unpredictable data sizes (e.g., dynamic data storage).
3. Trade-offs:
Static allocation is simpler and faster but lacks adaptability.
Linked allocation is versatile but comes with additional complexity and runtime costs.
Let me know if you'd like to explore more specific examples or use cases

13
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

Review Questions
 What is a linked list? What are its various types?
 Explain the representation of a linked list in memory with the help of an illustration.
 Explain the typical operations that are performed on a linked list.
 Explain the key advantages and disadvantages of linked lists.
 What is a circular linked list? How is it different from a normal linked list?
 What is a doubly linked list? Why is it used?
 Write the algorithm for searching an element in a singly linked list.
 Write the algorithm for inserting an element in a circular linked list.
 What is a stack? Explain with examples.
 Briefly describe the LIFO principle.
 What is a top pointer? Explain its significance.
 What are the different application areas of stack data structure?
 Give any four real-life examples that principally resemble the stack data structure.
 Explain the logical representation of stacks in memory with the help of an example.
 Explain push and pop operations with the help of examples.
 What will happen if we keep on pushing elements into a stack one after another?
 What will happen if we continue to pop out elements from a stack one after
another?
 How are stacks implemented?
 What is the advantage of linked implementation of stacks over array
implementation?
 What role does dynamic memory management techniques play in linked
implementation of stacks?
 Briefly explain the overflow and underflow conditions along with their remedies.
 Can an overflow situation occur even with linked implementation of stacks that
uses dynamic memory allocation techniques? Explain.

Excises programs
 Write a code snippet for declaring the node of a doubly linked list.
 Write a C function to delete a node from a singly linked list.
 Write a C function to insert a new node at the end of a circular linked list.
 Write a C function to print the elements of a linked list.
 Write a C function to print the elements of a doubly linked list in both forward
and backward directions.

 Write a function in C to perform the push operation on an array-based stack


that can store a maximum of 50 elements. Make sure that the overflow
condition is adequately handled.
 Write a function in C to perform the pop operation on a linked implementation of
stack. Make sure that the underflow condition is adequately handled.
 A stack contains N elements in it with TOP pointing at the top of the stack. It is
required to reverse the order of occurrence of the N elements and store them in
14
BY DR GANESH V BHAT DEPT ECE @ CEC
INTRODUCTION TO DATA STRUCTURES

the same stack. Write a C program to achieve the same.


 Modify the C program solution of Question 6.3 to store the N elements in sorted
fashion with the largest element stored at the TOP.
 A linked list implemented stack containing unknown number of elements is
given. You are required to count the number of elements present in the stack.
Write a function count () in C that uses the pop operation to count the number of
elements in the stack but does not actually remove the elements from the stack.
 Tower of Hanoi problem comprises of three towers with discs initially stacked
on to the first tower. The requirement is to replicate the initial stack of discs into
another tower while adhering to the following conditions:
A larger disk can not be placed on a smaller disk
Only one disc can be shifted at a time
Write a C program to find a solution to the above problem using stacks.

15
BY DR GANESH V BHAT DEPT ECE @ CEC

You might also like