Data Struct UNIT 2
Data Struct UNIT 2
Abstract Data Types (ADTs) are theoretical models that define a set of
values and operations on those values, without specifying
implementation details. Examples include:
Stack
Definition:
Basic Operations:
Implementation:
Push(element):
if top equals MAX_SIZE - 1:
Display "Stack Overflow"
else:
Increment top by 1
stack[top] = element
Pop():
if top equals -1:
Display "Stack Underflow"
else:
Element = stack[top]
Decrement top by 1
Return Element
Peek():
if top equals -1:
Display "Stack Underflow"
else:
Return stack[top]
isEmpty():
if top equals -1:
Return true
else:
Return false
isFull():
if top equals MAX_SIZE - 1:
Return true
else:
Return false
Application of Stack Data Structure:
Function calls and recursion: When a function is called, the current
state of the program is pushed onto the stack. When the function
returns, the state is popped from the stack to resume the previous
function’s execution.
Undo/Redo operations: The undo-redo feature in various
applications uses stacks to keep track of the previous actions. Each
time an action is performed, it is pushed onto the stack. To undo the
action, the top element of the stack is popped, and the reverse
operation is performed.
Expression evaluation: Stack data structure is used to evaluate
expressions in infix, postfix, and prefix notations. Operators and
operands are pushed onto the stack, and operations are performed
based on the stack’s top elements.
Browser history: Web browsers use stacks to keep track of the web
pages you visit. Each time you visit a new page, the URL is pushed
onto the stack, and when you hit the back button, the previous URL is
popped from the stack.
Backtracking Algorithms: The backtracking algorithm uses stacks to
keep track of the states of the problem-solving process. The current
state is pushed onto the stack, and when the algorithm backtracks, the
previous state is popped from the stack.
Prefix Notation
In this notation, operator is prefixed to operands, i.e. operator is written ahead of
operands. For example, +ab. This is equivalent to its infix notation a + b. Prefix
notation is also known as Polish Notation.
Postfix Notation
This notation style is known as Reversed Polish Notation. In this notation style,
the operator is postfixed to the operands i.e., the operator is written after the
operands. For example, ab+. This is equivalent to its infix notation a + b.
Example
Expression No Infix Notation Prefix Notation Postfix Notation
2 (a + b) * c *+abc ab+c*
3 a * (b + c) *a+bc abc+*
5 (a + b) * (c + d) *+ab+cd ab+cd+*
1. Read all the symbols one by one from left to right in the given Postfix
Expression
2. If the reading symbol is operand, then push it on to the Stack.
3. If the reading symbol is operator (+ , - , * , / etc.,), then perform TWO pop
operations and store the two popped oparands in two different variables
(operand1 and operand2). Then perform reading symbol operation using
operand1 and operand2 and push result back on to the Stack.
4. Finally! perform a pop operation and display the popped value as final result.
Example
Consider the following Expression...
What is Recursion?
Recursion is defined as a process which calls itself directly or indirectly
and the corresponding function is called a recursive function.
Properties of Recursion:
Types of Recursion:
int fact(int n)
{
if (n < = 1) // base case
return 1;
else
return n*fact(n-1);
}
Binary Search
Binary Search is defined as a searching algorithm used in a sorted array
by repeatedly dividing the search interval in half. The idea of binary
search is to use the information that the array is sorted and reduce the
time complexity to O(log N).
The Fibonacci programs in C that print the first n terms of the series can be coded using
two methods specified below:
Fibonacci series using recursion
Fibonacci series using loops
int fib(int n)
{
if (n <= 1)
return n;
return fib(n - 1) + fib(n - 2);
}
#include <stdio.h>
int fibonacci(int n) {
if (n <= 1)
return n;
else
return fibonacci(n-1) + fibonacci(n-2);
}
int main() {
int i;
// Print the first 10 Fibonacci numbers
for (i = 0; i < 10; i++) {
printf("%d\n", fibonacci(i));
}
return 0;
}
Fibonacci Iterative Algorithm
First we try to draft the iterative algorithm for Fibonacci series.
Procedure Fibonacci(n)
declare f0, f1, fib, loop
set f0 to 0
set f1 to 1
display f0, f1
for loop ← 1 to n
fib ← f0 + f1
f0 ← f1
f1 ← fib
display fib
end for
end procedure
Definition: A Queue is a linear data structure that follows the First In First Out
(FIFO) principle. In simpler terms, the first element inserted into the queue is the
first one to be removed. It resembles a real-world queue where people stand in
line to wait for service.
Operations on Queue:
Implementation:
1. Simple Queue: This is the basic form of a queue where elements are inserted at
the rear and removed from the front. It follows the FIFO (First In First Out)
principle.
2. Circular Queue (Ring Buffer): Circular queues are a variation of simple queues
where the rear of the queue is connected to the front, forming a circular structure.
This allows efficient space utilization and avoids wastage of memory.
3. Priority Queue: Priority queues are queues where each element has an
associated priority. Elements with higher priorities are dequeued before elements
with lower priorities, irrespective of their arrival order. Priority queues can be
implemented using various data structures like binary heaps, balanced binary
search trees, or arrays.
Enqueue Algorithm:
Algorithm enqueue(value):
if rear == MAX_SIZE - 1:
Print "Queue Overflow"
return
if front == -1 and rear == -1:
Set front = rear = 0
else:
Set rear = rear + 1
Set queue[rear] = value
Dequeue Algorithm:
Algorithm dequeue():
if front == -1:
Print "Queue Underflow"
return
if front == rear:
Set front = rear = -1
else:
Set front = front + 1
Program
#include <stdio.h>
#define MAX_SIZE 100
int queue[MAX_SIZE];
int front = -1, rear = -1;
int main() {
enqueue(10);
enqueue(20);
enqueue(30);
display();
dequeue();
display();
return 0;
}
Circular Queue
Enqueue Algorithm:
Algorithm enqueue(value):
if ((rear + 1) % MAX_SIZE == front):
Print "Queue Overflow"
return
if front == -1 and rear == -1:
Set front = rear = 0
else:
Set rear = (rear + 1) % MAX_SIZE
Set queue[rear] = value
Dequeue Algorithm:
Algorithm dequeue():
if front == -1:
Print "Queue Underflow"
return
if front == rear:
Set front = rear = -1
else:
Set front = (front + 1) % MAX_SIZE
Searching Algorithms
Searching Algorithms are designed to check for an element or retrieve an element
from any data structure where it is stored.
Sequential Search: In this, the list or array is traversed sequentially and every
element is checked. For example: Linear Search.
Linear Search is defined as a sequential search algorithm that starts at
one end and goes through each element of a list until the desired element
is found, otherwise the search continues till the end of the data set.
What is Hashing?
Hashing: Hashing is a popular technique for storing and retrieving data
as fast as possible.
Hashing is a technique or process of mapping keys, and values into the hash table by using
a hash function. It is done for faster access to elements. The efficiency of mapping depends
on the efficiency of the hash function used.
Let a hash function H(x) maps the value x at the index x%10 in an Array. For example if
the list of values is [11,12,13,14,15] it will be stored at positions {1,2,3,4,5} in the array or
Hash table respectively.
Components of Hashing
There are majorly three components of hashing:
1. Key: A Key can be anything string or integer which is fed as input in
the hash function the technique that determines an index or location
for storage of an item in a data structure.
2. Hash Function: The hash function receives the input key and
returns the index of an element in an array called a hash table. The
index is known as the hash index.
3. Hash Table: Hash table is a data structure that maps keys to values
using a special function called a hash function. Hash stores the data in
an associative manner in an array where each data value has its own
unique index.
There are many hash functions that use numeric or alphanumeric keys.
This article focuses on discussing different hash functions:
1. Division Method.
2. Mid Square Method.
3. Folding Method.
1. Division Method:
This is the most simple and easiest method to generate a hash value.
The hash function divides the value k by M and then uses the remainder
obtained.
Formula:
h(K) = k mod M
Here,
k is the key value, and
M is the size of the hash table.
It is best suited that M is a prime number as that can make sure the keys
are more uniformly distributed. The hash function is dependent upon the
remainder of a division.
Example:
k = 12345
M = 95
h(12345) = 12345 mod 95
= 90
k = 1276
M = 11
h(1276) = 1276 mod 11
=0
Pros:
1. This method is quite good for any value of M.
2. The division method is very fast since it requires only a single division
operation.
Cons:
1. This method leads to poor performance since consecutive keys map
to consecutive hash values in the hash table.
2. Sometimes extra care should be taken to choose the value of M.
2. Mid Square Method:
The mid-square method is a very good hashing method. It involves two
steps to compute the hash value-
1. Square the value of the key k i.e. k 2
2. Extract the middle r digits as the hash value.
Formula:
h(K) = h(k x k)
Here,
k is the key value.
The value of r can be decided based on the size of the table.
Example:
Suppose the hash table has 100 memory locations. So r = 2 because two
digits are required to map the key to the memory location.
k = 60
k x k = 60 x 60
= 3600
h(60) = 60
The hash value obtained is 60
Pros:
1. The performance of this method is good as most or all digits of the key
value contribute to the result. This is because all digits in the key
contribute to generating the middle digits of the squared result.
2. The result is not dominated by the distribution of the top digit or
bottom digit of the original key value.
Cons:
1. The size of the key is one of the limitations of this method, as the key
is of big size then its square will double the number of digits.
2. Another disadvantage is that there will be collisions but we can try to
reduce collisions.
3. Digit Folding Method:
This method involves two steps:
1. Divide the key-value k into a number of parts i.e. k1, k2, k3,….,kn,
where each part has the same number of digits except for the last part
that can have lesser digits than the other parts.
2. Add the individual parts. The hash value is obtained by ignoring the
last carry if any.
Formula:
k = k1, k2, k3, k4, ….., kn
s = k1+ k2 + k3 + k4 +….+ kn
h(K)= s
Here,
s is obtained by adding the parts of the key k
Example:
k = 12345
k1 = 12, k2 = 34, k3 = 5
s = k1 + k2 + k3
= 12 + 34 + 5
= 51
h(K) = 51
Note:
The number of digits in each part varies depending upon the size of the
hash table. Suppose for example the size of the hash table is 100, then
each part must have two digits except for the last part which can have a
lesser number of digits.
Collision in Hashing
In this, the hash function is used to find the index of the array. The hash
value is used to create an index for the key in the hash table. The hash
function may return the same hash value for two or more keys. When two
or more keys have the same hash value, a collision happens. To handle
this collision, we use collision resolution techniques.
Collision Resolution Techniques
Problem-
Using the hash function ‘key mod 7’, insert the following sequence of keys in the
hash table-
50, 700, 76, 85, 92, 73 and 101
Solution-
The given sequence of keys will be inserted in the hash table as-
Step-01:
Step-03:
Step-05:
Step-07:
The next key to be inserted in the hash table = 73.
Bucket of the hash table to which key 73 maps = 73 mod 7 = 3.
Since bucket-3 is already occupied, so collision occurs.
To handle the collision, linear probing technique keeps probing linearly until an
empty bucket is found.
The first empty bucket is bucket-4.
So, key 73 will be inserted in bucket-4 of the hash table as-
Step-08:
Separate Chaining-
Problem-
Using the hash function ‘key mod 7’, insert the following sequence of keys in the
hash table-
50, 700, 76, 85, 92, 73 and 101
Solution-
The given sequence of keys will be inserted in the hash table as-
Step-01:
Step-03:
Step-05:
Step-07: