CS-250 Data Structures and Algorithms 2024
CS-250 Data Structures and Algorithms 2024
CS-250
Data Structures and Algorithms
Fall Semester
PREPARED BY
Lab manual is prepared by Dr. Naima Iltaf and Lab Engr. Misbah Ghalib under the supervision of Head of Department
Dr. Naveed Iqbal Rao in year 2014.
GENERAL INSTRUCTIONS
a. Students are required to maintain the lab manual with them till the end of the semester.
b. All readings, answers to questions and illustrations must be solved on the place provided. If more space is
required then additional sheets may be attached.
c. It is the responsibility of the student to have the manual graded before deadlines as given by the instructor
d. Loss of manual will result in re submission of the complete manual.
e. Students are required to go through the experiment before coming to the lab session. Lab session details will
be given in training schedule.
f. Students must bring the manual in each lab.
g. Keep the manual neat clean and presentable.
h. Plagiarism is strictly forbidden. No credit will be given if a lab session is plagiarized and no re submission
will be entertained.
i. Marks will be deducted for late submission
VERSION HISTORY
At the end of the course the students will be able to: PLOs BT Level*
4. Constructors:
It is convenient if an object can initialize itself when it is first created, without need to make a
separate call to its member functions. C++ provides a non-static member function called as
constructor that is automatically called when object is created. After objects are created, their
members can be initialized by using constructors.
<class-name> (list-of-parameters);
# include<iostream.h>
class maths{
int a;
public:
maths(); //constructor declaration
void showdata(); //method to display the value of a
};
maths :: maths(){ //implementation of constructor and initizalize a with value 100
cout<<”\n this is a constructor”;
a=100;
}
#include <iostream>
using namespace std;
public:
student() //constructor define within the class
{
cout << "Enter the RollNo:";
cin >> rno;
cout << "Enter the Name:";
cin >> name;
cout << "Enter the Fee:";
cin >> fee;
}
return 0;
}
#include <iostream>
using namespace std;
class student { // define class
int rno;
char name[50];
double fee;
public:
student(); //constructor declaration
void display(); //display function declaration
};
void student::display()
{
cout << endl << rno << "\t" << name << "\t" << fee;
}
int main()
{
student s;
s.display();
return 0;
}
#include <iostream>
private:
double length;
};
return 0;
}
<class-name>: : ~ <class-name>()
{
It is not possible to define more than one destructor. The destructor is only one way to destroy the
object created by the constructor. Hence destructor can-not be overloaded. Destructor neither
requires any argument nor returns any value. It is automatically called when the object goes out of
scope. Destructors release memory space occupied by the objects created by the constructor. In
destructor, objects are destroyed in the reverse of object creation.
First Example
#include <iostream>
using namespace std;
class Test {
public:
Test() { cout << "\n Constructor executed"; }//construction
return 0;
}
Second Example
#include <iostream>
using namespace std;
class Test {
public:
Test() { cout << "\n Constructor executed"; }
main()
{
Test t, t1, t2, t3; //4 time execution
return 0;
}
6. Arrays:
An array is a collection of individual values, all of the same data type, stored in adjacent memory
locations. Using the array name together with an integral valued index in square brackets refers to
the individual values. Multi-dimensional arrays have additional indices for each additional
dimension. The index indicates the position of the individual component value within the collection
of values. The index is also called the subscript.
In C++, the first array element always has subscript 0. The second array element has subscript 1,
etc. The base address of an array is its beginning address in memory.
int main()
{
intArr[100],n,temp; //array hold up to 100 integers, temp is temporary variable used for swapping values
for(inti=0;i<n;i++)
{
cout<<"Enter element "<<i+1<<":";
cin>>Arr[i]; //reads user input and store in array index i
}
cout<<"\nArray after swapping"<<endl; //msg indicates that array has been modified
Exercise 1.1:
Write a program with constructor function and another for destruction function.
Exercise 1.2:
Write a program to search an element (given by user) in a two-dimensional array.
Exercise 1.3:
Introduce int variables x, y, z and int* pointer variables p, q, r. Set x, y, z to three
distinct values. Set p, q, r to the addresses of x, y, z respectively.
9. Web Resources:
http://www.tutorialspoint.com/cplusplus/cpp_constructor_destructor.htm
http://www.cplusplus.com/doc/tutorial/arrays/
http://www.tutorialspoint.com/cplusplus/cpp_pointers.htm
11. Summary:
This lab session introduces the concepts of constructors and destructors, arrays and pointers in C++.
This lab is designed to revise the concepts of arrays and pointers which will be used in
implementing the concepts of data structures.
3. Software Required:
(a) Microsoft Windows
(b) Microsoft Visual Studio 2012
4. Linked Lists: A linked list is a data structure consisting of a group of nodes which together
represent a sequence. Under the simplest form, each node is composed of a datum and a reference
(in other words, a link) to the next node in the sequence; more complex variants add additional
links. This structure allows for efficient insertion or removal of elements from any position in the
sequence.
last
first
class Node {
public:
int main()
{
Node* head = NULL;
Node* second = NULL;
Node* third = NULL;
head
|
|
+---+---+ +---+---+ +----+------+
| 1 | o----->| 2 | o-----> | 3 | NULL |
+---+---+ +---+---+ +----+------+
return 0;
}
class Node {
public:
int data;
Node* next;
};
// Function call
printList(head);
return 0;
5. }
Insertion: To insert data in a linked list, a record is created holding the new item. The nextpointer
of the new record is set to link it to the item which is to follow it in the list. The nextpointer of the
item which is to precede it must be modified to point to the new item.
if(head == NULL)
{
head = tmp;
tail = tmp;
}
else
{
tail->next = tmp;
tail = tail->next;
}
}
6. Deletion:To deleted data from list, The nextpointer of the item immediately preceding the one to
be deleted is altered, and made to point to the item following the deleted item.
// Free memory
delete temp;
}
}
// Driver code
int main()
{
deleteNode(&head, 1);
cout<<"(Linked List after Deletion of 1: )";
printList(head);
return 0;
}
Another example
#include <iostream>
struct node
{
int data;
node *next;
};
class linked_list
{
private:
node *head,*tail;
public:
linked_list()
{
head = NULL;
tail = NULL;
}
void add_node(int n)
{
node *tmp = new node;
tmp->data = n;
tmp->next = NULL;
node* gethead()
{
return head;
}
void front(int n)
{
node *tmp = new node;
tmp -> data = n;
tmp -> next = head;
head = tmp;
}
int main()
{
linked_list a;
a.add_node(1);
a.add_node(2);
a.front(3);
a.add_node(5);
a.add_node(15);
a.after(a.gethead()->next->next->next, 10);
a.del(a.gethead()->next);
linked_list::display(a.gethead());
return 0;
}
7. Exercises:
Write a program to display string using linked list. Take a string of character from user and
split the string in character, and then insert each character into linked list.
Example:
String = “RPI”
head R P I NULL
Exercise 2.2:
Consider a scenario where a firm wants to maintain the data of its employees. The data
containing employee number, name, and salary and department # are saved in a singly linked
list. Create following functions for the employee list.
InsertAtFront: Insertion of a record at the front.
InsertAtEnd: Insertion of a record at the end.
Insert: Insertion of a record at any position in the list
DeleteFirst: Deletion of first record.
DeleteLast: Deletion of last record.
Delete: Deletion of a record at any position in the list.
Search: Searching any record based on employee number and dept no.
Display: Displaying all records.
Write a program to split a single linked list in two separate lists and display the both lists.
8. Web Resources:
http://www.cprogramming.com/tutorial/lesson15.html
http://www.cs.cmu.edu/~adamchik/15-121/lectures/Linked%20Lists/linked%20lists.html
http://www.sourcetricks.com/2008/07/c-singly-linked-lists.html
9. Video Resources:
http://www.youtube.com/watch?v=pBrz9HmjFOs
http://www.youtube.com/watch?v=o5wJkJJpKtM
10. Summary:
This lab session introduces the concepts of single linked lists. It also helps students in
implementing singly linked lists using dynamic allocation.
4. Doubly Linked Lists:A doubly linked list is a data structure consisting of a group of nodes which
together represent a sequence and are connected to each other in both directions (Bi-directional). In
Doubly linked list, each node has two pointers. One pointer to its successor (NULL if there is none)
and one pointer to its predecessor (NULL if there is none) which enables bi-directional traversing.
Head
Let us call the function that adds at the front of the list push(). The push() must receive a
pointer to the head pointer because the push must change the head pointer to point to the new
node
Add a node at the front:
/* Given a reference (pointer to pointer) to the head of a
list and an int, inserts a new node on the front of the list.
*/
void push(Node** head_ref, int new_data)
{
/* 1. allocate node */
Node* new_node = new Node();
return;
}
return;
}
// Driver code
int main()
{
/* Start with the empty list */
Node* head = NULL;
return 0;
}
6. Deletion: In deletion process, element can be deleted from three different places. When the node is
deleted, the memory allocated to that node is released and the previous and next nodes of that node
are linked.
Deleting a node
// C++ program to delete a node from
// Doubly Linked List
#include <bits/stdc++.h>
using namespace std;
/* UTILITY FUNCTIONS */
/* Function to insert a node at the
beginning of the Doubly Linked List */
void push(Node** head_ref, int new_data)
{
/* allocate node */
Node* new_node = new Node();
/* Driver code*/
int main()
{
/* Start with the empty list */
Node* head = NULL;
return 0;
}
Exercise3.1:
Write a menu driven program to perform insertion, deletion and display functions for
doubly linked list.
Exercise 3.2:
Using the Exercise 5.1, write a function MoveToFront( ) with one argument of data type
integer. This function will first search the linked list and compare the Data member of the
node with the given number as argument. If the search finds the number in the list then this
function will move that node to the start of the list as shown in the example below. The order
of the remaining nodes is to remain unchanged. If no node in the list contains the integer,
MoveToFront( ) should leave the list unchanged. Assume that the list contains no duplicate
values. The structure definition of the doubly linked list is
structListNode{
ListNode *pre;
int Data;
ListNode *Next;
}*head;
The function declaration of MoveToFront function is Void MoveToFront(int);
Example:
The two diagrams below illustrate the effect of the call MoveToFront( 5).
Before the call:
9. Video Resource:
http://www.youtube.com/watch?v=5s0x8bc9DvQ
http://www.youtube.com/watch?v=JdQeNxWCguQ
Usually, programmers learn about arrays before they learn about linked lists, so it’s useful to compare the two. Although
arrays and linked lists are both data structures for storing multiple values, there are some major differences between the
two. There are pros and cons to using each.
Arra Linked
y Lists
Physically Contiguous Logically Contiguous Only
Fixed Length Changeable Length
Access Elements by Index Access Elements by Traversal
Insertion/Removal is Costly Insertion/Removal is Efficient
Memory Allocation
Linked list is one of the fundamental data structures, and can be used to implement other data structures. In a linked list
there are different numbers of nodes. Each node is consists of two fields. The first field holds the value or data and the
second field holds the reference to the next node or null if the linked list is empty.
Unlike a linked list, an array is both physically and logically contiguous. A good way to think about an array is to imagine
a single chunk of memory cells. The elements of an array are actually located next to each other as consecutive memory
addresses in RAM (Random Access Memory).
Accessing Elements
One advantage an array has over a linked list is indexing. Instead of having to traverse down every element in the array,
you can access an element directly by its index number. This costs only one instruction cycle. To get the fifth element of
an array, you only need to perform one lookup operation. The same operation in a linked list would cost you five
instruction cycles since you have to “inchworm” your way down the list.
In technical terms, retrieving an element by its index number in an array is always an O(1) operation. By contrast, the
same logically-equivalent operation in a linked list would take a variable amount of runtime depending on the number of
elements preceding the one you’re trying to access. Thus, retrieving a particular element in a linked list would be an O(n)
operation at worst and an O(1) operation at best (if the sought-after element happens to be at the front of the list).
Inserting/Removing Elements
One advantage a linked list has over an array is the ease of inserting and removing elements. In order to insert an element
into the middle of an array, you have to shift each element over to make space for insertion. This can be quite costly. In a
linked list, however all you need to do is reassign the pointer of one node to make it point to the new element and have
that new element point to the next logical node in the sequence.
The elements of a linked list are usually referred to as “nodes.” A C++ linked list is composed of node structs, each with a
data component and a pointer to other nodes in the list. The data attributes of the node in this example store a song name
and an artist name. The next pointer refers to the next song in the playlist.
Length:
Perhaps the most obvious difference between a linked list and an array is the fact that an array is a fixed length while a
linked list can expand or shrink during runtime. Memory slots can be added or removed from a linked list as needed. In an
array, however, you are stuck with an inflexible chunk of memory cells for the array’s lifetime. Even a dynamic array
(one that is assigned a length during runtime) is incapable of changing length once it’s created.
The pointer holds the address of the next element, not the address of the data in the next element, even though they are the
same in value sometimes. And It should be set to NULL while acting as the last node of the list.
1. Objectives:
(a). Understand the concept of stacks and their uses
(b). Implement stacks using both static and dynamic implementation
2. Time Required: 3 hrs
3. Software Required:
(a). Windows OS
(b). Microsoft Visual Studio
4. Stack:
Stack is a memory portion, which is used for storing the elements. The elements are stored based
on the principle of LIFO (Last In, First Out). In stack insertion and deletion of elements take place
at the same end (Top). The last element inserted will be the first to be retrieved.
• This end is called Top
• The other end is called Bottom
Data4 Top
Data3
Data2
Data1 Bottom
5. Top:The stack top operation gets the data from the top-most position and returns it to the user
without deleting it. The underflow state can also occur in stack top operation if stack is empty.
6. Push:The push operation adds a new element to the top of the stack, or initializes the stack if it is
empty. If the stack is full and does not contain enough space to accept the given item, the stack is
then considered to be in an overflow state.
7. Pop:The pop operation removes an item from the top of the stack. A pop either returns previously
inserted items, or NULL if stack is empty.
8. Overflow:When stack contains equal number of elements as per its capacity and no more
elements can be added, the status of stack is known as overflow
a) Stack Class definition: This class contains private data members i.e. a structure of node
describes the type data to be stored in element and a top pointer to node.
class ListStack{
private:
struct node
{
int num;
node *next;
}*top;
public:
ListStack()
{
top=NULL;
}
void push();
void pop();
void display();
};
b) Push( ) function:This function creates a new node and ask the user to enter the data to be
saved on the newly created node.
void ListStack::push()
{
node *newNode;
newNode= new node;
cout<<“Enter number to add on stack";
cin>>newNode->num;
newNode->next=top;
top=newNode;
}
void ListStack::pop()
{
node *temp;
temp=top;
if(top==NULL)
cout<<"Stack UnderFlow"<<endl;
else
{
cout<<"deleted Number from the stack =";
cout<<top->num;
top=top->next;
delete temp;
}
}
d) Main( ) function:
Description: To convert a number from decimal to binary, you simply divide by two and
push reminder to stack until quotient is reached to zero, then use pop operation to
display the binary representation of number. For example, to convert (35) 10 to binary,
you perform the following computation.
35/2 = 1
17/2 = 1
8/2 = 0
4/2 = 0
2/2 = 0
If you examine the remainders from the last division to the first one, writing them down
as you go, you will get the following sequence: 100011. i.e. (100011)2=(35)10
Write a program to compare opening and closing brackets in expression. This program
takes an expression in the form of string and scan it character by character. Finally the
output of the program is the valid or invalid expression.
Algorithm: To do this comparison a stack ADT can be used to keep track of the scope
delimiters encountered while scanning the expression.
13. Summary:
This lab introduces the concepts of stacks. This lab is designed to implement the concepts of
stacks using both static and dynamic implementation.
Objectives:
(c). Understand the applications of stacks
(d). Implement stacks using both static and dynamic implementation
Time Required: 3 hrs
Software Required:
(c). Windows OS
(d). Microsoft Visual Studio
4. Infix to Postfix:
An algorithm for parsing an infix notation without parentheses is given here.
Algorithm:
1. Create an empty stack called opstack for keeping operators. Create an empty string for output.
2. Each character in string is a token.
3. Scan the token list from left to right.
o If the token is an operand, append it to the end of the output string.
o If the token is a left parenthesis, push it on the opstack.
o If the token is a right parenthesis, pop the opstack until the corresponding left parenthesis is
removed. Append each operator to the end of the output string.
o If the token is an operator, *, /, +, or -, push it on the opstack. However, first remove any
operators already on the opstack that have higher or equal precedence and append them to the
output list.
4. When the input expression has been completely processed, check the opstack. Any operators still on the
stack can be removed and appended to the end of the output string.
In this Exercise, you have to take a string expression as input from user. Using this infix
expression, you have to convert it into its equivalent postfix notation.
Example: a + ( b * c )
Read an Expression Stack Output
a a
+ + a
( +( a
b +( ab
* +(* ab
c +(* abc
) + abc*
abc*+
#include<iostream>
#include<stack>
using namespace std;
bool isOperator(char c)
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='^')
{
return true;
}
else
{
return false;
}
}
int precedence(char c)
{
if(c == '^')
return 3; //highest
else if(c == '*' || c == '/')
return 2; //lower
else if(c == '+' || c == '-')
return 1; //lowest
else
return postfix;
}
int main()
{
return 0;
}
5. Parsing Infix Notation: An algorithm for parsing an infix notation without parentheses is given here.
Two stacks are required, one for numbers and the other for operators. The algorithm is:
For each item in the infix expression (no parentheses) from the right to the left
o If the item is a number then push it on the number stack.
o If the item is an operator (+,-,*, or /) and: the operator stack is empty or the operator on
the top of the stack is higher in priority (* and / are higher in priority than + or -), then
Pop an operator from the operator stack.
Pop two numbers off the number stack.
Calculate using second number-operator-first number.
Push the result on the number stack.
Push the item on the operator stack.
o Else push the item on the operator stack.
After the loop, while the operator stack is not empty
o Pop an operator from the operator stack.
Exercise 6.2:
Write a C++ code to evaluate the infix expression without parenthesis given by user.
Example: 3+4-5/2
Infix String Operand Stack Operator Stack Value
3 3
+ 3 +
4 34 +
- 34 +-
5 345 +-
/ 345 +-/
2 3452 +-/
34 +- / 2 5 -> 5/2 , Push 2
342 +-
3 + - 2 4 -> 4-2, Push 2
32 +
5 + 2 3 -> 3+2, Push 5
13. Summary:
This lab introduces different real world applications of stacks and their implementation using
static stacks in C++.
4. Queue:
A queue is a particular kind of collection in which the entities in the collection are kept in order
and the principal (or only) operations on the collection are the addition of entities to the rear
terminal position and removal of entities from the front terminal position. This makes the queue a
First-In-First-Out (FIFO) data structure. In a FIFO data structure, the first element added to the
queue will be the first one to be removed. This is equivalent to the requirement that once an
element is added, all elements that were added before have to be removed before the new element
can be invoked. A queue is an example of a linear data structure.
Dynamic: A queue can be implemented as a linked list, and expand or shrink with each enqueue
or dequeue operation.
Front Back
5. Enqueue:TheEnqueue ( ) operation adds a new item to the end of the queue, or initializes the
queue if it is empty.
6. Dequeue:TheDequeue ( ) operation removes an item from the front of the queue. A Dequeue
operation on an empty stack results in an underflow.
class DynQueue{
private:
structqueueNode
{
intnum;
queueNode *next;
};
queueNode *front;
queueNode *rear;
public:
DynQueue();
~DynQueue();
void enqueue();
void dequeue();
bool isEmpty();
void displayQueue();
void makeNull();
};
b) Constructor:
DynQueue::DynQueue()
{
front = NULL;
rear = NULL;
}
c) Enqueue() function:
void DynQueue::enqueue()
{
queueNode *ptr;
ptr = new queueNode;
cout<<"Enter Data";
cin>>ptr->num;
ptr->next= NULL;
if (front == NULL)
{
front = ptr;
rear = front;
d) Dequeue( ) Function:
void DynQueue::dequeue()
{
queueNode *temp;
temp = front;
if(isEmpty())
cout<<"Queue is Empty";
else
{
cout<<"data deleted="<<temp->num;
front = front->next;
delete temp;
}
}
8. Exercises:
Exercise 7.1:
Write a menu driven program to perform different operations with queue such aEnqueue
( ),
In this Exercise, you have to take a single string as input. Using this input string, you
have to create multiple queues in which each queue will comprise of separate word
appeared in input string. At the end, you will again concatenate all queues to a single
queue.
Example:
Exercise 7.3:
Write a program to demonstrate a printer queue in which jobs for printing are added on
the basis of priority. Each printing job should have name (e.g. A, B, C, D …..) and
priority value (e.g. 1=High, 2=Medium, 3=Low). If two jobs has same priority then
FIFO rule should be applied.
fron A B A C rear
t
1 2 2 3
11. Summary:
This lab session introduces the concepts of queues. This lab helps students in implementing
queues using dynamic allocation.
5. Recursive Call:A function call in which the function being called is the same as the one making the
call.
6. Base Case:
7. Recursive Case: A recursive function definition also contains one or more recursive cases; meaning
input(s) for which the program recurs (calls itself).
The job of the recursive cases can be seen as breaking down complex inputs into simpler ones. In a
properly-designed recursive function, with each recursive call, the input problem must be simplified
in such a way that eventually the base case must be reached.
For example, the factorial function can be defined recursively by the equations 0! = 1 and, for all n
> 0, n! = n (n − 1)! None of equation by itself constitutes a complete definition, the first is the base
case, and the second is the recursive case.
9. Algorithm: In this problem, there are pegs say A, B and C. There are n discs on peg A of
different diameters and are placed one above the other such that always a smaller disc is placed
above the larger disc. The two pegs B and C are empty. All the discs from peg A are to be
transferred to peg C using peg B as temporary storage. The subsequent guidelines must be
adhered while transferring the discs:
If there is only one disc, move that disc from A to C. If there are two discs, move the first disc
from A to B, move the second from A to C, then move the disc from B to C. In general, to
move n discs from A to C, the recursive technique consists of three steps:
11. Exercises:
Exercise 8.2:
Create a recursive function for Fibonacci series and a program for calculating it. In
mathematics, the Fibonacci numbers are the numbers in the following integer sequence:
0, 1, 1, 2, 3, 5, 8, 13, 21
By definition, the first two Fibonacci numbers are 0 and 1, and each subsequent number is the
sum of the previous two. In mathematical terms, the sequence Fn of Fibonacci numbers is
defined by the recurrence relation F(n) = F(n-1) + F(n-2) with seed values F(0) = 0 and F(1) =
1
Exercise 8.3:
Write a recursive function to display the data members of linked List in reverse order.
Exercise 8.4:
Write a program to reverse a number.
Exercise 8.5:
Write a recursive function to implement the algorithm of tower of Hanoi.
9. Web References:
http://www.cplusplus.com/articles/D2N36Up4/
http://www.danzig.us/cpp/recursion.html
64 Data Structures and Algorithms
http://www.learncpp.com/cpp-tutorial/710-recursion/
http://en.wikipedia.org/wiki/Tower_of_Hanoi
http://www.dsalgo.com/2013/02/towers-of-hanoi.html
11. Summary:
This lab introduces students with the concepts of recursion. It allows them to understand the
implementation of recursion with practical resolution of a well-known problem using concepts of
Data Structure and Algorithms.
EXPERIMENT 9 – SORTING-I
1. Objectives:
(a). Learning different sorting algorithms
(b). Implementation of selection, insertion, bubble and merge sort.
2. Time Required: 3 hrs
3. Software Required:
(a). C++
(b). Windows
(c). Microsoft Visual Studio 2012
4. Sorting: Sorting is the process of arranging values in any particular order. The order can be
ascending or descending.
5. Selection sort: is a sorting algorithm which works as follows:
Find the minimum value in the list
Swap it with the value in the first position
Repeat the steps above for remainder of the list (starting at the second position)
Pseudo code:
6. Insertion Sort:This algorithm takes one value at a time and builds up another sorted list of values.
It helps if you can imagine what you do when you play a game of cards: you pick a card and insert
it to an already sorted list of cards.
Pseudo code:
insertionSort(array A)
{This procedure sorts in ascending order.}
begin
for i := 1 to length(A)-1 do
begin
value := A[i];
j := i - 1;
done := false;
repeat
{ To sort in descending order simply reverse
the operator i.e. A[j] < value }
if A[j] > value then
begin
A[j + 1] := A[j];
j := j - 1;
if j < 0 then
done := true;
66 Data Structures and Algorithms
end
else
done := true;
until done;
A[j + 1] := value;
end;
end;
###############################
Step 1: Repeat Steps 2 to 5 for K = 1 to N-1
Step 2: set temp = A[K]
Step 3: set J = K – 1
Step 4: Repeat while temp <=A[J]
set A[J + 1] = A[J]
set J = J – 1
[end of inner loop]
Step 5: set A[J + 1] = temp
[end of loop]
Step 6: exit
Exercise 9.1:
Exercise 9.2:
Objectives:
(a). Learning different sorting algorithms
(b). Implementation of selection, insertion, bubble and merge sort.
Time Required: 3 hrs
Software Required:
(a). C++
(b). Windows
(c). Microsoft Visual Studio 2012
Bubble Sort: This algorithm looks at pairs of entries in the array and swaps their order if needed.
After the first step of the algorithm the maximal value will "bubble" up the list and will occupy
the last entry. After the second iteration, the second largest value will "bubble" up the list and will
occupy the next to last entry, and so on.
Pseudo code:
l1 = mergesort( l1 )
l2 = mergesort( l2 )
9. Exercises:
Exercise 10.2 :
12. Summary:
This lab introduces students with the concepts of sorting. It also helps them in implementing
different sorting algorithms such as bubble, merge, insertion and selection sort.
Pseudocode:
LINEAR(DATA,N, ITEM,LOC)
Set DATA[N+1] = ITEM
Set LOC = 1
Repeat while DATA[LOC] !=ITEM
Set LOC = LOC +1
If LOC = N+1, then Set LOC =0
Exit.
Pseudo code:
BINARY(DATA,LB,UB,ITEM,LOC)
Exercise 11.1:
Exercise 11.2:
Write a program to search an element linearly from the entered numbers. Also, indicate its
position in case the element is found or unavailability.
Exercise 11.3:
Write a program to demonstrate binary search. Use character array and store 10 names. This
program prompts the user to enter ten names. They are stored in ascending order the name[15]
[10] the fn[15] is used to store the name which we want to search.
9. Video Links:
www.youtube.com/watch?v=vohuRrwbTT4
http://tune.pk/video/2451896/binary-search-tree-implementation-in-cc
10. Summary:
This lab introduces students with the search algorithms. It helps students in implementing binary
search and linear search algorithms.
Minimum: The minimum element of a binary search tree is the last node of the left roof
Maximum: The maximum element is the last node of the right roof.
Basic Operations:
Search
Insert
Delete
Traverse
Search:
Search(key)
Begin
end
Delete:
Deleting a node from Binary search tree includes following three cases
Deleting a node from Binary search tree includes following three cases...
Case 1: Deleting a Leaf node (A node with no children)
Case 2: Deleting a node with one child
Case 3: Deleting a node with two children
Case 1: Deleting a leaf node
Step 1 - Find the node to be deleted using search operation
Step 2 - Delete the node using free function (If it is a leaf) and terminate the function.
Preorder traversal: In this traversal, we first visit the node, then traverse the right subtree
completely and then the left subtree.
Visit the root.
Traverse the left subtree, i.e., call Preorder(left->subtree)
Traverse the right subtree, i.e., call Preorder(right->subtree)
Postorder traversal: In this traversal, we first traverse the left subtree then the right
subtree and in the end visit the node.
Traverse the left subtree, i.e., call Postorder(left->subtree)
Traverse the right subtree, i.e., call Postorder(right->subtree)
Visit the root
Exercise 12.1:
Write a menu driven program for inserting and deleting an element of binary search tree.
Exercise 12.2:
Write a menu-driven program to traverse the binary search tree by using the following:
Preorder traversals
Inorder traversals
Postorder traversals
8. Web References:
http://www.personal.kent.edu/~rmuhamma/Algorithms/MyAlgorithms/binarySearchTree.htm
https://www.cs.auckland.ac.nz/~jmor159/PLDS210/niemann/s_bin.htm
http://www.sanfoundry.com/cpp-program-implement-binary-tree-2/
9. Video References:
www.youtube.com/watch?v=COZK7NATh4k
www.youtube.com/watch?v=5vwVuLMzqxQ
10. Summary:
This lab introduces students with the concepts of Binary search tree, its practical usages and its
implementation.
5. Graph Traversing:Traversing a graph consists of visiting each vertex only one time. We can
traverse the graph by two ways:
Depth first search
Breadth first search
6. Breadth First Search: Breadth-first search (BFS) is a graph search algorithm that begins at the root
node and explores all the neighbouring nodes. Then for each of those nearest nodes, it explores their
unexplored neighbour nodes, and so on, until it finds the goal.
The breadth-first search (BFS) algorithm is used to search a tree or graph data structure for a
node that meets a set of criteria. It starts at the tree’s root or graph and searches/visits all
nodes at the current depth level before moving on to the nodes at the next depth level.
Breadth-first search can be used to solve many problems in graph theory.
Pseudo code:
----------------------------------------------------------------------------------------------------------------
procedure BFS(Graph,v):
create a queue Q
enqueue v onto Q
mark v
while Q is not empty:
t ← Q.dequeue()
for all edges e in G.incidentEdges(t) do
o ← G.opposite(t,e)
83 Data Structures and Algorithms
if o is not marked:
mark o
enqueue o onto Q
#include <iostream>
#include
using namespace std;
struct Node {
int data;
struct Node *left, *right;
};
Node* newNode(int data) {
Node *temp = new Node;
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
int main() {
Node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
cout << "Level Order traversal of binary tree is
";
queue<Node *> q;
q.push(root);
while (q.empty() == false) {
Node *node = q.front();
cout << node->data << " ";
q.pop();
if (node->left != NULL)
q.push(node->left);
if (node->right != NULL)
q.push(node->right);
}
return 0;
}
7. Depth First Search: Depth-first search (DFS) is an algorithm for traversing or searching a tree,
tree structure, or graph. One starts at the root (selecting some node as the root in the graph case) and
explores as far as possible along each branch before backtracking.
#include <iostream>
using namespace std;
8. Exercises:
Exercise 13.1:
Create the following class Graph. Implement all function listed in class and test using menu
driven program.
class Graph
{
private:
structGNode
{
int data;
GNode *ptr;
bool visited;
};
GNode *GList;
public:
graph();
void Create();
voidInsertVertex(int);
voidInsertEdge();
voidDisplayVertices();
voidDeleteVertex();
voidDeleteEdges();
boolSearchVertex();
boolSearchEdge();
voidBFSTraversal();
voidDFSTraversal();
};
Write a function called DelAllMinEdges( ). This function will first search all the edges in the
graph and will delete all those edges having minimum weight. Consider that graph is
implemented using Adjacency List. Consider the following structure for both Vertices and
Edges
StructGNode
{
int weight;
GNode *ptr;
}*GList;
Note: In the following example DelAllMinEdges( ) will delete the edge between vertex 4 to 3
and 1to 4 because of minimum weight.
9. Web References:
http://www3.cs.stonybrook.edu/~algorith/files/graph-data-structures.shtml
http://interactivepython.org/runestone/static/pythonds/Graphs/graphintro.html
https://www.cs.auckland.ac.nz/~jmor159/PLDS210/mst.html
11. Summary:
This lab introduces students with the concepts of graphs and their implementation.
Components of Hashing
There are majorly three components of hashing:
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.
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.
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.
For example: Consider an array as a Map where the key is the index and the value is the value at
that index. So for an array A if we have index i which will be treated as the key then we can find
the value by simply looking at the value at A[i].
Types of Hash functions:
There are many hash functions that use numeric or alphanumeric keys.
Division Method.
Mid Square Method.
Folding Method.
Multiplication Method.
Efficiently computable.
Should uniformly distribute the keys (Each table position is equally likely for each.
Should minimize collisions.
Should have a low load factor(number of items in the table divided by the size of the
table)
Hash Table: A hash table is simply an array that is addressed via a hash function. Here Hash
Table is an array with 8 elements. Each element is a pointer to a linked list of numeric data. The
hash function for this example simply divides the data key by 8, and uses the remainder as an
index into the table. This yields a number from 0 to 7. Since the range of indices for Hash Table
is 0 to 7, we are guaranteed that the index is valid.
For example: {“ab”, “ba”} both have the same hash value, and string {“cd”,”be”} also generate
the same hash value, etc. This is known as collision and it creates problem in searching, insertion,
deletion, and updating of value.
What is collision?
The hashing process generates a small number for a big key, so there is a possibility that two keys
could produce the same value. The situation where the newly inserted key maps to an already
occupied, and it must be handled using some collision handling technology.
How to handle Collisions?
There are mainly two methods to handle collision:
Separate Chaining:
The idea is to make each cell of the hash table point to a linked list of records that have the same
hash function value. Chaining is simple but requires additional memory outside the table.
Example: We have given a hash function and we have to insert some elements in the hash table
using a separate chaining method for collision resolution technique.
Hash function = key % 5,
Elements = 12, 15, 22, 25 and 37.
Open Addressing:
In open addressing, all elements are stored in the hash table itself. Each table entry contains
either a record or NIL. When searching for an element, we examine the table slots one by one
until the desired element is found or it is clear that the element is not in the table.
a) Linear Probing
In linear probing, the hash table is searched sequentially that starts from the original location
of the hash. If in case the location that we get is already occupied, then we check for the next
location.
Algorithm:
Calculate the hash key. i.e. key = data % size
Check, if hashTable[key] is empty
store the value directly by hashTable[key] = data
If the hash index already has some value then
check for next index using key = (key+1) % size
Check, if the next index is available hashTable[key] then store the value. Otherwise try for
next index.
Do the above process till we find the space.
This method is also known as the mid-square method because in this method we look for i2‘th
probe (slot) in i’th iteration and the value of i = 0, 1, . . . n – 1. We always start from the
original hash location. If only the location is occupied then we check the other slots.
Let hash(x) be the slot index computed using the hash function and n be the size of the hash
table.
c) Double Hashing
Double hashing is a collision resolving technique in Open Addressed Hash tables. Double
hashing make use of two hash function,
The first hash function is h1(k) which takes the key and gives out a location on the hash table.
But if the new location is not occupied or empty then we can easily place our key.
But in case the location is occupied (collision) we will use secondary hash-function h2(k) in
combination with the first hash-function h1(k) to find the new location on the hash table.
This combination of hash functions is of the form
class Hash
{
int BUCKET; // No. of buckets
void displayHash();
};
Hash::Hash(int b)
{
this->BUCKET = b;
table = new list<int>[BUCKET];
}
// Driver program
int main()
{
// array that contains keys to be mapped
int a[] = {15, 11, 27, 8, 12};
int n = sizeof(a)/sizeof(a[0]);
return 0;
}
7. Exercises:
Exercise 14.1:
Write a program to prepare the hashing table as shown above. Take the elements through the
keyboard and map them in hash table.
Exercise 14.2:
Write a function deleteNode deletes and frees a node from the table.
Exercise 14.3:
8. Web Resources:
https://www.cs.auckland.ac.nz/software/AlgAnim/hash_func.html
http://datastructuresnotes.blogspot.com/2009/03/hashing-hash-data-structure-and-hash.html
9. Video Resources:
www.youtube.com/watch?v=MfhjkfocRR0
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-046j-introduction-to-
algorithms-sma-5503-fall-2005/video-lectures/lecture-7-hashing-hash-functions/
10. Summary:
This lab introduces students with hash functions, hash tables, their uses and their implementation.
EXPERIMENT 15 OPEN ENDED LAB
Objective:
The primary objective of this open-ended lab activity is to design and implement a Library Management
System. Through this activity, students will apply their knowledge of data structures, file handling, and object-
oriented programming to create a functional program capable of managing library resources, handling user
interactions, and performing efficient search and sorting operations.
Prerequisites:
- Intermediate understanding of programming language.
- Familiarity with data structures such as arrays, linked lists, and file handling concepts.
Materials Needed:
- Development environment (IDE or text editor)
- Sample library dataset (books, users, transactions)
Activity Description:
Task:
Develop a program for managing a library's resources, user interactions, and transactions. The program should
incorporate the following functionalities:
3. Transaction History:
- Maintain a transaction history to record details of books borrowed and returned by users, including
timestamps and user information.
Deliverables:
1. Program Code: Well-structured code implementing the Library Management System, including
appropriate comments and documentation.
2. User Manual: A comprehensive user manual outlining the functionalities of the program, including
instructions for managing books, users, and transactions.
3. Test Cases: A set of test cases and their expected outputs to validate the correctness and robustness of the
program.
4. Reflection and Analysis: A reflective analysis discussing the design decisions, challenges faced, and
insights gained during the development process.
Evaluation Criteria:
- Functionality Completeness: The program should fully implement the specified functionalities, ensuring
accurate management of library resources and transactions.
- Code Quality: The code should be well-organized, readable, and maintainable, adhering to best practices of
programming.
- Efficiency: Efficient utilization of data structures and algorithms to optimize the performance of search and
sorting operations.
- Documentation and Reflection: The quality and completeness of documentation, including user manuals,
test cases, and reflective analysis.