DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Assignment
Course Name: Design and Analysis of Algorithms
Subject Code: - (22CSH-317/22ITP-317)
Student Name: IRFAN UID: 22BCS80041
Branch: BE-CSE Section/Group: 611/A
Semester: V Date of Performance:24/10/24
Aim:
Given the pointer to the head node of a linked list, change the next pointers of
the nodes so that their order is reversed. The head pointer given may be null
meaning that the initial list is empty.
Code:
#include <bits/stdc++.h>
using namespace std; struct
SinglyLinkedListNode {
int data;
SinglyLinkedListNode* next;
SinglyLinkedListNode(int x) : data(x), next(nullptr) {}
};
SinglyLinkedListNode* insertAtEnd(SinglyLinkedListNode* head, int data) {
SinglyLinkedListNode* current = head; if
(!head) return new SinglyLinkedListNode(data);
while (current->next) current = current->next;
current->next = new SinglyLinkedListNode(data);
return head;
}
void printList(SinglyLinkedListNode* head) {
while (head) {
cout << head->data << (head->next ? " " : "\n");
head = head->next;
}
}
SinglyLinkedListNode* reverse(SinglyLinkedListNode* head) {
SinglyLinkedListNode *prev = nullptr, *current = head, *nextNode = nullptr;
while (current) { nextNode = current->next; current->next = prev;
prev = current;
current = nextNode;
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
return prev;
} int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t, n, val;
cin >> t;
while (t--) {
cin >> n;
SinglyLinkedListNode* head =
nullptr; while (n--) { cin >>
val;
head = insertAtEnd(head, val);
}
SinglyLinkedListNode* reversedHead =
reverse(head); printList(reversedHead); while
(reversedHead) {
SinglyLinkedListNode* temp =
reversedHead; reversedHead = reversedHead-
>next; delete temp;
} }
return 0; }
Ques 2:
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
Write the postOrder function. It received 1 parameter: a pointer to the root of a binary
tree. It must print the values in the tree's postorder traversal as a single line of
spaceseparated values.
Code:
#include <bits/stdc++.h>
using namespace std;
class Graph { public: unordered_map<int,
vector<int>> adjList;
void addEdge(int u, int v) {
adjList[u].push_back(v);
}
void DFS(int node, unordered_map<int, bool> &visited, vector<int> &postOrderResult) {
visited[node] = true;
for (int neighbor : adjList[node]) {
if (!visited[neighbor]) {
DFS(neighbor, visited, postOrderResult);
}
}
postOrderResult.push_back(node); // Add to postorder when finished with all neighbors
}
vector<int> getPostOrder(int startNode, int numNodes)
{ unordered_map<int, bool> visited; vector<int>
postOrderResult;
DFS(startNode, visited, postOrderResult);
return postOrderResult;
} }; int
main() {
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
while (t--) {
int n, m;
cin >> n >> m; // n is the number of nodes, m is the number of edges
Graph g;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
g.addEdge(u, v); // Add directed edge u -> v
}
int startNode;
cin >> startNode;
vector<int> postOrder = g.getPostOrder(startNode, n);
for (int node : postOrder) {
cout << node << " ";
}
cout << "\n";
}
return 0;
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
3. You are given a pointer to the root of a binary search tree and values to be inserted into the tree.
Insert the values into their appropriate position in the binary search tree and return the root of the
updated binary tree.
CODE:-
#include <bits/stdc++.h> using
namespace std;
struct TreeNode {
int data;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : data(x), left(nullptr), right(nullptr) {} };
TreeNode* insert(TreeNode* root, int data) { if (!root)
return new TreeNode(data); if (data < root->data) root-
>left = insert(root->left, data); else root->right =
insert(root->right, data); return root;
} void inOrderTraversal(TreeNode* root)
{ if (!root) return;
inOrderTraversal(root->left);
cout << root->data << " ";
inOrderTraversal(root->right);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0); int t, n, val;
cin >> t;
while(t--){ cin >> n;
vector<int> arr(n); for(auto &x: arr)
cin >> x; TreeNode* root = nullptr;
for(auto x: arr) root = insert(root, x);
inOrderTraversal(root); cout << "\n";
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
// Memory cleanup if(root){
queue<TreeNode*> q; q.push(root);
while(!q.empty()){
TreeNode* curr = q.front(); q.pop();
if(curr->left) q.push(curr->left); if(curr-
>right) q.push(curr->right); delete curr;
}
} }
return 0;
}
4. Huffman Coding assigns variable length codewords to fixed length input characters based on their
frequencies. More frequent characters are assigned shorter codewords and less frequent characters are assigned
longer codewords. All edges along the path to a character contain a code digit. If they are on the left side of the
tree, they will be a 0 (zero). If on the right, they'll be a 1 (one). Only the leaves will contain a letter and its
frequency count. All other nodes will contain a null instead of a character, and the count of the frequency of all
of it and its descendant characters.
For instance, consider the string ABRACADABRA. There are a total of 11 characters in the string. This
number should match the count in the ultimately determined root of the tree. Our frequencies are A= 5, B=2,
R=2,C=1 and D-1. The two smallest frequencies are for C and D, both equal to 1 , so we'll create a tree with
them. The root node will contain the sum of the counts of its descendants, in this case 1+1 =2 . The left node
will be the first character encountered, C , and the right will contain D . Next we have 3 items with a character
count of 2 : the tree we just created, the character B and the character R. The tree came first, so it will go on the
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
left of our new root node. B will go on the right. Repeat until the tree is complete, then fill in the 1 's and 0 's for
the edges.
Code:-
#include<bits/stdc++.h> using
namespace std;
struct TreeNode{
char data; int
freq;
TreeNode* left;
TreeNode* right;
TreeNode(char x, int f): data(x), freq(f), left(NULL), right(NULL){} };
struct Compare{
bool operator()(TreeNode* a, TreeNode* b){ if(a-
>freq == b->freq) return a->data > b->data; return a-
>freq > b->freq;
}
};
TreeNode* buildHuffmanTree(map<char, int> &freq){
priority_queue<TreeNode*, vector<TreeNode*>, Compare> pq; for(auto &[c, f]:
freq) pq.push(new TreeNode(c, f)); while(pq.size()>1){
TreeNode* left = pq.top(); pq.pop();
TreeNode* right = pq.top(); pq.pop();
TreeNode* parent = new TreeNode('\0', left->freq + right->freq);
parent->left = left; parent->right = right; pq.push(parent);
} return
pq.top();
}
map<char, string> getCodes(TreeNode* root, string code, map<char, string> &codes){
if(!root) return codes; if(root->data != '\0') codes[root->data] = code;
getCodes(root->left, code+"0", codes); getCodes(root->right, code+"1", codes);
return codes;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
string encodeString(string s, map<char, string> &codes){
string encoded; for(char c:s) encoded += codes[c];
return encoded;
}
string decode_huff(TreeNode* root, string s){
string decoded; TreeNode* node=root;
for(char c:s){ node = (c=='0')? node->left
: node->right; if(!node->left && !node-
>right){ decoded += node->data;
node=root;
}
}
return decoded;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0); int t; cin>>t;
while(t--){ string s;
cin>>s;
map<char, int> freq; for(char c:s) freq[c]++;
TreeNode* root = buildHuffmanTree(freq); map<char,
string> codes; getCodes(root, "", codes); string
encoded = encodeString(s, codes);
cout<<decode_huff(root, encoded)<<"\n";
// Cleanup queue<TreeNode*> q;
if(root) q.push(root); while(!q.empty()){
TreeNode* curr = q.front(); q.pop();
if(curr->left) q.push(curr->left); if(curr-
>right) q.push(curr->right); delete curr;
}
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
5. we're covering a divide-and-conquer algorithm called Quicksort (also known as Partition Sort). This
challenge is a modified version of the algorithm that only addresses partitioning. It is implemented as
follows:
Step 1: Divide
Choose some pivot element, p, and partition your unsorted array, arr, into three smaller arrays: ,left
,right and equal, where each element in left < p, each element in right > p, and each element in equal =
p.
CODE:
#include<bits/stdc++.h> using
namespace std;
vector<int> quickSort(vector<int> arr){
if(arr.empty()) return arr; int
p=arr[0]; vector<int> left, equal,
right; for(auto x: arr){ if(x < p)
left.push_back(x); else if(x == p)
equal.push_back(x); else
right.push_back(x);
}
left.insert(left.end(), equal.begin(), equal.end());
left.insert(left.end(), right.begin(), right.end()); return
left;
}
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
int main(){
ios::sync_with_stdio(false); cin.tie(0); int
t; cin>>t; while(t--){ int n; cin>>n;
vector<int> arr(n); for(auto &x: arr) cin>>x;
vector<int> sorted = quickSort(arr);
for(int i=0;i<sorted.size();i++) cout<<sorted[i]<<(i<sorted.size()-1?" ":"");
cout<<"\n";
}
return 0;
}
6. - Given an amount and the denominations of coins available, determine how many ways change
can be made for amount. There is a limitless supply of each coin type.
CODE:
#include<bits/stdc++.h>
using namespace std;
DEPARTMENT OF
COMPUTER SCIENCE & ENGINEERING
int getWays(int n, vector<int> &c){
vector<long long> dp(n+1,0); dp[0]=1;
for(auto coin:c) for(int i=coin;i<=n;i++) dp[i] += dp[i-coin];
return dp[n];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0); int t;
cin>>t; while(t--){
int n,m; cin>>n>>m;
vector<int> c(m); for(auto &x: c) cin>>x;
cout<<getWays(n,c)<<"\n";
}
}