Theory of Data Structure With Notes
Theory of Data Structure With Notes
Basic Terminology
Group Items: Data items which have subordinate data items are called
Group item, for example, name of a student can have first name and
the last name.
From the data structure point of view, following are some important
categories of algorithms −
Characteristics of an Algorithm
1. It is easy to understand.
Disadvantages of Algorithms:
Categories of Algorithm:
if(condition)
Statement-1;
else
Statement-2;
The above syntax specifies that if the condition is true, statement-1 will
be executed otherwise statement-2 will be executed. In case the
operation is unsuccessful. Then sequence of algorithm should be
changed/ corrected in such a way that the system will re-execute until
the operation is successful.
i.Time Complexity:
The amount of time required for an algorithm to complete its execution
is its time complexity. An algorithm is said to be efficient if it takes the
minimum (reasonable) amount of time to complete its execution.
ii. Space Complexity:
The amount of space occupied by an algorithm is known as Space
Complexity. An algorithm is said to be efficient if it occupies less space
and required the minimum amount of time to complete its execution.
4.Write an algorithm to find the Simple Interest for given Time and Rate
of Interest .
Step 1: Start
Step 2: Read P,R,S,T.
Step 3: Calculate S=(PTR)/100
Step 4: Print S
Step 5: Stop
ASYMPTOTIC NOTATIONS
Asymptotic Notations
Following are the commonly used asymptotic notations to calculate the
running time complexity of an algorithm.
Ο Notation
Ω Notation
θ Notation
Big Oh Notation, Ο
The notation Ο(n) is the formal way to express the upper bound of an
algorithm's running time. It measures the worst case time complexity or
the longest amount of time an algorithm can possibly take to complete
For example, for a function f(n)
Ο(f(n)) = { g(n) : there exists c > 0 and n0 such that f(n) ≤ c.g(n) for all n
> n0. }
Omega Notation, Ω
The notation Ω(n) is the formal way to express the lower bound of an
algorithm's running time. It measures the best case time complexity or
the best amount of time an algorithm can possibly take to complete.
UNIT-2
Stacks:
Stack is a linear data structure that follows a particular order in which the
operations are performed. The order may be LIFO(Last In First Out) or
FILO(First In Last Out). LIFO implies that the element that is inserted last,
comes out first and FILO implies that the element that is inserted first, comes
out last. Stack creation in two different ways : by an Array and by Linked List.
So, let’s first write a function to check whether a stack is empty or not.
IS_EMPTY(S)
if S.top == 0
return TRUE
return FALSE
We are going to consider only the elements from 1 to S.top as part of the
stack. It might be possible that there are other elements also in the array but
we are not going to consider them as stack.
PUSH(S, x)
S.top = S.top+1
else
S[top] = x
Similarly to remove an item from a stack (pop), we will first check if the stack
is empty or not. If it is empty, then we will throw an error of "Stack Underflow",
otherwise remove the element from the stack and return it.
POP()
if S.top<0
else
S.top = S.top-1
return S.top
Application of STACK:
There are many applications of a stack. Some of them are:
A stack will be empty if the linked list won’t have any node i.e., when
the top pointer of the linked list will be null. So, let’s start by making a function
to check whether a stack is empty or not.
IS_EMPTY(S)
if S.top == null
return TRUE
return FALSE
Now, to push any node to the stack (S) - PUSH(S, n), we will first check if the
stack is empty or not. If the stack is empty, we will make the new node head
of the linked list and also point the top pointer to it.
Digram:
PUSH(S, n)
if IS_EMPTY(S) //stack is empty
...
else
S.top.next = n
S.top = n
PUSH(S, n)
else
S.top.next = n
S.top = n
Similarly, to remove a node (pop), we will first check if the stack is empty or
not as we did in the implementation with array.
POP(S)
if IS_EMPTY(S)
Error “Stack Underflow”
In the case when the stack is not empty, we will first store the value
in top node in a temporary variable because we need to return it after deleting
the node.
POP(S)
if IS_EMPTY(S)
...
else
x = S.top.data
Now if the stack has only one node (top and head are same), we will just
make both top and head null.
POP(S)
if IS_EMPTY(S)
...
else
...
if S.top == S.head //only one node
S.top = NULL
S.head = NULL
If the stack has more than one node, we will move to the node previous to
the top node and make the next of point it to null and also point the top to it.
POP(S)
...
...
if S.top == S.head //only one node
...
else
tmp = S.head
while tmp.next != S.top //iterating to the node previous
to top
tmp = tmp.next
tmp.next = NULL //making the next of the node null
S.top = tmp //changing the top pointer
We first iterated to the node previous to the top node and then we marked
its next to null - tmp.next = NULL. After this, we pointed the top pointer to it -
S.top = tmp.
At last, we will return the data stored in the temporary variable - return x.
POP(S)
if IS_EMPTY(S)
else
x = S.top.data
S.top = NULL
S.head = NULL
else
tmp = S.head
tmp = tmp.next
return x
Stacks can be used to implement algorithms involving Infix, postfix and prefix
expressions. So let us learn about them:-
INFIX:-
An infix expression is a single letter, or an operator, proceeded by one infix
string and followed by another infix string.
A
A+B
(A + B) + (C – D)
PREFIX:-
A prefix expression is a single letter, or an operator, followed by two prefix
strings. Every prefix string longer than a single variable contains an operator,
first operand and second operand
A
+AB
++AB–CD
POSTFIX:-
A postfix expression (also called Reverse Polish Notation) is a single letter or
an operator, preceded by two postfix strings. Every postfix string longer than a
single variable contains first and second operands followed by an operator.
A
AB+
AB+CD–
Prefix and postfix notations are methods of writing mathematical expressions
without parenthesis. Time to evaluate a postfix and prefix expression is O(n),
where n is the number of elements in the array.
(A + B) * C – D –*+ABCD AB+C*D–
| bitwise OR 4 left-to-right
&& logical AND 3 left-to-right
|| logical OR 2 left-to-right
() Brackets 1
Scan +, it’s an operator. Pop two operands from stack, apply the +
operator on operands. We get 3 + 2 which results in 5. We push the
result 5 to stack. The stack now becomes ‘5’.
Scan -, it’s an operator, pop two operands from stack, apply the –
operator on operands, we get 5 – 9 which results in -4. We push the
result -4 to the stack. The stack now becomes ‘-4’.
Evaluate ‘-‘ operator and push result in stack
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.
Or
Queue is also an abstract data type or a linear data structure, just like
stack data structure, in which the first element is inserted from one end
called the REAR(also called tail), and the removal of existing element
takes place from the other end called as FRONT(also called head).
This makes queue as FIFO (First in First Out) data structure, which
means that element inserted first will be removed first.
Same is the case with Queue data structure. Data inserted first, will
leave the queue first. The process to add an element into queue is
called Enqueue and the process of removal of an element from queue
is called Dequeue.
a new element enters a queue at the last (tail of the queue) and removal of an
element occurs from the front (head of the queue).
Similar to the stack, we will implement the queue using a linked list as well as
with an array.
Front→ It is similar to the pop operation of stack i.e., it returns and deletes the
front element from the queue.
isEmpty → It is used to check whether the queue has any element or not.
isFull → It is used to check whether the queue is full or not.
Front → It is similar to the top operation of a stack i.e., it returns the front
element of the queue (but don’t delete it).
Before moving forward to code up these operations, let’s discuss the
applications of a queue.
Applications of Queue
We will maintain two pointers – tail (rear) and head (front) to represent a
queue. Head (front) will always point to the oldest element which was added
and tail (rear) will point where the new element is going to be added.
To insert any element, we add that element at tail(rear) and increase
the tail(rear) by one to point to the next element of the array.
Suppose tail (rear) is at the last element of the queue and there are empty
blocks before head (front) as shown in the picture given below.
In this case, our tail (rear) will point to the first element of the array and will
follow a circular order.
Initially, the queue will be empty i.e., both head (front) and tail (rear) will point
to the same location i.e., at index 1. We can easily check if a queue is empty
or not by checking if head(front) and tail (rear) are pointing to the same
location or not at any time.
Queue Using Linked List
As we know that a linked list is a dynamic data structure and we can change
the size of it whenever it is needed. So, we are not going to consider that
there is a maximum size of the queue and thus the queue will never overflow.
However, one can set a maximum size to restrict the linked list from growing
more than that size.
As told earlier, we are going to maintain a head and a tail pointer to the
queue. In the case of an empty queue, head will point to NULL.
s told earlier, we are going to maintain a head and a tail pointer to the queue.
In the case of an empty queue, head will point to NULL.
IS_EMPTY(Q)
if Q.head == null
return True
return False
We will point the head pointer to the first element of the linked list and
the tail pointer to the last element of it as shown in the picture given below.
The enqueue operation simply adds a new element to the last of a linked list.
However, if the queue is empty, we will simply make the new
node head and tail of the queue.
Operation on QUEUE:
This function is used to see the data at the front of the queue. The
peek() function’s algorithm is as follows −
Algorithm
begin procedure peek
return queue[front]
end procedure
return queue[front];
isfull()
Algorithm
begin procedure isfull
return true
else
return false
endif
end procedure
if(rear == MAXSIZE - 1)
return true;
else
return false;
isempty()
Algorithm
begin procedure isempty
return true
else
return false
endif
end procedure
If the value of front is less than MIN or 0, it signifies that the queue is
not yet initialized, hence empty.
C programming language implementation of the isempty()
function −
bool isempty() {
return true;
else
return false;
Enqueue Operation
Front and rear data pointers are kept in queues. As a result, compared
to stack operations, its operations are more complex to implement.
Step 3: If the queue is not full, move the rear pointer forward to the
next empty space.
Step 4: Where the rear is pointing, add the data element to the queue
location.
if queue is full
return overflow
endif
rear ← rear + 1
queue[rear] ← data
return true
end procedure
if(isfull())
return 0;
rear = rear + 1;
queue[rear] = data;
return 1;
Dequeue Operation
It takes two steps to access data from a queue: first, access the data
where the front is pointing, and second, remove the data after access.
The dequeue operation is carried out in the manner described below:
if queue is empty
return underflow
end if
data = queue[front]
front ← front + 1
return true
end procedure
if(isempty())
return 0;
front = front + 1;
return data;
Priority Queue.
Priority Queue:
A priority queue is a collection of elements such that each element has been
assigned a priority. We can insert an element in priority queue at the rare
position. We can delete an element from the priority queue based on the
elements priority and such that the order in which elements are deleted and
processed comes from the following rules:
1. An element of higher priority is processed before any element of lower
priority.
2. Two elements with same priority are processed according to the order in
which they were added to the queue. It follows FIFO or FCFS (First Comes
First serve) rules.
We always remove an element with the highest priority, which is given by the
minimal integer priority assigned.
stacks Queues
1.A stack is a linear list of elements 1.A Queue is a linerar list of
in which the element may be elements in which the elements are
inserted or deleted at one end. added at one end and deletes the
2. In stacks, elements which are elements at another end.
inserted last is the first element to 2. . In Queue the element which is
be deleted. inserted first is the element deleted
3.Stacks are called LIFO (Last In first.
First Out)list 3. Queues are called FIFO (First In
4.In stack elements are removed in First Out)list.
reverse order in which thy are 4. In Queue elements are removed
inserted. in the same order in which thy are
5.suppose the elements a,b,c,d,e inserted.
are inserted in the stack, the 5. Suppose the elements a,b,c,d,e
deletion of elements will be are inserted in the Queue, the
e,d,c,b,a. deletion of elements will be in the
6.In stack there is only one pointer same order in which thy are
to insert and delete called “Top”. inserted.
7.Initially top=-1 indicates a stack is 6. In Queue there are two pointers
empty. one for insertion called “Rear” and
8.Stack is full represented by the another for deletion called “Front”.
condition TOP=MAX-1(if array 7. Initially Rear=Front=-1 indicates
index starts from ‘0’). a Queue is empty.
9.To push an element into a stack, 8.Queue is full represented by the
Top is incremented by one condition
10.To POP an element from Rear=Max-1.
stack,top is decremented by one. 9.To insert an element into Queue,
Rear is incremented by one.
10.To delete an element from
Queue,
UNIT-3
Since DATA consists of 8 elements, there are 8!=40320 ways that the
numbers 10,20,30,40,50,60,70,80 can appear in DATA.
In selection sort, the smallest value among the unsorted elements of the array
is selected in every pass and inserted to its appropriate position into the array.
First, find the smallest element of the array and place it on the first position.
Then, find the second smallest element of the array and place it on the
second position. The process continues until we get the sorted array. The
array with n elements is sorted by using n-1 pass of selection sort algorithm.
In 1st pass, smallest element of the array is to be found along with its index
pos. then, swap A[0] and A[pos]. Thus A[0] is sorted, we now have n -1
elements which are to be sorted.
In 2nd pas, position pos of the smallest element present in the sub-array
A[n-1] is found. Then, swap, A[1] and A[pos]. Thus A[0] and A[1] are sorted,
we now left with n-2 unsorted elements.
In n-1th pass, position pos of the smaller element between A[n-1] and A[n-
2] is to be found. Then, swap, A[pos] and A[n-1].
Therefore, by following the above explained process, the elements A[0], A[1],
A[2], ... , A[n-1] are sorted.
Example: Consider the following array with 6 elements. Sort the elements of
the array by using selection sort.
A = {10, 2, 3, 90, 43, 56}.
BUBBLE SORT
Bubble Sort: This sorting technique is also known as exchange sort, which
arranges values by iterating over the list several times and in each iteration
the larger value gets bubble up to the end of the list. This algorithm uses
multiple passes and in each pass the first and second data items are
compared. if the first data item is bigger than the second, then the two items
are swapped. Next the items in second and third position are compared and if
the first one is larger than the second, then they are swapped, otherwise no
change in their order. This process continues for each successive pair of data
items until all items are sorted.
Bubble Sort Algorithm:
Step 1: Repeat Steps 2 and 3 for i=1 to 10
Step 2: Set j=1
Step 3: Repeat while j<=n
(A)
if a[i] < a[j] Then
interchange a[i] and a[j]
[End of if]
(B) Set j = j+1
[End of Inner Loop]
[End of Step 1 Outer Loop]
Step 4: Exit
INSERTION SORT
Step 4: Then the fourth element 11 is compared with its previous elements.
Since 11 is less than 33 and 20 ; and greater than 7. So it is placed in
between 7 and 20. For this the elements 20 and 33 are shifted one position
towards the right.
Step5: Finally the last element 6 is compared with all the elements preceding
it. Since it is smaller than all other elements, so they are shifted one position
towards right and 6 is inserted at the first position in the array. After this pass,
the Array is sorted.
Insertion_sort(ARR,SIZE)
Step 1: Set i=1;
Step 2: while(i<SIZE)
Set temp=ARR[i]
J=i=1;
While(Temp<=ARR[j] and j>=0)
Set ARR[j+1]=ARR[i]
Set j=j-1
End While
SET ARR(j+1)=Temp;
Print ARR after ith pass
Set i=i+1
End while
Step 3: print no.of passes i-1
Step 4: end
Disadvantages:-
It is less efficient on list containing more number of elements.
As the number of elements increases the performance of program would be
slow
QUICK SORT
The Quick Sort algorithm follows the principal of divide and Conquer. It first
picks up the partition element called ‘Pivot’, which divides the list into two sub
lists such that all the elements in the left sub list are smaller than pivot and all
the elements in the right sub list are greater than the pivot. The same process
is applied on the left and right sub lists separately. This process is repeated
recursively until each sub list containing more than one element.
The main task in Quick Sort is to find the pivot that partitions the given list into
two halves, so that the pivot is placed at its appropriate position in the array.
The choice of pivot as a significant effect on the efficiency of Quick Sort
algorithm. The simplest way is to choose the first element as the Pivot.
However the first element is not good choice, especially if the given list is
ordered or nearly ordered .For better efficiency the middle element can be
chosen as Pivot.
Initially three elements Pivot, Beg and End are taken, such that both Pivot and
Beg refers to 0th position and End refers to the (n-1)th position in the list. The
first pass terminates when Pivot, Beg and End all refers to the same array
element. This indicates that the Pivot element is placed at its final position.
The elements to the left of Pivot are smaller than this element and the
elements to it right are greater.
To understand the Quick Sort algorithm, consider an unsorted array as
follows. The steps to sort the values stored in the array in the ascending order
using Quick Sort are given below.
Step 1: Initially the index ‘0’ in the list is chosen as Pivot and the index
variable Beg and End are initiated with index ‘0’ and (n-1) respectively.
Step 2: The scanning of the element starts from the end of the list.
A[Pivot]>A[End]
i.e; 8>4 so they are swapped.
Step 3: Now the scanning of the elements starts from the beginning of the list.
Since A[Pivot]>A[Beg]. So Beg is incremented by one and the list remains
unchanged.
Step 4: The element A[Pivot] is smaller than A[Beg].So they are swapped.
Step 5: Again the list is scanned form right to left. Since A[Pivot] is smaller
than A[End], so the value of End is decreased by one and the list remains
unchanged.
Step 6: Next the element A[Pivot] is smaller than A[End], the value of End is
increased by one. and the list remains unchanged.
At this point the variable Pivot, Beg, End all refers to same element, the first
pass is terminated and the value 8 is placed at its appropriate position. The
elements to its left are smaller than 8 and the elements to its right are greater
than 8.The same process is applied on left and right sub lists.
ALGORITHM
Stop
Stop
Step 7: Exchange the Pivot element with element placed at j, which is correct
place for Pivot.
Advantages of Quick Sort:
Disadvantages:
MERGE SORT
The Merge Sort algorithm is based on the fact that it is easier and faster to
sort two smaller arrays than one large array. It follows the principle of “Divide
and Conquered”. In this sorting the list is first divided into two halves. The left
and right sub lists obtained are recursively divided into two sub lists until each
sub list contains not more than one element. The sub list containing only one
element do not require any sorting. After that merge the two sorted sub lists to
form a combined list and recursively applies the merging process till the
sorted array is achieved.
Let us apply the Merge Sort to sort the following list
Advantages:
Merge sort is stable sort
It is easy to understand
It gives better performance.
Disadvantages:
It requires extra memory space
Copy of elements to temporary array
It requires additional array
It is slow process.
LINEAR SEARCH