Module-1
Lecture-01
Introduction to Data structures
In computer terms, a data structure is a Specific way to store and organize data in a
‘computer's memory so that these data can be used efficiently later. Data may be
arranged in many different ways such as the logical or mathematical model for a
particular organization of data is termed as a data structure. The variety of a particular
data model depends on the two factors -
+ Firstly, it must be loaded enough in structure to refiect the actual relationships of
the data with the real world object.
+ Secondly, the formation should be simple enough so that anyone can efficiently
process the data each time it is necessary.
Categories of Data Structure:
The data structure can be sub divided into major types:
+ Linear Data Structure
+ Non-linear Data Structure
Linear Data Structure:
A data structure is said to be linear if its elements combine to form any specific order.
There are basically two techniques of representing such linear structure within memory.
+ First way is to provide the linear relationships among all the elements
represented by means of linear memory location. These linear structures are termed as
arrays.
+ The second technique is to provide the linear relationship among all the elements
represented by using the concept of pointers or links. These linear structures are
termed as linked lists.
The common examples of linear data structure are:
+ Arrays
+ Queues
+ Stacks
+ Linked lists
Non linear Data Structure:
This structure is mostly used for representing data that contains a hierarchical
relationship among various elements.
Examples of Non Linear Data Structures are listed below:
iz Graphs
+ family of trees and
. table of contents
Tree: In this case, data often contain a hierarchical relationship among various
elements. The data structure that reflects this relationship is termed as rooted tree
graph or a tree.Graph: In this case, data sometimes hold a relationship between the pairs of elements
which is not necessarily following the hierarchical structure. Such data structure is
termed as a Graph.
Array is a container which can hold a fix number of items and these items should be of
the same type. Most of the data structures make use of arrays to implement their
algorithms. Following are the important terms to understand the concept of Array.
+ Element - Each item stored in an array is called an element.
+ Index - Each location of an element in an array has a numerical index, which is
used to identify the element.
Array Representation:(Storage structure)
Arrays can be declared in various ways in different languages. For illustration, let's take
C array declaration.
int array [10] = { 35, 33, 42, 10, 14, 19, 27, 44, 26, 31}
Arrays can be declared in various ways in different languages. For illustration, let's take
C array declaration.
elements 35 33 | 42 | 10 | 14] 19 27 | 44| 26 | 31
index 012 345 67 8 9
Size :10
As per the above illustration, following are the important points to be considered.
. Index starts with 0.
+ Array length is 10 which means it can store 10 elements.
+ Each element can be accessed via its index. For example, we can fetch an
element at index 6 as 9.
Basic Operations
Following are the basic operations supported by an array.
+ Traverse ~ print all the array elements one by one.
+ Insertion - Adds an element at the given index.
+ Deletion - Deletes an element at the given index.
+ Search - Searches an element using the given index or by the value.
+ Update - Updates an element at the given index.
In C, when an array is initialized with size, then it assigns defaults values to its
elements in following order.
Data Type Default Value
bool falsechar 0
int 0
float 0.0
double 0.0F
void
wehar_t 0
Insertion Operation
Insert operation is to insert one or more data elements into an array. Based on the
requirement, a new element can be added at the beginning, end, or any given index of
array.
Here, we see a practical implementation of insertion operation, where we add data at
the end of the array ~
Algorithm
Let LA be a Linear Array (unordered) with N elements and K is a positive integer such
that Ke=N. Following is the algorithm where ITEM is inserted into the K" position of LA
. Start
. Set J=N
. Set N= N+1
Repeat steps 5 and 6 while J >=K
Set LA[J+1] = LAlJ]
Set J=J-1
Set LA(K] = ITEM
. Stop
Example
Following is the implementation of the above algorithm ~
PNOTEONS
#include
main() {
int LAN = (1,3,5,7,8);
int item = 10, k
inti =0,j=n;
printi("The original array elements are :\n’);
for(i = 0; icn; i++) {
printi("LA[%d] = %d \n", i, LAG);
}Lay
i=i-t:
uy
LAK] = item;
print{("The array elements after insertion :\n");
for(i = 0; i
void main() {
int LAN = (1,3,5,7,8);
printi("The original array elements are :\n
for(i = 0; icn; i+) {
while(j
void main() {
int LAN = (1,3,5,7.8);
intitem =5,n=5;
inti =0,
printf("The original array elements are \n");
for(i = 0; icn; i++) {
printf("LA[%d] = %d \n", i, LALil);
}
while(j
void main() {
int LA) = (1,3.
intk =3,n=
inti,
print{("The original array elements are :\n");
for(i = 0; icn: i+) {
printf("LA[%d] = %d \n", i, LAL):
ui
5,7,8):
. item = 10;
LA\k-1] = item;
printf("The array elements after updation :\n")
for(i = 0; i
int main()
{
// Assume 4x5 sparse matrix
int sparseMatrix(4][5] =
{
{0,0,3,0,4},
{0,0,5,7,0},
{0,0,0,0,0},
{0,2,6,0,0}
h
int size
for (int i = 0; i < 4; i++)
for (int j = 0; j <5; j++)
if (sparseMatrixilf] != 0)
size++;
int compactMatrix{3][size];
1/ Making of new matrixintk =0;
for (int i = 0; i < 4; i++)
for (int j = 0; | <5; j++)
if (sparseMatrix{i][i] != 0)
{
compactMatrix{0][k
compactMatrix{1][
compactMatrix{2]{k
k++;
= sparseMatrix{i]{j;
for (int i=0; i<3; i++)
for (int j=0; jesize; j++)
printf("%d ", compactMatrix{i][i));
printf("\n");
return 0;
00304
oos70 >
ooo000
02600Lecture-04
STACK
A stack is an Abstract Data Type (ADT), commonly used in most programming languages. It is
named stack as it behaves like a real-world stack, for example — a deck of cards or a pile of
plates, ete.
A real-world stack allows operations at one end only. For example, we can place or remove a
card or plate from the top of the stack only. Likewise, Stack ADT allows all data operations at
one end only. At any given time, we can only access the top element of a stack.
This feature makes it LIFO data structure. LIFO stands for Last-in-first-out. Here, the element
which is placed (inserted or added) last, is accessed first. In stack terminology, insertion
operation is called PUSH operation and removal operation is called POP operation
Stack Representation
The following diagram depicts a stack and its operations -
;
; i
*\, Last In - First Out
Pop
Push 1
|| ata Bement ata Element
| Data Bement Data Element
ata Bement ata Eament
Data Bement ‘baa Bement
| cas enone ta Bemect
Stack Stack
A stack can be implemented by means of Array, Structure, Pointer, and Linked List. Stack can
either be a fixed size one or it may have a sense of dynamic resizing. Here, we are going to
implement stack using arrays, which makes it a fixed size stack implementation.
Basic Operations
Stack operations may involve initializing the stack, using it and then de -initializing it. Apart from
these basic stuffs, a stack is used for the following two primary operations ~
+ push() ~ Pushing (storing) an element on the stack.+ pop() ~ Removing (accessing) an element from the stack.
When data is PUSHed onto stack
To use a stack efficiently, we need to check the status of stack as well. For the same purpose,
the following functionality is added to stacks ~
+ peek() ~ get the top data element of the stack, without removing it.
+ isFull() - check if stack is full
Empty() ~ check if stack is empty.
At all times, we maintain a pointer to the last PUSHed data on the stack. As this pointer always
represents the top of the stack, hence named top. The top pointer provides top value of the
stack without actually removing it.
First we should learn about procedures to support stack functions ~
peek()
Algorithm of peek() function -
begin procedure peek
return stack{top]
end procedure
Implementation of peek() function in C programming language ~
Example
int peek() {
Tetum stack(top];
}
isfull()
Algorithm of isfull() function ~
begin procedure isfull
if top equals to MAXSIZE
return true
else
retum false
endif
end procedure
Implementation of isfull() function in C programming language -
Example
boo! isfull() {
if(top == MAXSIZE)
return true;
else
retum false;isempty()
Algorithm of isempty() function ~
begin procedure isempty
if top less than 1
return true
else
return false
endif
end procedure
Implementation of isempty() function in C programming language is slightly different. We
initialize top at -1, as the index in array starts from 0. So we check if the top is below zero or -1
to determine if the stack is empty. Here's the code -
Example
bool isempty() {
if(top == -1)
return true;
else
return false;
}
Push Operation
The process of putting a new data element onto stack is known as a Push Operation. Push
operation involves a series of steps ~
+ Step 1 ~ Checks if the stack is full
Step 2 - If the stack is full, produces an error and exit.
Step 3 - If the stack is not full, increments top to point next empty space.
Step 4 - Adds data element to the stack location, where top is pointing.
Step 5 - Returns success.
ea
If the linked list is used to implement the stack, then in step 3, we need to allocate space
dynamically.
Algorithm for PUSH Operation
A simple algorithm for Push operation can be derived as follows ~
begin procedure push: stack, data
if stack is fullreturn null
endif
top <—top+1
stack[top] — data
end procedure
Implementation of this algorithm in C, is very easy. See the following code ~
Example
void push(int data) {
if(lisFullQ) {
top = top +1
stack(top] = data;
} else {
printf("Could not insert data, Stack is full.\n");
}
}
Pop Operation
Accessing the content while removing it from the stack, is known as a Pop Operation. In an
array implementation of pop() operation, the data element is not actually removed,
instead top is decremented to a lower position in the stack to point to the next value. But in
linked-list implementation, pop() actually removes data element and deallocates memory space.
‘Pop operation may involve the following steps ~
+ Step 1 - Checks if the stack is empty.
Step 2 - If the stack is empty, produces an error and exit.
Step 3 - If the stack is not empty, accesses the data element at which top is pointing.
Step 4 ~ Decreases the value of top by 1.
Step 5 ~ Returns success.
e
Pop Operation (
° top—+|
¢ c
Stack Stack
Algorithm for Pop OperationA simple algorithm for Pop operation can be derived as follows ~
begin procedure pop: stack
if stack is empty
return null
endif
data — stack{top]
top — top -1
return data
end procedure
Implementation of this algorithm in C, is as follows -
Example
int pop(int data) {
if(lisempty()) {
data = stack[top];
top = top - 1;
return data;
) else {
printf("Could not retrieve data, Stack is empty.\n");
}
}Lecture-05
Stack Applications
Three applications of stacks are presented here. These examples are central to many activities
that a computer must do and deserve time spent with them.
1. Expression evaluation
2. Backtracking (game playing, finding paths, exhaustive searching)
3. Memory management, run-time environment for nested language features.
Expression evaluation
In particular we will consider arithmetic expressions. Understand that there are boolean and
logical expressions that can be evaluated in the same way. Control structures can also be
treated similarly in a compiler.
This study of arithmetic expression evaluation is an example of problem solving where you solve
a simpler problem and then transform the actual problem to the simpler one.
Aside: The NP-Complete problem. There are @ set of apparently intractable problems: finding
the shortest route in a graph (Traveling Salesman Problem), bin packing, linear programming,
etc. that are similar enough that if a polynomial solution is ever found (exponential solutions
abound) for one of these problems, then the solution can be applied to all problems.
Infix, Prefix and Postfix Notation
We are accustomed to write arithmetic expressions with the operation between the two
operands: a+b or c/d. If we write a+b*c, however, we have to apply precedence rules to avoid
the ambiguous evaluation (add first or multiply first?)
There's no real reason to put the operation between the variables or values. They can just as
well precede or follow the operands. You should note the advantage of prefix and postfix: the
need for precedence rules and parentheses are eliminated.
lintix Prefix Postfix
latb +ab ab+
latb‘c +a*be abe'+
(a+b) *(e-a) *tab-cd ab+cd-*
Ibtb-4*atc
40-3°54+1
Postfix expressions are easily evaluated with the aid of a stack
Infix, Prefix and Postfix Notation KEY
\Infix Prefix Postfix
la+b +ab ab+latbtc +a’be abe'+
|(a+b)*(c-) *+ab-cd ab+cd-*
b*b-4*a'c -"bb **4ac bb*4a‘*c*-
l40-3*5+4 = 26 +-40°351 4035*-14+
Postfix Evaluation Algorithm
Assume we have a string of operands and operators, an informal, by hand process is.
‘Scan the expression left to right
SENS
replaced with one operand)
Skip values or variables (operands)
When an operator is found, apply the operation to the preceding two operands
Replace the two operands and operator with the calculated value (three symbols are
5. Continue scanning until only a value remains--the result of the expression
The time complexity is O(n) because each operand is scanned once, and each operation is
performed once.
A more formal algorithm:
create a new stack
while (input stream is not empty){
token = getNextToken();
if(token instanceof operand){
push(token);
} else if (token instance of operator)
0p2 = pop();
opt = pop();
result = calc(token, op1, op2);
push(result);
}
}
return pop();
Demonstration with 234+*5 -
Infix transformation to Postfix
This process uses a stack as well. We have to hold information that's expressed inside
parentheses while scanning to find the closing '. We also have to hold information on
operations that are of lower precedence on the stack. The algorithm is:
ene
. Create an empty stack and an empty postfix output string/stream
Scan the infix input string/stream left to right
If the current input token is an operand, simply append it to the output string (note the
examples above that the operands remain in the same order)
4. If the current input token is an operator, pop off all operators that have equal or higherprecedence and append them to the output string; push the operator onto the stack. The
order of popping is the order in the output.
if the current input token is \(', push it onto the stack
If the current input token is '’, pop off all operators and append them to the output string
until a \( is popped; discard the '(
7. If the end of the input string is found, pop all operators and append them to the output
string.
This algorithm doesn't handle errors in the input, although careful analysis of parenthesis or lack
of parenthesis could point to such error determination.
Apply the algorithm to the above expressions.
5.
6.
Backtracking
Backtracking is used in algorithms in which there are steps along some path (state) from some
starting point to some goal.
+ Find your way through a maze
+ Find a path from one point in a graph (roadmap) to another point.
+ Play a game in which there are moves to be made (checkers, chess).
In all of these cases, there are choices to be made among a number of options. We need some
way to remember these decision points in case we wantIneed to come back and try the
alternative
Consider the maze. At a point where a choice is made, we may discover that the choice leads
to a dead-end. We want to retrace back to that decision point and then try the other (next)
alternative.
Again, stacks can be used as part of the solution. Recursion is another, typically more favored,
solution, which is actually implemented by a stack.
Memory Management
Any modem computer environment uses a stack as the primary memory management model for
a running program. Whether it's native code (x86, Sun, VAX) or JVM, a stack is at the center of
the run-time environment for Java, C++, Ada, FORTRAN, etc.
The discussion of JVM in the text is consistent with NT, Solaris, VMS, Unix runtime
environments.
Each program that is running in a computer system has its own memory allocation containing
the typical layout as shown below.Unused
Memory
Call and return process
When a method/function is called
1
2,
3.
4,
5;
6.
7.
An activation record is created; its size depends on the number and size of the local
variables and parameters.
The Base Pointer value is saved in the special location reserved for it
The Program Counter value is saved in the Return Address location
. The Base Pointer is now reset to the new base (top of the call stack prior to the creation
of the AR)
The Program Counter is set to the location of the first bytecode of the method being
called
Copies the calling parameters into the Parameter region
Initializes local variables in the local variable region
While the method executes, the local variables and parameters are simply found by adding a
constant associated with each variable/parameter to the Base Pointer.
When a method returns
1. Get the program counter from the activation record and replace what's in the PC
2.
3.
Get the base pointer value from the AR and replace what's in the BP
Pop the AR entirely from the stack.Lecture-06
QUEUE
Queue is an abstract data structure, somewhat similar to Stacks. Unlike stacks, a queue is open
at both its ends. One end is always used to insert data (enqueue) and the other is used to
remove data (dequeue). Queue follows First-In-First-Out methodology, i.e., the data item stored
first will be accessed first.
tasrin
Last our
A real-world example of queue can be a single-lane one-way road, where the vehicle enters
first, exits first. More real-world examples can be seen as queues at the ticket windows and bus-
stops.
‘Queue Representation
‘As we now understand that in queue, we access both ends for different reasons. The following
diagram given below tries to explain queue representation as data structure —
€ »
In Data Data Data Dati Data Out
oa a»
Last in Last Out First in First Out
Queue
‘As in stacks, a queue can also be implemented using Arrays, Linked-lists, Pointers and
Structures. For the sake of simplicity, we shall implement queues using one-dimensional array.
Basic Operations
Queue operations may involve initializing or defining the queue, utilizing it, and then completely
erasing it from the memory. Here we shall try to understand the basic operations associated
with queues ~
+ enqueue() - add (store) an item to the queue.
+ dequeue() - remove (access) an item from the queue.
Few more functions are required to make the above-mentioned queue operation efficient. These
are -
+ peek() ~ Gets the element at the front of the queue without removing it.
+ isfull() - Checks if the queue is full.
+ isempty() ~ Checks if the queue is empty.
In queue, we always dequeue (or access) data, pointed by front pointer and while enqueing (or
storing) data in the queue we take help of rear pointer.
Let's first learn about supportive functions of a queue -
peek()This function helps to see the data at the front of the queue. The algorithm of peek() function is
as follows ~
Algorithm
begin procedure peek
return queueffront]
end procedure
Implementation of peek() function in C programming language ~
Example
int peek() {
return queueffront};
}
isfull()
As we are using single dimension array to implement queue, we just check for the rear pointer
to reach at MAXSIZE to determine that the queue is full. In case we maintain the queue in a
circular linked/-ist, the algorithm will differ. Algorithm of isfull() function ~
Algorithm
begin procedure isfull
if rear equals to MAXSIZE
return true
else
return false
endif
end procedure
Implementation of isfull() function in C programming language -
Example
boo! isfull() {
if(rear == MAXSIZE - 1)
return true;
else
return false;
}
isempty()
Algorithm of isempty() function ~
Algorithm
begin procedure isempty
if front is less than MIN OR front is greater than rear
return trueelse
return false
endif
end procedure
If the value of front is less than MIN or 0, it tells that the queue is not yet initialized, hence
empty.
Here's the C programming code -
Example
bool isempty() {
if(front < 0 || front > rear)
return true;
else
retum false;
}
Enqueue Operation
Queues maintain two data pointers, front and rear. Therefore, its operations are comparatively
difficult to implement than that of stacks.
The following steps should be taken to enqueue (insert) data into a queue -
+ Step 1 ~ Check if the queue is full.
+ Step 2 - If the queue is full, produce overflow error and exit.
+ Step 3 - If the queue is not full, increment rear pointer to point the next empty space.
+ Step 4 - Add data element to the queue location, where the rear is pointing.
+ Step 5 - return success.
eat Front
E | |
— < 2 ‘ before
Rear Front
t 1
° e . ‘ ater
Queue Enqueue
Sometimes, we also check to see if a queue is initialized or not, to handle any unforeseen
situations.
Algorithm for enqueue operation
procedure enqueue(data)
if queue is full
return overflowendif
rear <—rear+1
queuefrear] — data
return true
end procedure
Implementation of enqueue() in C programming language —
Example
int enqueue(int data)
if(istull))
return 0;
rear = rear + 1;
queuefrear] = data;
return 1;
end procedure
Dequeue Operation
Accessing data from the queue is a process of two tasks - access the data where front is
pointing and remove the data after access. The following steps are taken to
perform dequeue operation -
+ Step 1 ~ Check if the queue is empty.
+ Step 2 - If the queue is empty, produce underflow error and exit.
+ Step 3 - If the queue is not empty, access the data where front is pointing.
+ Step 4 ~ Increment front pointer to point to the next available data element.
+ Step 5 ~ Return success
Rear Front
i |
before | 8 e *
Pear Front
| |
ater ° e °
Queue
Queue Dequeue
Algorithm for dequeue operation
procedure dequeueif queue is empty
retumn underflow
end if
data = queueffront]
front —front +1
return true
end procedure
Implementation of dequeue() in C programming language —
Example
int dequeue() {
iffisempty())
return 0;
int data = queueffront);
front = front + 1;
return data;
}Lecture-07
LINKED LIST
A linked list is a sequence of data structures, which are connected together via links.
Linked List is a sequence of links which contains items. Each link contains a connection
to another link. Linked list is the second most-used data structure after array. Following
are the important terms to understand the concept of Linked List.
+ Link ~ Each link of a linked list can store a data called an element
+ Next ~ Each link of a linked list contains a link to the next link called Next.
+ LinkedList - A Linked List contains the connection link to the first link called
First.
Linked List Representation
Linked list can be visualized as a chain of nodes, where every node points to the next
node.
Head Next Next Next
Data tems Data Items Data Items
Wut
As per the above illustration, following are the important points to be considered.
+ Linked List contains a link element called first.
+ Each link carries a data field(s) and a link field called next.
+ Each link is linked with its next link using its next link.
+ Lastlink carries a link as null to mark the end of the list.
‘Types of Linked List
Following are the various types of linked list.
+ Simple Linked List ~ Item navigation is forward only.
+ Doubly Linked List - Items can be navigated forward and backward.
+ Circular Linked List - Last item contains link of the first element as next and
the first element has a link to the last element as previous.
Basic Operations
Following are the basic operations supported by a list.
+ Insertion - Adds an element at the beginning of the list.
Deletion - Deletes an element at the beginning of the list.
Display ~ Displays the complete list.
Search ~ Searches an element using the given key.
+ Delete - Deletes an element using the given key.
i ;
‘Adding a new node in linked list is a more than one step activity. We shall learn this
with diagrams here. First, create a node using the same structure and find the location
where it has to be inserted.Head Next Next
_» Data ttems —> Data tems
NULL
Imagine that we are inserting a node B(NewNode), between A (LeftNode)
and C (RightNode). Then point B.next to C -
NewNode.next -> RightNode;
It should look like this —
Hoos Next Next
Data Items ata tems
aT
Tou
Next
Data tems
Now, the next node at the left should point to the new node.
LeftNode.next -> NewNode;
oad Next . Next
+ Data tems (> Data items
. NULL
Next
Datattems “|
This will put the new node in the middle of the two. The new list should look like this
Hoag Next Next
Data items Data items » Data tems
NULL
Similar steps should be taken if the node is being inserted at the beginning of the list.
While inserting it at the end, the second last node of the list should point to the new
node and the new node will point to NULL.Deletion Operation
Deletion is also a more than one step process. We shall learn with pictorial
representation. First, locate the target node to be removed, by using searching
algorithms.
Head Next Next Next
+ Data items > Data items _+ Data items
Tu
The left (previous) node of the target node now should point to the next node of the
target node -
LeftNode.next -> TargetNode.next;
Had Next ~F Next Next
> Data items > Data items ""__SData tems
Tu
This will remove the link that was pointing to the target node. Now, using the following
code, we will remove what the target node is pointing at.
TargetNode.next -> NULL;
We need to use the deleted node. We can keep that in memory otherwise we can
simply deallocate memory and wipe off the target node completely,
Head Next Next
Data Items » Data Items
aT
NULL
F —
This operation is a thorough one. We need to make the last node to be pointed by the
head node and reverse the whole linked list.
Head Next Next
+ Dataltems ~~ ____, Data items
ULLFirst, we traverse to the end of the list. It should be pointing to NULL. Now, we shall
make it point to its previous node ~
Hoag Next Next
Dataitems ~_» Data items
-— te H
We have to make sure that the last node is not the lost node. So we'll have some temp
node, which looks like the head node pointing to the last node. Now, we shall make all
left side nodes point to their previous nodes one by one.
Head Next Next
Data items » Data tems
NULL
Except the node (first node) pointed by the head node, all nodes should point to their
predecessor, making them their new successor. The first node will point to NULL
Head Next
Data tems
p—_ ds
now
Well make the head node point to the new first node by using the temp node.
Next Next Head
Data tems Data tems L.
eS S+_
Nut
The linked list is now reversed.
Program:
#include
#include
#include
#include
struct node {
int data;
int key;
struct node “next;
b‘struct node “head = NULL;
struct node “current = NULL;
Idisplay the list
void printList() {
struct node “ptr = head;
printf("\n[ ");
/start from the beginning
while(ptr != NULL) {
rinti("(%d,%d) " ptr->key,ptr->data);
ptr = ptr->next;
}
printf("]");
}
insert link at the first location
void insertFirst(int key, int data) {
Wereate a link
struct node “link = (struct node") malloc(sizeof(struct node));
link->key = key;
link->data = data;
/Ipoint it to old first node
link->next = head;
point first to new first node
head = link;
}
Jidelete first item
struct node" deleteFirst() {
//save reference to first link
struct node “tempLink = head;
Jimark next to first link as first
head = head->next;
//return the deleted linkreturn tempLink;
}
His list empty
bool isEmpty() {
return head == NULL:
}
int length() {
int length = 0;
‘struct node ‘current;
for(current = head; current != NULL; current = current->next) {
length++;
}
return length;
}
find a link with given key
struct node" find(int key) {
Jistart from the first link
struct node” current = head;
Jil list is empty
iffhead == NULL) {
return NULL;
a
/Inavigate through list
while(current->key != key) {
if itis last node
if(current->next
return NULL;
} else {
/Igo to next link
current = current->next;
}
NULL) {Hf data found, return the current Link
return current;
}
/Idelete a link with given key
struct node* delete(int key) {
start from the first link
struct node” current = head;
struct node* previous = NULL;
if list is empty
iffhead == NULL) {
return NULL;
uF
//navigate through list
while(current->key != key) {
if tis last node
if(current->next
return NULL;
yelse {
IIstore reference to current link
previous = current;
IImove to next link
current = current->next;
}
a
/found @ match, update the link
if(current == head) {
Uichange first to point to next link
head = head->next;
} else {
I/eypass the current link
previous->next = current->next;
}
NULL) {
return current;void sort() {
inti, j, k, tempKey, tempData;
struct node “current;
struct node “next;
int size = length();
k= size;
for (i= 0 ;inext;
for(j=1idata > next->data ) {
tempData = current->data;
next->data;
tempData;
tempKey = current->key;
current->key = next->key;
next->key = tempKey;
}
current = current->next;
next = next->next;
}
}
}
void reverse(struct node" head_ref) {
struct node’ prev = NULL;
struct node* current = *head_ref;
struct node” next;
while (current != NULL) {
next = current->next;
current->next = prev;
prev = current;
current = next;
}*head_ref = prev;
}
void main() {
insertFirst(1,10);
insertFirst(2,20);
insertFirst(3,30)
insertFirst(4,1
insertFirst(5,4
insertFirst(6,51
printf(*Original List:
print list
printList();
while(lisEmpty()) {
struct node “temp = deleteFirst();
printf("\nDeleted value:");
rinti("(%d,%d) ",temp->key,temp->data);
}
printf("\nList after deleting all items: °);
printList();
insertFirst(1,10);
insertFirst(2,20);
insertFirst(3,30);
insertFirst(4,1);
insertFirst(5,40);
insertFirst(6,5i
printi("\nRestored List: *);
printList();
printf("\n");
struct node “foundLink = find(4);
if(foundLink |= NULL) {
printi("Element found: ");
printf("(%d,%d) *,foundLink->key,foundLink->data);
printf("\n");} else {
printf("Element not found.");
y
delete(4);
Printi(‘List after deleting an item: *);
rintList();
printf("\n");
foundLink = find(4);
if(foundLink != NULL) ¢
printi("Element found: ");
printi("(%d,%d) * foundLink->key, foundLink->data);
printi("\n");
} else {
printi("Element not found.");
}
printf("\
sort();
print(‘List after sorting the data: ");
printList();
reverse(&head);
print{("\nList after reversing the data: ");
printList();
}
If we compile and run the above program, it will produce the following result ~
Original List:
(6,56) (5,40) (4,4) (3,30) (2,20) (1,10) ]
Deleted value:(6,56)
Deleted value:(5,40)
Deleted value:(4,1)
Deleted value:(3,30)
Deleted value:(2,20)
Deleted value:(1,10)
List after deleting all items:
u
Restored List:
[(6,56) (5,40) (4,1) (3,30) (2,20) (1,10) ]Element found: (4,1)
List after deleting an item:
(6,56) (6,40) (3,30) (2,20) (1,10) ]
Element not found.
List after sorting the data:
[ (1,10) (2,20) (3,30) (5,40) (6,56) ]
List after reversing the data:
[(6,56) (5,40) (3,30) (2,20) (1,10) ]Lecture-08
Polynomial List
A polynomial p(x) is the expression in variable x which is in the form (ax" + bx! +... +
+ k), where a, b, c...., k fallin the category of real numbers and 'n’ is non negative
integer, which is called the degree of polynomial.
‘An important characteristics of polynomial is that each term in the polynomial
expression consists of two parts:
+ ones the coefficient
+ other is the exponent
Example:
10x? + 26x, here 10 and 26 are coefficients and 2, 1 are its exponential value.
Points to keep in Mind while working with Polynomials:
+ The sign of each coefficient and exponent is stored within the coefficient and the
exponent itself
+ Additional terms having equal exponent is possible one
+ The storage allocation for each term in the polynomial must be done in
ascending and descending order of their exponent
poly
| » Coefficient
| F 3.2
4x +6x +10x +6
! ¥
4 3 t—>| 6 2 > 10/ 1 6 Oo
- - Power
Representation of Polynomial
Polynomial can be represented in the various ways. These are
By the use of arrays
+ Bythe use of Linked List
Representation of Polynomials using Arrays
There may arise some situation where you need to evaluate many polynomial
expressions and perform basic arithmetic operations like: addition and subtraction with
those numbers. For this you will have to get a way to represent those polynomials. The
simple way is to represent a polynomial with degree 'n' and store the coefficient of n#1
terms of the polynomial in array. So every array element will consists of two values:
+ Coefficient and
* Exponent
Representation of Polynomial Using Linked Lists
A polynomial can be thought of as an ordered list of non zero terms. Each non zero
term is a two tuple which holds two pieces of information+ The exponent part
+ _ The coefficient part
Adding two polynomials using Linked List
Given two polynomial numbers represented by a linked list. Write a function that add
these lists means add the coefficients who have same variable powers
Example:
Input:
4st number = 5x"2 + 4x1 + 2x40
2nd number = 5x“ + 5x40
Output:
SxA2 + OxM + 7x00
Input:
1st number = 5x"3 + 4x42 + 2x40
2nd number = 5x1 + 5x40
Output:
XMS + 4xA2 + 5XM + 7x0.
nia EETPELLP ms
+
mu
Resultant Liststruct Node
{
int coeff;
int pow;
struct Node ‘next;
void create_node(int x, int y, struct Node **temp)
{
struct Node *r, *z;
z
temp,
if(z == NULL)
{
F =(struct Node*)malloc(sizeof(struct Node));
r->coeff = x;
f->pow = y;
“temp
r->next = (struct Node*)malloc(sizeof(struct Node));
r= rpnext;
r>next = NULL;r-enext = (struct Node*)malloc(sizeof(struct Node));
r
next;
r->next = NULL;
}
void polyadd(struct Node “poly1, struct Node *poly2, struct Node *poly)
{
while (poly1->next && poly2->next)
{
if(poly1->pow > poly2->pow)
{
poly->pow = poly1->pow;
poly->coeff = poly1->coett;
poly’ = poly1->next;
}
else if(poly1->pow < poly2->pow)
{
poly->pow = poly2->pow;
poly->coeff = poly2->coett;
poly2 = poly2-snext;
else
poly->pow = poly1->pow;
poly->coeff = poly1->coett+poly2->coeff;}
poly = polyt->next;
poly2 = poly2->next;
}
poly->next = (struct Node *)malloc(sizeof(struct Node));
poly = poly->next;
poly->next = NULL;
while(poly1->next || poly2->next)
{
if(poly->next)
{
poly->pow = poly1->pow;
poly->coeff = poly1->coetf;
poly’ = poly1->next;
}
if(poly2->next)
{
poly->pow = poly2->pow;
poly->coeff = poly2->coett;
poly2 = poly2->next;
}
poly->next = (struct Node *)malloc(sizeof(struct Node));
poly = poly->next;
poly->next = NULL;}
void show(struct Node *node)
{
while(node-snext != NULL)
{
Printi("%edx"%ed", node->coeff, node->pow);
node = node->next;
if(node->next != NULL)
printf(* +
}
int main()
{
struct Node “poly1 = NULL, *poly2 = NULL, “poly = NULL;
11 Create first list of 5x*2 + 4xM + 2x40
create_node(5,2,&poly1);
create_node(4,1,&poly1);
create_node(2,0,&poly1);
i Create second list of 5x41 + 5x*0
create_node(5,1,&poly2);
create_node(5,0,&poly2);
printf("1st Number: ");
show(poly1);
printf("\n2nd Number: *);
show(poly2);poly = (struct Node *)malloo(sizeof(struct Node));
1! Function add two polynomial numbers
polyadd(poly1, poly2, poly);
// Display resultant List
printi("\nAdded polynomial: ");
show(poly);
return 0;
}
Output:
4st Number: 5x12 + 4xM + 2x0
‘2nd Number: 5xM + 5x0
Added polynomial: 5x*2 + 9x™1 + 7x0Lecture-09
Doubly Linked List
A Doubly Linked List (DLL) contains an extra pointer, typically called previous pointer,
together with next pointer and data which are there in singly linked list.
Head
NULL
Following is representation of a DLL node in C language.
/° Node of a doubly linked list */
struct Node {
int data;
struct Node* next; // Pointer to next node in DLL
struct Node* prev; // Pointer to previous node in DLL
h
Following are advantages/disadvantages of doubly linked list over singly linked list.
Advantages over singly linked list
1) ADLL can be traversed in both forward and backward direction.
2) The delete operation in DLL is more efficient if pointer to the node to be deleted is
given.
3) We can quickly insert a new node before a given node.
In singly linked list, to delete a node, pointer to the previous node is needed. To get
this previous node, sometimes the list is traversed. In DLL, we can get the previous
node using previous pointer.
Disadvantages over singly linked list
1) Every node of DLL Require extra space for an previous pointer. It is possible to
implement DLL with single pointer though
2) All operations require an extra pointer previous to be maintained. For example, in
insertion, we need to modify previous pointers together with next pointers. For
example in following functions for insertions at different positions, we need 1 or 2 extra
steps to set previous pointer.
Insertion
Anode can be added in four ways
1) At the front of the DLL
2) After a given node.
3) At the end of the DLL
4) Before a given node.
1) Add a node at the front: (A 5 steps process)
The new node is always added before the head of the given Linked List. And newly
added node becomes the new head of DLL. For example if the given Linked List is10152025 and we add an item 5 at the front, then the Linked List becomes 510152025.
Let us call the function that adds at the front of the list is push(). The push() must
receive a pointer to the head pointer, because push must change the head pointer to
point to the new node
hai 7 tT
a
nue H|-
2) Add a node after a given node.: (A’7 steps process)
We are given pointer to a node as prev_node, and the new node is inserted after the
given node.
Head
=pTp™
3) Add a node at the end: (7 steps process)
The new node is always added after the last node of the given Linked List. For example
if the given DLL is 510152025 and we add an item 30 at the end, then the DLL becomes
51015202530. Since a Linked List is typically represented by the head of it, we have to
traverse the list till end and then change the next of last node to new node.
one Nest New, Next Next
ww FACE Te
4) Add a node before a given node:
Steps
Let the pointer to this given node be next_node and the data of the new node to be
added as new_data.1.
Check if the next_node is NULL or not. If it's NULL, return from the function
because any new node can not be added before a NULL
Allocate memory for the new node, let it be called new_node
Set new_node->data = new_data
Set the previous pointer of this new_node as the previous node of the next_node,
new_node->prev = next_node->prev
Set the previous pointer of the next_node as the new_node, next_node->prev =
new_node
Set the next pointer of this new_node as the next_node, new_node->next =
next_node;
If the previous node of the new_node is not NULL, then set the next pointer of
this previous node as new_node, new_node->prev->next = new_node
B
Alisfti[e/i-flolt ~™
prevLecture-10
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 doubly
circular linked list.
Heat
Advantages of Circular Linked Lists:
1) Any node can be a starting point. We can traverse the whole list by starting from any
point. We just need to stop when the first visited node is visited again.
2) Useful for implementation of queue. Unlike this implementation, we don't need to
maintain two pointers for front and rear if we use circular linked list. We can maintain a
pointer to the last inserted node and front can always be obtained as next of last.
3) Circular lists are useful in applications to repeatedly go around the list. For example,
when multiple applications are running on a PC, it is common for the operating system
to put the running applications on a list and then to cycle through them, giving each of
them a slice of time to execute, and then making them wait while the CPU is given to
another application. It is convenient for the operating system to use a circular list so that
when it reaches the end of the list it can cycle around to the front of the list.
4) Circular Doubly Linked Lists are used for implementation of advanced data structures
like Fibonacci Heap.
Insertion in an empty List
Initially when the list is empty, /ast pointer will be NULL.
After inserting a node T,
After insertion, T is the last node so pointer /ast points to node T. And Node T is first
and last node, so T is pointing to itself.
Function to insert node in an empty List,
struct Node *addToEmpty(struct Node “last, int data)
{
JI This function is only for empty list
if (last != NULL)
return last;1! Creating a node dynamically.
struct Node “last =
(struct Node*)malloc(sizeof(struct Node));
// Assigning the data.
last -> data = data;
JI Note : list was empty. We link single node
/Ito itself.
last -> next = last;
return last;
}
Run on IDE
Insertion at the beginning of the list
To Insert a node at the beginning of the list, follow these step:
1. Create a node, say T.
2. Make T -> next = last -> next.
3. last -> next =T.
After insertion,
Function to insert node in the beginning of the List,
struct Node *addBegin(struct Node “last, int data)
{
if (last == NULL)
return addToEmpty(last, data);
1/ Creating a node dynamically.
struct Node *temp.
= (struct Node *)malloc(sizeot(struct Node));
1/ Assigning the data.
temp -> data = data;
1/ Adjusting the links.
temp -> next = last -> next;
last -> next = temp;
return last;}
Insertion at the end of the list
To Insert a node at the end of the list, follow these step:
1. Create a node, say T
2. Make T -> next = last -> next;
3. last -> next = T.
4. last =T.
Last
Node T
x | e 7 8 le [10 e|
After insertion,
Last
e
Node T
4+ 6 | @+ + 3 1@ vole
Function to insert node in the end of the List,
struct Node *addEnd(struct Node “last, int data)
if
if (last == NULL)
return addToEmpty(last, data);
11 Creating a node dynamically.struct Node *temp =
(struct Node *)malloc(sizeof(struct Node));
1/ Assigning the data.
temp -> data = data;
1/ Adjusting the links.
temp -> next = last -> next;
last -> next = temp;
last = temp;
return last;
}
Insertion in between the nodes
To Insert a node at the end of the list, follow these step:
1. Create a node, say T.
2. Search the node after which T need to be insert, say that node be P.
3. Make T -> next = P -> next;
4.P->next=T.
Suppose 12 need to be insert after node having value 10,
Last
Node T
After searching and insertion,Last
Function to insert node in the end of the List,
struct Node *addAfter(struct Node “last, int data, int item)
{
if (last == NULL)
return NULL;
struct Node “temp, *p:
p=last -> next;
I! Searching the item.
do
{
if (p ->data
{
temp = (struct Node *)malloc(sizeof(struct Node));
1 Assigning the data.
temp -> data = data;
1/ Adjusting the links.
temp -> next = p > next;
11 Adding newly allocated node after p.
p->next = temp;
11 Checking for the last node.
if (p == last)
last = temp;
return last;
item)
> next;
} while (p != last -> next);
cout << item << " not present in the list." << endl;
return last;
}Memory Allocation-
Whenever a new node is created, memory is allocated by the system. This memory is
taken from list of those memory locations which are free i.e. not allocated. This list is
called AVAIL List. Similarly, whenever a node is deleted, the deleted space becomes
reusable and is added to the list of unused space i.e. to AVAIL List. This unused space
can be used in future for memory allocation.
Memory allocation is of two types-
1. Static Memory Allocation
2. Dynamic Memory Allocation
1. Static Memory Allocation:
When memory is allocated during compilation time, it is called ‘Static Memory
Allocation’. This memory is fixed and cannot be increased or decreased after
allocation. If more memory is allocated than req
ment, then memory is wasted. If
less memory is allocated than requirement, then program will not run successfully.
So exact memory requirements must be known in advance.
2. Dynamic Memory Allocation:
When memory is allocated during run/execution time, it is called ‘Dynamic Memory
Allocation’. This memory is not fixed and is allocated according to our requirements.
Thus in it there is no wastage of memory. So there is no need to know exact memory
requirements in advance.
Garbage Collection-
Whenever a node is deleted, some memory space becomes reusable. This memory
space should be available for future use. One way to do this is to immediately insert the
free space into availability list. But this method may be time consuming for the operating
system. So another method is used which is called ‘Garbage Collection’. This method is
described below: In this method the OS collects the deleted space time to time onto the
availability list. This process happens in two steps. In first step, the OS goes through all
the lists and tags all those cells which are currently being used. In the second step, theOS goes through all the lists again and collects untagged space and adds this collected
space to availability list. The garbage collection may occur when small amount of free
space is left in the system or no free space is left in the system or when CPU is idle and
has time to do the garbage collection.
Compaction
One preferable solution to garbage collection is compaction.
The process of moving all marked nodes to one end of memory and all available
memory to other end is called compaction. Algorithm which performs compaction is
called compacting algorithm.Lecture-12
Infix to Postfix Conversion
1 #include
2 char stack{20);
3 inttop =-1;
4 void push(char x)
5
6 stack(++top]
7
8
9 char pop()
10 {
14 ifftop == -1)
12 return -1;
13 else
14 return stack{top~};
15}
16
17 int priority(char x)
18 {
19
20
21
22 return
23 iff =:
24 return 2;
25}
26
27 main()
28 {
29 char exp[20};
30 char*e, x;
31 printf("Enter the expression :
32 scanf("%s",exp);
33 e = exp;
34 while(*e != '0')
35 0O{
36 iffisalnum(*e))
37 printf("%c",*e);
38 else if(*e == '(')
39 push("e);
40 else if(*e
“4 {43 printi(*%6c", x);
}
45 else
{
47 while (priority(stack{top}) >= priority(“e))
48 printf("%c" pop());
49 push(‘e);
}
51 ett;
}
53 while(top !=-1)
55 Printf("%c",pop());
}
OUTPUT:
Enter the expression :: atb*c
abe*+
Enter the expression :: (a+b)*c+(d-a)
ab+o'da-+Evaluate POSTFIX Expression Using Stack
1
Cr
10
1
12
13
14
15
16
17
18
19
20
21
22
23
24
#include
int stack(20};
int top =-1;
void push(int x)
{
stack[++top]
int pop)
{
return stack{top~];
int main()
{
char exp[20];
char *e;
int n1,n2,n3,num;
printf("Enter the expression ::");
scant("%s" exp);
e=exp
while(*e != 0’)
{
iffisdigit(*e))25
26
27
28
29
30
3
32
33
35
36
37
38
39
40
4
42
43
45
46
47
48
49
num = *e - 48;
push(num);
else
nt = pop();
1n2 = pop);
switch(*e)
n3=nt +n2;
n3=nt*n2;
break;50
51
52
53
54
55
56
87
58
59
60
61
62
63
64
Output:
3. =n2/n1;
break;
}
push(n3);
ett;
}
printf("\nThe result of expression %s = %d\n\n",exp,pop());
return 0;
Enter the expression :: 245+"
The result of expression 245+" = 18