0% found this document useful (0 votes)
13 views11 pages

Ai Lab

The document discusses the implementation of Breadth-First Search (BFS) and Depth-First Search (DFS) techniques for tree traversal. BFS explores nodes level by level, making it suitable for finding the shortest path in unweighted graphs, while DFS explores as deep as possible along a branch before backtracking. The document also includes code examples for creating binary trees and performing both BFS and DFS traversals.

Uploaded by

PrashansaBhatia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views11 pages

Ai Lab

The document discusses the implementation of Breadth-First Search (BFS) and Depth-First Search (DFS) techniques for tree traversal. BFS explores nodes level by level, making it suitable for finding the shortest path in unweighted graphs, while DFS explores as deep as possible along a branch before backtracking. The document also includes code examples for creating binary trees and performing both BFS and DFS traversals.

Uploaded by

PrashansaBhatia
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 11

Artificial Intelligence Lab: 1

Name: Sarakshi Mamodia


Reg. No.: 231071056
Batch: C

Aim: To implement Breadth-First and Depth-First searching techniques.

Theory

Tree traversal is a key concept in data structures that involves systematically visiting all nodes of a
tree. This process is essential for tasks like searching, updating, or displaying the elements of the
tree.

Types of Tree Traversal

1. Depth-First Traversal (DFS)

2. Breadth-First Traversal (BFS)

Breadth-First Search (BFS)

Description:

 BFS is a graph traversal technique that processes nodes level by level. Starting from the root
(or any chosen node), it explores all adjacent nodes at the current depth before progressing
to nodes at the next depth level.

 It is especially effective for finding the shortest path in unweighted graphs.

Use Case:

 Level Order Traversal: This approach is used in trees to visit all nodes at a specific level
before moving on to the next level.

Completeness:

 BFS is complete as long as the branching factor b is finite.

Time Complexity:

 O(b^d), where b is the branching factor, and d is the depth of the shallowest solution.

Space Complexity:

 O(b^d), since BFS stores all nodes at the current depth.

Depth-First Search (DFS)

Description:
 DFS is a graph traversal algorithm that explores as deep as possible along one path before
backtracking to explore other paths. Unlike BFS, it prioritizes depth over breadth.

Tree Traversal Orders:

1. Preorder: Visit the node first, then its left child, and then its right child.
Order: Root → Left Subtree → Right Subtree.

2. Inorder: Visit the left child first, then the node, and finally the right child.
Order: Left Subtree → Root → Right Subtree.

3. Postorder: Visit the left child, then the right child, and finally the node.
Order: Left Subtree → Right Subtree → Root.

Completeness:

 DFS is not guaranteed to be complete, as it may get stuck in infinite-depth spaces or cycles.

Time Complexity:

 O(b^m), where b is the branching factor, and mmm is the maximum depth of the search tree.

Space Complexity:

 O(bm), requiring linear space proportional to the depth of the search tree.

Code:

#include <iostream>

#include <queue>

using namespace std;

struct TreeNode {

int value;

TreeNode* left;

TreeNode* right;

TreeNode(int val) {

value = val;

left = nullptr;

right = nullptr;

};
// Function to insert nodes in the tree level-wise

TreeNode* createTree() {

cout << "Enter the root value (or -1 for no node): ";

int rootValue;

cin >> rootValue;

if (rootValue == -1) return nullptr; // No tree

TreeNode* root = new TreeNode(rootValue);

queue<TreeNode*> q;

q.push(root);

while (!q.empty()) {

TreeNode* current = q.front();

q.pop();

int leftValue, rightValue;

cout << "Enter left child of " << current->value << " (or -1 for no node): ";

cin >> leftValue;

if (leftValue != -1) {

current->left = new TreeNode(leftValue);

q.push(current->left);

cout << "Enter right child of " << current->value << " (or -1 for no node): ";

cin >> rightValue;

if (rightValue != -1) {

current->right = new TreeNode(rightValue);


q.push(current->right);

return root;

// Function for BFS (Level Order Traversal)

void BFS(TreeNode* root) {

if (root == nullptr) {

cout << "Tree is empty." << endl;

return;

queue<TreeNode*> q;

q.push(root);

cout << "BFS (Level Order Traversal): ";

while (!q.empty()) {

TreeNode* current = q.front();

q.pop();

cout << current->value << " ";

if (current->left != nullptr) {

q.push(current->left);

if (current->right != nullptr) {

q.push(current->right);

}
}

cout << endl;

int main() {

cout << "Create your binary tree:" << endl;

TreeNode* root = createTree();

BFS(root);

return 0;

Output:

Working:

1. BFS starts with the root node (1). It is added to the queue and processed first.
Queue: [1] → Process: 1 → Output: 1

2. The neighbors (children) of node 1, which are 2 and 3, are added to the queue.
Queue: [2, 3] → Process: 2 → Output: 1, 2
3. The neighbors (children) of node 2, which are 4 and 5, are added to the queue.
Queue: [3, 4, 5] → Process: 3 → Output: 1, 2, 3

4. Node 3 has no children, so the next node in the queue (4) is processed.
Queue: [4, 5] → Process: 4 → Output: 1, 2, 3, 4

5. Finally, node 5 is processed. It has no children, and the queue becomes empty.
Queue: [5] → Process: 5 → Output: 1, 2, 3, 4, 5

Applications of BFS

1. Shortest Path in Unweighted Graphs: Efficiently finds the minimum edges between two
nodes.

2. Connected Components: Identifies connected components in a graph.

3. Cycle Detection: Detects cycles in undirected graphs.

4. Level Order Traversal in Trees: Traverses trees level by level.

5. Web Crawlers: Explores all reachable links starting from a given page.

BFS provides a structured and efficient approach for traversing graphs and trees.

Code:

#include <iostream>

#include <queue>

using namespace std;

struct TreeNode {

int value;

TreeNode* left;

TreeNode* right;

TreeNode(int val) {

value = val;

left = nullptr;

right = nullptr;

};
// Function to build a binary tree from user input

TreeNode* buildTree() {

cout << "Enter the root value (-1 for no node): ";

int rootValue;

cin >> rootValue;

if (rootValue == -1) return nullptr;

TreeNode* root = new TreeNode(rootValue);

queue<TreeNode*> q;

q.push(root);

while (!q.empty()) {

TreeNode* current = q.front();

q.pop();

int leftValue, rightValue;

cout << "Enter left child of " << current->value << " (-1 for no node): ";

cin >> leftValue;

if (leftValue != -1) {

current->left = new TreeNode(leftValue);

q.push(current->left);

cout << "Enter right child of " << current->value << " (-1 for no node): ";

cin >> rightValue;

if (rightValue != -1) {

current->right = new TreeNode(rightValue);

q.push(current->right);
}

return root;

void DFS_Preorder(TreeNode* root) {

if (root == nullptr) return;

cout << root->value << " ";

DFS_Preorder(root->left);

DFS_Preorder(root->right);

void DFS_Inorder(TreeNode* root) {

if (root == nullptr) return;

DFS_Inorder(root->left);

cout << root->value << " ";

DFS_Inorder(root->right);

void DFS_Postorder(TreeNode* root) {

if (root == nullptr) return;

DFS_Postorder(root->left);

DFS_Postorder(root->right);

cout << root->value << " ";

int main() {
cout << "Build your binary tree:\n";

TreeNode* root = buildTree();

cout << "Preorder Traversal: ";

DFS_Preorder(root);

cout << endl;

cout << "Inorder Traversal: ";

DFS_Inorder(root);

cout << endl;

cout << "Postorder Traversal: ";

DFS_Postorder(root);

cout << endl;

return 0;

Output:
Working:

1. Preorder Traversal (Node → Left → Right):

 Visit the node first, then recursively traverse the left subtree, followed by the right subtree.

Steps:

1. Visit node 1 (root).

2. Traverse left subtree of 1: Visit node 2 → Visit node 4 → Visit node 5.

3. Traverse right subtree of 1: Visit node 3.

Output: 1, 2, 4, 5, 3

2. Inorder Traversal (Left → Node → Right):

 Recursively traverse the left subtree, visit the node, then traverse the right subtree.

Steps:

1. Traverse left subtree of 1: Traverse left subtree of 2 (Visit node 4) → Visit node 2 → Visit
node 5.

2. Visit node 1 (root).

3. Traverse right subtree of 1: Visit node 3.

Output: 4, 2, 5, 1, 3

3. Postorder Traversal (Left → Right → Node):

 Recursively traverse the left subtree, then the right subtree, and visit the node at the end.

Steps:

1. Traverse left subtree of 1: Traverse left subtree of 2 (Visit node 4) → Visit node 5 → Visit
node 2.
2. Traverse right subtree of 1: Visit node 3.

3. Visit node 1 (root).

Output: 4, 5, 2, 3, 1

Applications of DFS in Binary Trees

1. Preorder Traversal:

o Used for copying a tree.

o Produces prefix expressions for expression trees.

2. Inorder Traversal:

o Produces sorted order for binary search trees (BSTs).

o Essential for many tree-related algorithms.

3. Postorder Traversal:

o Useful for freeing memory from a tree.

o Produces postfix expressions for expression trees.

DFS facilitates efficient exploration of binary trees and solving tree-related problems.

Conclusion

In this experiment, we examined the functionality and implementation of two graph traversal
techniques, Breadth-First Search (BFS) and Depth-First Search (DFS). BFS traverses a graph or tree
level by level, exploring all nodes at the current depth before moving to the next. It uses a queue
data structure to track the nodes to visit, making it ideal for applications like finding the shortest path
in an unweighted graph or performing level-order traversal in trees. On the other hand, DFS explores
as deeply as possible along each branch before backtracking, utilizing either recursion or an explicit
stack. It supports three traversal orders—pre-order, in-order, and post-order—and is commonly
used for tasks like pathfinding, cycle detection, and analyzing hierarchical structures. While BFS
processes nodes horizontally, requiring more memory for nodes at the current level, DFS explores
vertically and requires memory proportional to the depth. BFS guarantees finding the shortest path
in unweighted graphs, whereas DFS does not ensure optimal paths. Together, these techniques offer
versatile approaches to solving various computational problems.

You might also like