Analysis and Design of Algorithms
Analysis and Design of Algorithms
Analysis and Design of Algorithms
F i r s t D e s i g n U n i v e r s i t y in T h e R e g i o n
ASSIGNMENT NO: 01
Subject Name : Analysis of Design and Algorithm Lab
Subject Code : CSE 2338
Submitted By:
Name:
Dep: B.S.C in CSE (Evening)
Batch: 8th
Semester: 4st
ID:
Submitted To:
Pelob Chakrowborty
Lecturer
Department Of CSE & CSIT
SMUCT
b) If x’s uncle is BLACK, then there can be four configurations for x, x’s parent (p) and x’s
grandparent (g) (This is similar to AVL Tree)
i) Left Left Case (p is left child of g and x is left child of p)
ii) Left Right Case (p is left child of g and x is right child of p)
iii) Right Right Case (Mirror of case i)
iv) Right Left Case (Mirror of case ii)
Following are operations to be performed in four subcases when uncle is BLACK.
All four cases when Uncle is BLACK
Left Left Case (See g, p and x)
3.2) Do following while the current node u is double black and it is not root. Let
sibling of node be s.
(a): If sibling s is black and at least one of sibling’s children is red, perform
rotation(s). Let the red child of s be r. This case can be divided in four subcases
depending upon positions of s and r.
(i) Left Left Case (s is left child of its parent and r is left child of s or both children of
s are red). This is mirror of right right case shown in below diagram.
(ii) Left Right Case (s is left child of its parent and r is right child). This is mirror of
right left case shown in below diagram.
(iii) Right Right Case (s is right child of its parent and r is right child of s or both
children of s are red)
(iv) Right
Left Case (s is right child of its parent and r is left child of s)
(b): If sibling is black and its both children are black, perform recoloring, and recur
for the parent if parent is black.
In this case, if parent was red, then we didn’t need to recur for prent, we can simply
make it black (red + double black = single black)
…..(c): If sibling is red, perform a rotation to move old sibling up, recolor the old
sibling and parent. The new sibling is always black (See the below diagram). This
mainly converts the tree to black sibling case (by rotation) and leads to case (a) or (b).
This case can be divided in two subcases.
(i) Left Case (s is left child of its parent). This is mirror of right right case shown in
below diagram. We right rotate the parent p.
(iii) Right Case (s is right child of its parent). We left rotate the parent p.
3.3) If u is root, make it single black and return (Black height of complete tree reduces
by 1).
below is the C++ implementation of above approach:
Red-Black Tree Deletion Code
#include <iostream>
#include <queue>
usingnamespacestd;
enumCOLOR { RED, BLACK };
classNode {
public:
intval;
COLOR color;
Node *left, *right, *parent;
Node(intval) : val(val) {
parent = left = right = NULL;
color = RED;
}
Node *uncle() {
if(parent == NULL or parent->parent == NULL)
returnNULL;
if(parent->isOnLeft())
returnparent->parent->right;
else
returnparent->parent->left;
}
boolisOnLeft() { returnthis== parent->left; }
Node *sibling() {
if(parent == NULL)
returnNULL;
if(isOnLeft())
returnparent->right;
returnparent->left;
}
voidmoveDown(Node *nParent) {
if(parent != NULL) {
if(isOnLeft()) {
parent->left = nParent;
} else{
parent->right = nParent;
}
}
nParent->parent = parent;
parent = nParent;
}
boolhasRedChild() {
return(left != NULL and left->color == RED) or
(right != NULL and right->color == RED);
}
};
classRBTree {
Node *root;
voidleftRotate(Node *x) {
Node *nParent = x->right;
if(x == root)
root = nParent;
x->moveDown(nParent);
x->right = nParent->left;
if(nParent->left != NULL)
nParent->left->parent = x;
nParent->left = x;
}
voidrightRotate(Node *x) {
Node *nParent = x->left;
if(x == root)
root = nParent;
x->moveDown(nParent);
x->left = nParent->right;
if(nParent->right != NULL)
nParent->right->parent = x;
nParent->right = x;
}
voidswapColors(Node *x1, Node *x2) {
COLOR temp;
temp = x1->color;
x1->color = x2->color;
x2->color = temp;
}
voidswapValues(Node *u, Node *v) {
inttemp;
temp = u->val;
u->val = v->val;
v->val = temp;
}
voidfixRedRed(Node *x) {
if(x == root) {
x->color = BLACK;
return;
}
Node *parent = x->parent, *grandparent = parent->parent,
*uncle = x->uncle();
if(parent->color != BLACK) {
if(uncle != NULL && uncle->color == RED) {
parent->color = BLACK;
uncle->color = BLACK;
grandparent->color = RED;
fixRedRed(grandparent);
} else{
if(parent->isOnLeft()) {
if(x->isOnLeft()) {
swapColors(parent, grandparent);
} else{
leftRotate(parent);
swapColors(x, grandparent);
}
rightRotate(grandparent);
} else{
if(x->isOnLeft()) {
rightRotate(parent);
swapColors(x, grandparent);
} else{
swapColors(parent, grandparent);
}
leftRotate(grandparent);
}
}
}
}
Node *successor(Node *x) {
Node *temp = x;
while(temp->left != NULL)
temp = temp->left;
returntemp;
}
Node *BSTreplace(Node *x) {
if(x->left != NULL and x->right != NULL)
returnsuccessor(x->right);
Implementation-
Following is the C++ implementation of Huffman coding. The algorithmcan be
mapped to any programming language as per the requirement.
#include <iostream>
#include <vector>
#include <queue>
#include <string>
usingnamespace std;
classHuffman_Codes
{
struct New_Node
{
char data;
size_t freq;
New_Node* left;
New_Node* right;
New_Node(char data, size_t freq):data(data),
freq(freq),
left(NULL),
right(NULL)
{}
~New_Node()
{
delete left;
delete right;
}
};
struct compare
{
booloperator()(New_Node* l, New_Node* r)
{
return(l->freq > r->freq);
}
};
New_Node* top;
if(root->data =='$')
{
print_Code(root->left, str +"0");
print_Code(root->right, str +"1");
}
if(root->data !='$')
{
cout << root->data <<" : "<< str <<"\n";
print_Code(root->left, str +"0");
print_Code(root->right, str +"1");
}
}
public:
Huffman_Codes(){};
~Huffman_Codes()
{
delete top;
}
voidGenerate_Huffman_tree(vector<char>& data, vector<size_t>&
freq, size_t size)
{
New_Node* left;
New_Node* right;
priority_queue<New_Node*, vector<New_Node*>, compare >
minHeap;
while(minHeap.size()!=1)
{
left = minHeap.top();
minHeap.pop();
right = minHeap.top();
minHeap.pop();
intmain()
{
int n, f;
char ch;
Huffman_Codes set1;
vector<char> data;
vector<size_t> freq;
cout<<"Enter the number of elements \n";
cin>>n;
cout<<"Enter the characters \n";
for(int i=0;i<n;i++)
{
cin>>ch;
data.insert(data.end(), ch);
}
cout<<"Enter the frequencies \n";
for(int i=0;i<n;i++)
{
cin>>f;
freq.insert(freq.end(), f);
}
return0;
}
The program is executed using same inputs as that of the example explained above.
This will help in verifying the resultant solution set with actual output.
Output:
In this graph,
V={A,B,C,D,E}
E = { AB , AC , BD , CD , DE }
BFS for Disconnected Graph
In previous post, BFS only with a particular vertex is performed i.e. it is assumed that
all vertices are reachable from the starting vertex. But in the case of disconnected
graph or any vertex that is unreachable from all vertex, the previous implementation
will not give the desired output, so in this post, a modification is done in BFS.
All vertices are reachable. So, for above graph simple BFS will work.
As in above graph a vertex 1 is unreachable from all vertex, so simple BFS wouldn’t
work for it.
// C++ implementation of modified BFS
#include<bits/stdc++.h>
adj[u].push_back(v);
vector<bool>&visited)
list<int> q;
visited[u] = true;
q.push_back(u);
while(!q.empty())
u = q.front();
q.pop_front();
if (!visited[adj[u][i]])
visited[adj[u][i]] = true;
q.push_back(adj[u][i]);
if (visited[u] == false)
int main()
int V = 5;
vector<int> adj[V];
addEdge(adj, 0, 4);
addEdge(adj, 1, 2);
addEdge(adj, 1, 3);
addEdge(adj, 1, 4);
addEdge(adj, 2, 3);
addEdge(adj, 3, 4);
BFS(adj, V);
return 0;
}
Output:
04123
Approach: Depth First Traversal can be used to detect cycle in a Graph. DFS for a
connected graph produces a tree. There is a cycle in a graph only if there is a back
edge present in the graph. A back edge is an edge that is from a node to itself
(selfloop) or one of its ancestor in the tree produced by DFS. In the following graph,
there are 3 back edges, marked with cross sign. It can be observed that these 3 back
edges indicate 3 cycles present in the graph.
For a disconnected graph, we get the DFS forest as output. To detect cycle, we can
check for cycle in individual trees by checking back edges.In the previous post, we
have discussed a solution that stores visited vertices in a separate array which stores
vertices of the current recursion call stack.
In this post, a different solution is discussed. The solution is from CLRS book. The
idea is to do DFS of a given graph and while doing traversal, assign one of the below
three colours to every vertex.
WHITE : Vertex is not processed yet. Initially, all vertices are WHITE.
GRAY: Vertex is being processed (DFS for this vertex has started, but not finished
which means that all descendants (in DFS tree) of this vertex are not processed yet (or
this vertex is in the function call stack)
BLACK : Vertex and all its descendants are processed. While doing DFS, if an edge
is encountered from current vertex to a GRAY vertex, then this edge is back edge and
hence there is a cycle.
Algorithm:
1. Create a recursive function that takes the edge and color array (this can be also
kept as a global variable)
2. Mark the current node as GREY.
3. Traverse all the adjacent nodes and if any node is marked GREY then return
true as a loop is bound to exist.
4. If any adjacent vertex is WHITE then call the recursive function for that node.
If the function returns true. Return true.
5. If no adjacent node is grey or has not returned true then mark the current Node
as BLACK and return false.