Project Report On Algorithm Visualizer
Project Report On Algorithm Visualizer
A Major Project
BY
VINAY PRATAP
(MCA/40015/21)
DEPARTMENT OF CSE
1
BIRLA INSTITUTE OF TECHNOLOGY
MESRA
Off- Campus, Lalpur, Ranchi
Certificate
This is to certify that the contents of this major project entitled “Algorithm
Visualizer” is a bonafide work carried out by Vinay Pratap | (Class Roll No.:
MCA/40015/21), of MCA (4th Semester), may be accepted in partial fulfillment for
the degree of Master of Computer Application under my guidance.
This is to further certify that the matter of this of this project has not been
submitted by anyone else for the award of any degree.
………………………………………
(Dr. Amar Kumar)
Department of CSE
Birla Institute of Technology- Lalpur
2
BIRLA INSTITUTE OF TECHNOLOGY
MESRA
Off- Campus, Lalpur, Ranchi
Certificate Of Approval
Date: Date:
Director (In-Charge)
Birla Institute of Technology
Lalpur, Ranchi
3
ACKNOWLEDGEMENT
We would like to express special thanks & gratitude to our guide, Dr. Amar
Kumar who gave us this golden opportunity to work on this scalable project
on the topic of “Algorithm Visualizer”, which led us into doing a lot of
Research which diversified our knowledge to a huge extent for which we
are thankful.
Also, we would like to thank our parents and friends who supported us
a lot in finalizing this project within the limited time frame.
--------------------------------------
VINAY PRATAP
(MCA/40015/21)
4
Table of Contents
Page No.
Abstract …………………………………………………………………… 6
1. Introduction ………………………………………………………………. 8
4. System Design……………………………………………………………… 16
8. Conclusion…………………………………………………………………… 103
5
Abstract
6
underlying code to help users understand the logic and
mechanics behind each algorithm. Ultimately, the Algorithm
Visualizer project aims to promote algorithm literacy and
empower users to use these tools effectively in their work or
personal projects.
7
1. Introduction
8
In this report, an e-learning tool for Pathfinder, Prime Numbers, Sorting
Algorithms, N Queen, Convex Hull, Binary Search Game visualization is
described.
For example,
Dijkstra’s Algorithm
A* Search
Swarm Algorithm
9
2. Sorting Algorithm: - In sorting the animation tool would
represent information as a bar and once choosing a data-
ordering and algorithms, the user will run an automatic
animation or step through it at their own pace.
Merge Sort
Quick Sort
Heap Sort
Bubble Sort
10
2. Review of Literature
11
Balancing simplicity and complexity: A key challenge in algorithm
visualizer projects is balancing simplicity and complexity. While it's
essential to provide an accessible platform that is easy to use for
beginners, it's also important to provide in-depth insights for more
experienced users. Striking the right balance can be challenging.
12
3. Objective of the Project
The objectives of a project on algorithm visualizer can vary depending on
the specific goals of the project, but some common objectives might include:
-
13
User
Binary
Sorting Search
Algorithm
Prime
Numbers
Visualization
14
Features:
The algorithm visualizer project includes the following features:
and JavaScript
Challenges Encountered
development, including:
15
4. System Design
Hardware Requirements:
Laptop/ Desktop
Core i5/i7 processor
At least 8 GB RAM
At least 60 GB of Usable Hard Disk Space
Software Requirements:
IDE: - Visual Studio Code
Development Environment: - React.js
Coding Language: - HTML, CSS, JavaScript
Browser: - Google Chrome
Operating System: - Windows 7 or above
Data Information:
17
Start
Choose action
Visualize
End
18
Data Format:
The sample of the dataset is given below.
class BinarySearch {
constructor(array, searchValue) {
this.array = array;
this.left = 0;
this.right = array.length - 1;
this.mid = Math.floor((this.left + this.right) / 2);
this.searchValue = searchValue;
}
executeStep() {
if (this.left > this.right) {
return null;
}
if (this.array[this.mid] === this.searchValue) {
return this.mid;
} else if (this.array[this.mid] > this.searchValue) {
this.right = this.mid - 1;
} else {
this.left = this.mid + 1;
}
this.mid = Math.floor((this.left + this.right) / 2);
return "continue";
}
}
19
In this example, the data format includes a class called 'BinarySearch' that
represents the binary search algorithm being visualized. The class includes a
constructor that initializes the algorithm with an array to search and the value
being searched for. The class also includes a method called 'executeStep()' that
executes one step of the algorithm and updates the state of the algorithm
accordingly.
The data format in this example is represented using JavaScript code, which
can be easily executed by the algorithm visualizer to visualize the algorithm's
execution. The visualizer can use the state of the ‘BinarySearch’ object to show
the current state of the algorithm's execution, such as the current value of 'left',
'right', and 'mid'.
20
5 . Methodology for Implementation
(Formulation/Algorithm)
DATA COLLECTION:
Here are some examples of data collection methods for an algorithm visualizer
using pathfinding visualization and sorting algorithm:
21
Analytics: For pathfinding visualization, we can use analytics tools such
as Google Analytics to track user engagement with the algorithm
visualizer. For example, we can collect data on the number of users who
use the visualizer, the duration of use, and the paths that are most
frequently used. Similarly, for sorting algorithms, we can collect data on
the number of users who use the visualizer, the duration of use, and the
sorting algorithms that are most frequently used.
22
Path-finding Algorithm
Pathfinding algorithms are used to find the shortest path between two points
in a graph or grid. There are several pathfinding algorithms available,
including Dijkstra's algorithm, A* algorithm, and breadth-first search
algorithm.
1. Dijkstra’s Algorithm: -
Methodology:
1. Initialize the source node with distance 0 and all other nodes with infinite
distance.
2. Add the source node to a priority queue.
3. While the priority queue is not empty, do the following:
a. Pop the node with the smallest distance from the priority queue.
b. For each neighbor of the popped node, do the following:
i. Calculate the distance from the source node to the neighbor through
the popped node.
ii. If this distance is less than the current distance for the neighbor,
update the distance and the path information for the neighbor.
iii. Add the neighbor to the priority queue.
4. Return the distance and path information for all nodes.
23
Code Example:
Here is an example implementation of Dijkstra's algorithm in Python:
import heapq
while queue:
current_distance, current_node = heapq.heappop(queue)
24
In this example, the 'dijkstra' function takes two arguments: 'graph', which is
a dictionary that represents the graph, and 'source', which is the starting
node.
The function initializes the 'distances' dictionary with infinite distances for all
nodes except the source node, which has a distance of 0. It then creates a
priority queue 'queue' with the source node.
The function uses the 'heapq' module to implement the priority queue. Each
item in the queue is a tuple with the distance and the node.
The function then enters a loop where it pops the node with the smallest
distance from the queue, and updates the distance and path information for
its neighbors. It checks if the distance from the source node to the neighbor
through the popped node is less than the current distance for the neighbor. If
it is, the function updates the distance and path information for the neighbor,
and adds the neighbor to the queue.
Finally, the function returns the 'distances' dictionary and the 'path'
dictionary for all nodes. The 'path' dictionary stores the parent of each node
in the shortest path from the source node to that node.
2. A* algorithm: -
The A* (pronounced "A star") algorithm is a heuristic-based search algorithm
that finds the shortest path between a starting node and a goal node in a
weighted graph. It works by maintaining two lists of nodes: an open list of
nodes that have been visited but not yet explored, and a closed list of nodes
that have been explored. The algorithm selects the next node to visit by
25
choosing the node with the lowest total cost, which is the sum of the cost from
the starting node to the current node (the g-value) and an estimated cost from
the current node to the goal node (the h-value).
Methodology:
26
Code Example:
while open_set:
current = min(open_set, key=lambda node: f_score[node])
if current == goal:
return construct_path(parent, current)
open_set.remove(current)
closed_set.add(current)
parent[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score[neighbor] = g_score[neighbor] + heuristic(neighbor, goal)
return None
27
def construct_path(parent, node):
path = [node]
while node in parent:
node = parent[node]
path.append(node)
path.reverse()
return path
In this example, the 'a_star' function takes three arguments: 'start' and
'goal', which are the start and goal nodes, and ‘graph’, which is a dictionary
that represents the graph. The keys of the dictionary are the nodes, and the
values are lists of the nodes that are adjacent to the key node.
Breadth-first search (BFS) is a graph traversal algorithm that visits all the
nodes of a graph or tree in breadth-first order, i.e., it visits all the nodes at the
same level before moving down to the next level. BFS is often used for finding
the shortest path between two nodes in an unweighted graph.
Methodology:
1. Initialize a queue and a visited set. Enqueue the start node to the queue
and add it to the visited set.
2. While the queue is not empty, do the following:
a. Dequeue the front node from the queue.
b. For each of the node's neighbors, if the neighbor has not been visited,
mark it as visited and enqueue it to the queue.
c. If the goal node is found, return the path.
3. If the goal node is not found, return null.
28
Code Example:
while queue:
node = queue.pop(0)
if node == goal:
return construct_path(parent, goal)
return None
29
In this example, the 'bfs' function takes three arguments: 'start' and 'goal',
which are the start and goal nodes, and 'graph', which is a dictionary that
represents the graph. The keys of the dictionary are the nodes, and the values
are lists of the nodes that are adjacent to the key node.
The function uses a 'queue' to keep track of the nodes to visit and a 'visited' set
to keep track of the visited nodes. The 'parent' dictionary is used to keep track
of the parent of each visited node in order to reconstruct the path once the
goal node is found.
The algorithm starts by enqueueing the start node to the queue and marking
it as visited. It then enters a loop where it dequeues the front node from the
queue, and for each of its neighbors, if the neighbor has not been visited, it
marks it as visited, enqueues it to the queue, and adds the parent of the
neighbor to the 'parent' dictionary. If the goal node is found, the function calls
the 'construct_path' function to reconstruct the path from the start node to
the goal node. If the goal node is not found, the function returns 'None'.
30
Sorting Algorithm
1. Quick-Sort Algorithm: -
Methodology:
1. If the array has fewer than two elements, return the array.
3. Partition the array into two subarrays, one with elements smaller than the
pivot and the other with elements greater than the pivot.
31
Code Example:
def quicksort(arr):
if len(arr) < 2:
return arr
pivot = arr[0]
less = [x for x in arr[1:] if x <= pivot]
greater = [x for x in arr[1:] if x > pivot]
In this example, the ‘quicksort’ function takes one argument, ‘arr’, which is the
array to be sorted. The function first checks if the length of the array is less
than two, and if so, returns the array. If the length of the array is two or
greater, the function selects the first element of the array as the pivot, and
partitions the rest of the array into two subarrays, one with elements smaller
than or equal to the pivot, and the other with elements greater than the pivot.
32
The function then recursively sorts the subarrays using quicksort, and
concatenates the sorted subarrays with the pivot element in between them, in
ascending order. Finally, the function returns the sorted array.
2. Bubble-Sort Algorithm: -
Bubble sort is a simple sorting algorithm that works by repeatedly swapping
adjacent elements if they are in the wrong order. It gets its name from the way
smaller elements "bubble" to the top of the list as the algorithm progresses.
Methodology:
1. Starting from the first element, compare the current element with the
next element.
2. If the current element is greater than the next element, swap them.
3. Move to the next pair of elements and repeat step 2.
4. Continue this process until the end of the list is reached.
5. Repeat steps 1-4 for each element in the list.
34
3. Insertion-Sort Algorithm: -
Insertion sort is a simple sorting algorithm that sorts an array or list of
elements by repeatedly iterating over the list and inserting each element
in its correct position in a sorted sub-list.
Methodology:
The algorithm works as follows:
1. Start with the first element of the list and assume it is sorted.
2. Iterate over the list, starting with the second element. For each
element, compare it with all the elements in the sorted sub-list that
come before it and insert it at the correct position.
3. Repeat step 2 until all the elements are sorted.
Python Code:
def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j=i-1
while j >= 0 and arr[j] > key:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr
35
In this code, 'arr' is the input list to be sorted. We start iterating from the
second element ('i=1') and assume the first element is sorted. We store the
current element in a variable called 'key' and start comparing it with the
elements in the sorted sub-list that come before it. If an element is greater
than 'key', we shift it to the right by one position and continue the
comparison until we find the correct position for 'key'. We then insert 'key'
at the correct position in the sorted sub-list.
The outer loop iterates over all the elements in the list, and the inner loop
compares and shifts the elements in the sorted sub-list. The time
complexity of the insertion sort algorithm is O(n^2) in the worst case,
where n is the number of elements in the list. However, it performs well
on small lists and is an efficient sorting algorithm for nearly sorted lists.
4. Selection-Sort Algorithm: -
The selection sort algorithm is a simple sorting algorithm that sorts an array
by repeatedly finding the minimum element from the unsorted part of the
array and placing it at the beginning.
In every iteration of the selection sort, the minimum element from the
unsorted subarray is picked and swapped with the leftmost element of the
unsorted subarray. The leftmost element is then considered sorted, and the
process continues until the entire array is sorted.
36
Methodology:
The step-by-step methodology of implementing the selection-sort algorithm:
1. Set the first element as the minimum.
2. Compare the minimum element with the second element. If the second
element is smaller than the minimum, set the second element as the new
minimum.
3. Repeat step 2 for the rest of the elements in the array.
4. Swap the minimum element with the first element of the array.
5. Repeat steps 1 through 4 for the remaining elements of the array.
def selection_sort(arr):
n = len(arr)
for i in range(n):
# Find the minimum element in the unsorted part of the array
min_index = i
for j in range(i+1, n):
if arr[j] < arr[min_index]:
min_index = j
37
Here, we first find the length of the array and then iterate through each
element of the array using a for loop. In each iteration, we find the minimum
element in the unsorted part of the array and swap it with the first element of
the unsorted subarray. We then continue this process until the entire array is
sorted.
5. Merge-Sort Algorithm: -
Mergesort is a popular sorting algorithm that works by recursively
dividing an array into smaller subarrays until each subarray contains only
one element. Then, it combines the subarrays by sorting and merging
them.
Methodology:
The following is the methodology of implementing the Mergesort
algorithm along with a code example in Python:
1. Divide the array into two halves
2. Sort the left half recursively using mergesort
3. Sort the right half recursively using mergesort
4. Merge the two sorted halves
def mergeSort(arr):
if len(arr) > 1:
mid = len(arr) // 2 # Find the mid-point of the array
38
left_half = arr[:mid] # Divide the array into two halves
right_half = arr[mid:]
i=j=k=0
In this code, the 'mergeSort()' function takes an array as input and sorts it
using the Mergesort algorithm. The function first checks if the length of
the array is greater than 1. If the array contains only one element, it is
already sorted and the function returns. Otherwise, it divides the array into
two halves using the mid-point of the array. Then, it recursively calls itself
to sort the left and right halves of the array. Once both halves are sorted, it
merges them using the 'while' loop until all the elements are sorted in the
final output array. Finally, it returns the sorted array.
which is the sorted version of the input array '[64, 34, 25, 12, 22, 11, 90]'.
6. Heap-Sort Algorithm: -
Heapsort is a sorting algorithm that works by building a heap data
structure from the array to be sorted and then repeatedly extracting the
maximum element from the heap and placing it at the end of the sorted
array. The process is repeated until the entire array is sorted.
40
Methodology:
2. Swap the first element of the heap with the last element of the heap.
3. Discard the last element of the heap (it is now sorted) and reduce the
root element.
def heap_sort(arr):
n = len(arr)
41
# Build a max heap
for i in range(n // 2 - 1, -1, -1):
max_heapify(arr, n, i)
42
Let's test the code with an example:
Output:
43
6. Implementation Details
10. Implement the algorithm: Once the user interface is designed, the
next step is to implement the algorithm. This involves writing the code
for the algorithm and incorporating it into the visualizer.
44
11. Implement the visualization: After the algorithm is implemented, the
next step is to implement the visualization. This involves using graphics
and animation to show the steps of the algorithm as it progresses.
13. Deploy the application: Once the application is tested and working
correctly, it can be deployed to a web server so that users can access it
online.
Here are some additional features that you can add to the algorithm visualizer
project:
<!DOCTYPE html>
45
<html>
<head>
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
svg {
background-color: white;
border: 1px solid black;
}
</style>
</head>
<body>
<svg width="500" height="500"></svg>
<script>
// Bubble Sort implementation
function bubbleSort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
// Visualization elements
const svg = d3.select("svg");
46
const width = +svg.attr("width");
const height = +svg.attr("height");
const padding = 50;
const numRects = 10;
const rectWidth = (width - padding * 2) / numRects;
svg
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => padding + i * rectWidth)
.attr("y", (d) => height - padding - d * rectWidth)
.attr("width", rectWidth)
.attr("height", (d) => d * rectWidth)
function bubbleSort() {
let n = data.length;
let swapped;
do {
swapped = false;
for (let i = 0; i < n - 1; i++) {
if (data[i] > data[i + 1]) {
const temp = data[i];
data[i] = data[i + 1];
data[i + 1] = temp;
47
swapped = true;
}
}
bars.data(data)
.transition()
.duration(1000)
.attr("y", (d) => svgHeight - yScale(d));
n--;
} while (swapped);
}
d3.select("#sort-button").on("click", bubbleSort);
Next, we create a selection of bars using the selectAll method, bind the data to
the bars using the data method, and create a rect element for each data point
using the enter method. We set the x and y positions and the width and height
of the bars using the scale functions.
The bubbleSort function implements the Bubble Sort algorithm using a do-
while loop. Each time two elements are swapped, we update the data array
and the position of the bars using the data and transition methods. The
duration argument specifies how long the transition should take, in
milliseconds.
48
Finally, we add a button to the HTML document with an ID of sort-button,
and use the on method to call the bubbleSort function when the button is
clicked.
This example is just a starting point - you can customize the visualization to
add more features, such as highlighting the bars being compared, or
animating the swaps in a different way.
49
7. Results and Sample Output
Algorithm visualizers are tools that can help developers and students better
understand how algorithms work by visualizing their execution step-by-step.
Here are some potential results of using an algorithm visualizer, along with
examples and sample outputs:
Results:
50
Enhanced learning: Algorithm visualizers are particularly useful for
educational purposes, as they can help students visualize and
understand complex algorithms and data structures.
Pathfinding Algorithms
Pathfinding algorithms are used to find the shortest or most efficient path
between two points in a graph or network. There are several pathfinding
algorithms such as Dijkstra's algorithm, A* algorithm, BFS, and DFS.
Code:
<html>
<head>
<title>Pathfinding Visualizer</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link id="cssTheme" rel="stylesheet" href="public/styling/cssBasic.css"/>
<link rel="shortcut icon" type="image/png" href="public/styling/c_icon.png"/>
</head>
<body>
<div id='navbarDiv'>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a id="refreshButton" class="navbar-brand" href="#">Pathfinding Visualizer</a>
</div>
<ul class="nav navbar-nav">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Algorithms
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li id='startButtonDijkstra'><a href="#">Dijkstra's Algorithm</a></li>
<li id='startButtonAStar2'><a href="#">A* Search</a></li>
<li id='startButtonGreedy'><a href="#">Greedy Best-first Search</a></li>
51
<li id='startButtonAStar'><a href="#">Swarm Algorithm</a></li>
<li id='startButtonAStar3'><a href="#">Convergent Swarm Algorithm</a></li>
<li id='startButtonBidirectional'><a href="#">Bidirectional Swarm
Algorithm</a></li>
<li id='startButtonBFS'><a href="#">Breadth-first Search</a></li>
<li id='startButtonDFS'><a href="#">Depth-first Search</a></li>
</ul>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Mazes &
Patterns
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li id='startButtonCreateMazeTwo'><a href="#">Recursive Division</a></li>
<li id='startButtonCreateMazeThree'><a href="#">Recursive Division
(vertical skew)</a></li>
<li id='startButtonCreateMazeFour'><a href="#">Recursive Division
(horizontal skew)</a></li>
<li id='startButtonCreateMazeOne'><a href="#">Basic Random Maze</a></li>
<li id='startButtonCreateMazeWeights'><a href="#">Basic Weight
Maze</a></li>
<li id='startStairDemonstration'><a href="#">Simple Stair Pattern</a></li>
</ul>
</li>
<li id='startButtonAddObject'><a href="#">Add Bomb</a></li>
<li id='startButtonStart'><button id="actualStartButton" class="btn btn-default
navbar-btn" type="button">Visualize!</button></li>
<li id='startButtonClearBoard'><a href="#">Clear Board</a></li>
<li id='startButtonClearWalls'><a href="#">Clear Walls & Weights</a></li>
<li id='startButtonClearPath'><a href="#">Clear Path</a></li>
<li class="dropdown">
<a id="adjustSpeed" class="dropdown-toggle" data-toggle="dropdown"
href="#">Speed: Fast
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li id='adjustFast'><a href="#">Fast</a></li>
<li id='adjustAverage'><a href="#">Average</a></li>
<li id='adjustSlow'><a href="#">Slow</a></li>
</ul>
</li>
</ul>
</div>
</nav>
</div>
<div id="tutorial">
<h3>Welcome to Pathfinding Visualizer!</h3>
52
<h6>This short tutorial will walk you through all of the features of this
application.</h6>
<p>If you want to dive right in, feel free to press the "Skip Tutorial" button
below. Otherwise, press "Next"!</p>
<div id="tutorialCounter">1/9</div>
<img id="mainTutorialImage" src="public/styling/c_icon.png">
<button id="nextButton" class="btn btn-default navbar-btn"
type="button">Next</button>
<button id="previousButton" class="btn btn-default navbar-btn"
type="button">Previous</button>
<button id="skipButton" class="btn btn-default navbar-btn" type="button">Skip
Tutorial</button>
</div>
<div id='mainGrid'>
<div id='mainText'>
<ul>
<li>
<div class="start"></div>Start Node</li>
<li>
<div class="target"></div>Target Node</li>
<li id="bombLegend">
<div class="object"></div>Bomb Node</li>
<li id="weightLegend">
<div class="borderlessWeight"></div>Weight Node</li>
<li>
<div class="unvisited"></div>Unvisited Node</li>
<li>
<div class="visited"></div><div class="visitedobject"></div>Visited Nodes</li>
<li>
<div class="shortest-path"></div>Shortest-path Node</li>
<li>
<div class="wall"></div>Wall Node</li>
</ul>
</div>
<div id="algorithmDescriptor">Pick an algorithm and visualize it!</div>
<table id='board'/>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src='public/browser/bundle.js'></script>
</html>
53
Output:
Here are some examples of the results and sample output of pathfinding
algorithms:
1. Dijkstra's algorithm:
Given a weighted graph with vertices A, B, C, D, E, and F, and edges with
weights as follows:
AB = 6
AD = 1
AE = 4
BC = 3
BD = 2
CD = 1
CE = 8
DE = 2
DF = 7
EF = 5
54
To find the shortest path from A to F, Dijkstra's algorithm would give the
following output:
The shortest path from A to F would be A -> D -> E -> F with a distance of 8.
Code:
55
return "success!";
}
if (name === "astar" || name === "greedy") {
updateNeighbors(nodes, currentNode, boardArray, target, name, start, heuristic);
} else if (name === "dijkstra") {
updateNeighbors(nodes, currentNode, boardArray);
}
}
}
function averageNumberOfNodesBetween(currentNode) {
let num = 0;
while (currentNode.previousNode) {
num++;
currentNode = currentNode.previousNode;
}
return num;
}
56
if (actualTargetNode && name === "astar") {
if (heuristic === "manhattanDistance") {
distanceToCompare = currentNode.distance + targetNode.weight + distance[0] +
manhattanDistance(targetNode, actualTargetNode);
} else if (heuristic === "poweredManhattanDistance") {
distanceToCompare = currentNode.distance + targetNode.weight + distance[0] +
Math.pow(manhattanDistance(targetNode, actualTargetNode), 3);
} else if (heuristic === "extraPoweredManhattanDistance") {
distanceToCompare = currentNode.distance + targetNode.weight + distance[0] +
Math.pow(manhattanDistance(targetNode, actualTargetNode), 5);
}
let startNodeManhattanDistance = manhattanDistance(actualStartNode, actualTargetNode);
} else if (actualTargetNode && name === "greedy") {
distanceToCompare = targetNode.weight + distance[0] + manhattanDistance(targetNode,
actualTargetNode);
} else {
distanceToCompare = currentNode.distance + targetNode.weight + distance[0];
}
if (distanceToCompare < targetNode.distance) {
targetNode.distance = distanceToCompare;
targetNode.previousNode = currentNode.id;
targetNode.path = distance[1];
targetNode.direction = distance[2];
}
}
57
return neighbors;
}
58
return [3, ["r", "r", "f"], "right"];
} else if (nodeOne.direction === "down") {
return [2, ["l", "f"], "right"];
}
}
}
module.exports = test;
Output:
59
2. A* algorithm:
Given a grid with obstacles, start point (S), and target point (T):
S.....
.#.#..
...#..
.#...
....#T
Using the A* algorithm to find the shortest path from S to T would give the
following output:
Path found!
S -> (0, 1) -> (1, 2) -> (2, 3) -> (2, 2) -> (2, 1) -> (3, 0) -> (4, 1) -> (4, 2) -> (4,
3) -> (3, 4) -> T
.#..
..
*#**.
....#T
60
Code:
62
// let potentialWallTwo = `${x.toString()}-${(y - 1).toString()}`
// if (nodes[potentialNeighbor].status !== "wall" && !(nodes[potentialWallOne].status ===
"wall" && nodes[potentialWallTwo].status === "wall")) neighbors.push(potentialNeighbor);
// }
// if (boardArray[x + 1] && boardArray[x + 1][y - 1]) {
// potentialNeighbor = `${(x + 1).toString()}-${(y - 1).toString()}`
// let potentialWallOne = `${(x + 1).toString()}-${y.toString()}`
// let potentialWallTwo = `${x.toString()}-${(y - 1).toString()}`
// if (nodes[potentialNeighbor].status !== "wall" && !(nodes[potentialWallOne].status ===
"wall" && nodes[potentialWallTwo].status === "wall")) neighbors.push(potentialNeighbor);
// }
// if (boardArray[x - 1] && boardArray[x - 1][y + 1]) {
// potentialNeighbor = `${(x - 1).toString()}-${(y + 1).toString()}`
// let potentialWallOne = `${(x - 1).toString()}-${y.toString()}`
// let potentialWallTwo = `${x.toString()}-${(y + 1).toString()}`
// if (nodes[potentialNeighbor].status !== "wall" && !(nodes[potentialWallOne].status ===
"wall" && nodes[potentialWallTwo].status === "wall")) neighbors.push(potentialNeighbor);
// }
// if (boardArray[x + 1] && boardArray[x + 1][y + 1]) {
// potentialNeighbor = `${(x + 1).toString()}-${(y + 1).toString()}`
// let potentialWallOne = `${(x + 1).toString()}-${y.toString()}`
// let potentialWallTwo = `${x.toString()}-${(y + 1).toString()}`
// if (nodes[potentialNeighbor].status !== "wall" && !(nodes[potentialWallOne].status ===
"wall" && nodes[potentialWallTwo].status === "wall")) neighbors.push(potentialNeighbor);
// }
return neighbors;
}
63
return [2.5, null, "up"];
} else if (nodeOne.direction === "up-left") {
return [1.5, null, "up"];
} else if (nodeOne.direction === "down-left") {
return [2.5, null, "up"];
}
} else if (x2 > x1 && y1 === y2) {
if (nodeOne.direction === "up") {
return [3, ["r", "r", "f"], "down"];
} else if (nodeOne.direction === "right") {
return [2, ["r", "f"], "down"];
} else if (nodeOne.direction === "left") {
return [2, ["l", "f"], "down"];
} else if (nodeOne.direction === "down") {
return [1, ["f"], "down"];
} else if (nodeOne.direction === "up-right") {
return [2.5, null, "down"];
} else if (nodeOne.direction === "down-right") {
return [1.5, null, "down"];
} else if (nodeOne.direction === "up-left") {
return [2.5, null, "down"];
} else if (nodeOne.direction === "down-left") {
return [1.5, null, "down"];
}
}
if (y2 < y1 && x1 === x2) {
if (nodeOne.direction === "up") {
return [2, ["l", "f"], "left"];
} else if (nodeOne.direction === "right") {
return [3, ["l", "l", "f"], "left"];
} else if (nodeOne.direction === "left") {
return [1, ["f"], "left"];
} else if (nodeOne.direction === "down") {
return [2, ["r", "f"], "left"];
} else if (nodeOne.direction === "up-right") {
return [2.5, null, "left"];
} else if (nodeOne.direction === "down-right") {
return [2.5, null, "left"];
} else if (nodeOne.direction === "up-left") {
return [1.5, null, "left"];
} else if (nodeOne.direction === "down-left") {
return [1.5, null, "left"];
}
} else if (y2 > y1 && x1 === x2) {
if (nodeOne.direction === "up") {
return [2, ["r", "f"], "right"];
} else if (nodeOne.direction === "right") {
return [1, ["f"], "right"];
64
} else if (nodeOne.direction === "left") {
return [3, ["r", "r", "f"], "right"];
} else if (nodeOne.direction === "down") {
return [2, ["l", "f"], "right"];
} else if (nodeOne.direction === "up-right") {
return [1.5, null, "right"];
} else if (nodeOne.direction === "down-right") {
return [1.5, null, "right"];
} else if (nodeOne.direction === "up-left") {
return [2.5, null, "right"];
} else if (nodeOne.direction === "down-left") {
return [2.5, null, "right"];
}
} /*else if (x2 < x1 && y2 < y1) {
if (nodeOne.direction === "up") {
return [1.5, ["f"], "up-left"];
} else if (nodeOne.direction === "right") {
return [2.5, ["l", "f"], "up-left"];
} else if (nodeOne.direction === "left") {
return [1.5, ["r", "f"], "up-left"];
} else if (nodeOne.direction === "down") {
return [2.5, ["r", "r", "f"], "up-left"];
} else if (nodeOne.direction === "up-right") {
return [2, null, "up-left"];
} else if (nodeOne.direction === "down-right") {
return [3, null, "up-left"];
} else if (nodeOne.direction === "up-left") {
return [1, null, "up-left"];
} else if (nodeOne.direction === "down-left") {
return [2, null, "up-left"];
}
} else if (x2 < x1 && y2 > y1) {
if (nodeOne.direction === "up") {
return [1.5, ["f"], "up-right"];
} else if (nodeOne.direction === "right") {
return [1.5, ["l", "f"], "up-right"];
} else if (nodeOne.direction === "left") {
return [2.5, ["r", "f"], "up-right"];
} else if (nodeOne.direction === "down") {
return [2.5, ["r", "r", "f"], "up-right"];
} else if (nodeOne.direction === "up-right") {
return [1, null, "up-right"];
} else if (nodeOne.direction === "down-right") {
return [2, null, "up-right"];
} else if (nodeOne.direction === "up-left") {
return [2, null, "up-right"];
} else if (nodeOne.direction === "down-left") {
return [3, null, "up-right"];
65
}
} else if (x2 > x1 && y2 > y1) {
if (nodeOne.direction === "up") {
return [2.5, ["f"], "down-right"];
} else if (nodeOne.direction === "right") {
return [1.5, ["l", "f"], "down-right"];
} else if (nodeOne.direction === "left") {
return [2.5, ["r", "f"], "down-right"];
} else if (nodeOne.direction === "down") {
return [1.5, ["r", "r", "f"], "down-right"];
} else if (nodeOne.direction === "up-right") {
return [2, null, "down-right"];
} else if (nodeOne.direction === "down-right") {
return [1, null, "down-right"];
} else if (nodeOne.direction === "up-left") {
return [3, null, "down-right"];
} else if (nodeOne.direction === "down-left") {
return [2, null, "down-right"];
}
} else if (x2 > x1 && y2 < y1) {
if (nodeOne.direction === "up") {
return [2.5, ["f"], "down-left"];
} else if (nodeOne.direction === "right") {
return [2.5, ["l", "f"], "down-left"];
} else if (nodeOne.direction === "left") {
return [1.5, ["r", "f"], "down-left"];
} else if (nodeOne.direction === "down") {
return [1.5, ["r", "r", "f"], "down-left"];
} else if (nodeOne.direction === "up-right") {
return [3, null, "down-left"];
} else if (nodeOne.direction === "down-right") {
return [2, null, "down-left"];
} else if (nodeOne.direction === "up-left") {
return [2, null, "down-left"];
} else if (nodeOne.direction === "down-left") {
return [1, null, "down-left"];
}
}*/
}
66
let xChange = Math.abs(xOne - xTwo);
let yChange = Math.abs(yOne - yTwo);
module.exports = astar;
Output:
67
Using BFS algorithm to find the shortest path from A to F would give the
following output:
Path found!
A -> C -> F
Code:
function averageNumberOfNodesBetween(currentNode) {
let num = 0;
while (currentNode.previousNode) {
num++;
currentNode = currentNode.previousNode;
}
return num;
}
69
let distance = getDistance(currentNode, targetNode);
let distanceToCompare;
if (actualTargetNode && name === "CLA") {
let weight = targetNode.weight === 15 ? 15 : 1;
if (heuristic === "manhattanDistance") {
distanceToCompare = currentNode.distance + (distance[0] + weight) *
manhattanDistance(targetNode, actualTargetNode);
} else if (heuristic === "poweredManhattanDistance") {
distanceToCompare = currentNode.distance + targetNode.weight + distance[0] +
Math.pow(manhattanDistance(targetNode, actualTargetNode), 2);
} else if (heuristic === "extraPoweredManhattanDistance") {
distanceToCompare = currentNode.distance + (distance[0] + weight) *
Math.pow(manhattanDistance(targetNode, actualTargetNode), 7);
}
let startNodeManhattanDistance = manhattanDistance(actualStartNode, actualTargetNode);
} else if (actualTargetNode && name === "greedy") {
distanceToCompare = targetNode.weight + distance[0] + manhattanDistance(targetNode,
actualTargetNode);
} else {
distanceToCompare = currentNode.distance + targetNode.weight + distance[0];
}
if (distanceToCompare < targetNode.distance) {
targetNode.distance = distanceToCompare;
targetNode.previousNode = currentNode.id;
targetNode.path = distance[1];
targetNode.direction = distance[2];
}
}
70
potentialNeighbor = `${x.toString()}-${(y + 1).toString()}`
if (nodes[potentialNeighbor].status !== "wall") neighbors.push(potentialNeighbor);
}
return neighbors;
}
71
} else if (nodeOne.direction === "right") {
return [1, ["f"], "right"];
} else if (nodeOne.direction === "left") {
return [3, ["r", "r", "f"], "right"];
} else if (nodeOne.direction === "down") {
return [2, ["l", "f"], "right"];
}
}
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
for (let currenty = nodeOneCoordinates[1]; currenty <= nodeTwoCoordinates[1]; currenty++)
{
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
72
}
for (let currentx = nodeOneCoordinates[0]; currentx <= nodeTwoCoordinates[0]; currentx++)
{
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
for (let currenty = nodeOneCoordinates[1]; currenty >= nodeTwoCoordinates[1]; currenty--)
{
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
for (let currentx = nodeOneCoordinates[0]; currentx <= nodeTwoCoordinates[0]; currentx++)
{
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
73
if (additionalxChange + additionalyChange < otherAdditionalxChange +
otherAdditionalyChange) {
xChange += additionalxChange;
yChange += additionalyChange;
} else {
xChange += otherAdditionalxChange;
yChange += otherAdditionalyChange;
}
} else if (nodeOneCoordinates[0] >= nodeTwoCoordinates[0] && nodeOneCoordinates[1] <
nodeTwoCoordinates[1]) {
let additionalxChange = 0,
additionalyChange = 0;
for (let currentx = nodeOneCoordinates[0]; currentx >= nodeTwoCoordinates[0]; currentx--)
{
let currentId = `${currentx}-${nodeOne.id.split("-")[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
for (let currenty = nodeOneCoordinates[1]; currenty <= nodeTwoCoordinates[1]; currenty++)
{
let currentId = `${nodeTwoCoordinates[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
for (let currenty = nodeOneCoordinates[1]; currenty <= nodeTwoCoordinates[1]; currenty++)
{
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
for (let currentx = nodeOneCoordinates[0]; currentx >= nodeTwoCoordinates[0]; currentx--)
{
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
74
} else if (nodeOneCoordinates[0] >= nodeTwoCoordinates[0] && nodeOneCoordinates[1] >=
nodeTwoCoordinates[1]) {
let additionalxChange = 0,
additionalyChange = 0;
for (let currentx = nodeOneCoordinates[0]; currentx >= nodeTwoCoordinates[0]; currentx--
) {
let currentId = `${currentx}-${nodeOne.id.split("-")[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
for (let currenty = nodeOneCoordinates[1]; currenty >= nodeTwoCoordinates[1]; currenty--
) {
let currentId = `${nodeTwoCoordinates[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
for (let currenty = nodeOneCoordinates[1]; currenty >= nodeTwoCoordinates[1]; currenty--
) {
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
for (let currentx = nodeOneCoordinates[0]; currentx >= nodeTwoCoordinates[0]; currentx--
) {
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
module.exports = weightedSearchAlgorithm;
75
Output:
Using DFS algorithm to find the path from A to F would give the following
output:
Path found!
A -> B -> D -> C -> F
76
The path would look like this:
A --- C --- F
\/
B --- D ---
|
E
Code:
function unweightedSearchAlgorithm(nodes, start, target, nodesToAnimate, boardArray, name) {
if (!start || !target || start === target) {
return false;
}
let structure = [nodes[start]];
let exploredNodes = {start: true};
while (structure.length) {
let currentNode = name === "bfs" ? structure.shift() : structure.pop();
nodesToAnimate.push(currentNode);
if (name === "dfs") exploredNodes[currentNode.id] = true;
currentNode.status = "visited";
if (currentNode.id === target) {
return "success";
}
let currentNeighbors = getNeighbors(currentNode.id, nodes, boardArray, name);
currentNeighbors.forEach(neighbor => {
if (!exploredNodes[neighbor]) {
if (name === "bfs") exploredNodes[neighbor] = true;
nodes[neighbor].previousNode = currentNode.id;
structure.push(nodes[neighbor]);
}
});
}
return false;
}
module.exports = unweightedSearchAlgorithm;
78
Output:
Path found!
A -> C -> F
79
The path would look like this:
A --- C --- F
\/
B --- D ---
|
E
Code:
const astar = require("./astar");
81
}
82
let x = parseInt(coordinates[0]);
let y = parseInt(coordinates[1]);
let neighbors = [];
let potentialNeighbor;
if (boardArray[x - 1] && boardArray[x - 1][y]) {
potentialNeighbor = `${(x - 1).toString()}-${y.toString()}`
if (nodes[potentialNeighbor].status !== "wall") neighbors.push(potentialNeighbor);
}
if (boardArray[x + 1] && boardArray[x + 1][y]) {
potentialNeighbor = `${(x + 1).toString()}-${y.toString()}`
if (nodes[potentialNeighbor].status !== "wall") neighbors.push(potentialNeighbor);
}
if (boardArray[x][y - 1]) {
potentialNeighbor = `${x.toString()}-${(y - 1).toString()}`
if (nodes[potentialNeighbor].status !== "wall") neighbors.push(potentialNeighbor);
}
if (boardArray[x][y + 1]) {
potentialNeighbor = `${x.toString()}-${(y + 1).toString()}`
if (nodes[potentialNeighbor].status !== "wall") neighbors.push(potentialNeighbor);
}
return neighbors;
}
83
return [1, ["f"], "down"];
}
}
if (y2 < y1) {
if (nodeOne.direction === "up") {
return [2, ["l", "f"], "left"];
} else if (nodeOne.direction === "right") {
return [3, ["l", "l", "f"], "left"];
} else if (nodeOne.direction === "left") {
return [1, ["f"], "left"];
} else if (nodeOne.direction === "down") {
return [2, ["r", "f"], "left"];
}
} else if (y2 > y1) {
if (nodeOne.direction === "up") {
return [2, ["r", "f"], "right"];
} else if (nodeOne.direction === "right") {
return [1, ["f"], "right"];
} else if (nodeOne.direction === "left") {
return [3, ["r", "r", "f"], "right"];
} else if (nodeOne.direction === "down") {
return [2, ["l", "f"], "right"];
}
}
}
84
} else if (nodeOne.otherdirection === "left") {
return [2, ["l", "f"], "down"];
} else if (nodeOne.otherdirection === "down") {
return [1, ["f"], "down"];
}
}
if (y2 < y1) {
if (nodeOne.otherdirection === "up") {
return [2, ["l", "f"], "left"];
} else if (nodeOne.otherdirection === "right") {
return [3, ["l", "l", "f"], "left"];
} else if (nodeOne.otherdirection === "left") {
return [1, ["f"], "left"];
} else if (nodeOne.otherdirection === "down") {
return [2, ["r", "f"], "left"];
}
} else if (y2 > y1) {
if (nodeOne.otherdirection === "up") {
return [2, ["r", "f"], "right"];
} else if (nodeOne.otherdirection === "right") {
return [1, ["f"], "right"];
} else if (nodeOne.otherdirection === "left") {
return [3, ["r", "r", "f"], "right"];
} else if (nodeOne.otherdirection === "down") {
return [2, ["l", "f"], "right"];
}
}
}
let additionalxChange = 0,
additionalyChange = 0;
85
for (let currentx = nodeOneCoordinates[0]; currentx <= nodeTwoCoordinates[0]; currentx++)
{
let currentId = `${currentx}-${nodeOne.id.split("-")[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
for (let currenty = nodeOneCoordinates[1]; currenty <= nodeTwoCoordinates[1]; currenty++)
{
let currentId = `${nodeTwoCoordinates[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
for (let currenty = nodeOneCoordinates[1]; currenty <= nodeTwoCoordinates[1]; currenty++)
{
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
for (let currentx = nodeOneCoordinates[0]; currentx <= nodeTwoCoordinates[0]; currentx++)
{
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
86
let currentId = `${nodeTwoCoordinates[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
for (let currenty = nodeOneCoordinates[1]; currenty >= nodeTwoCoordinates[1]; currenty--)
{
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
for (let currentx = nodeOneCoordinates[0]; currentx <= nodeTwoCoordinates[0]; currentx++)
{
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
87
for (let currenty = nodeOneCoordinates[1]; currenty <= nodeTwoCoordinates[1]; currenty++)
{
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
for (let currentx = nodeOneCoordinates[0]; currentx >= nodeTwoCoordinates[0]; currentx--)
{
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
let otherAdditionalxChange = 0,
otherAdditionalyChange = 0;
for (let currenty = nodeOneCoordinates[1]; currenty >= nodeTwoCoordinates[1]; currenty--
) {
let currentId = `${nodeOne.id.split("-")[0]}-${currenty}`;
let currentNode = nodes[currentId];
additionalyChange += currentNode.weight;
}
for (let currentx = nodeOneCoordinates[0]; currentx >= nodeTwoCoordinates[0]; currentx--
) {
88
let currentId = `${currentx}-${nodeTwoCoordinates[1]}`;
let currentNode = nodes[currentId];
additionalxChange += currentNode.weight;
}
module.exports = bidirectional;
Output:
89
Sorting Algorithms:
There are several sorting algorithms, each with their own strengths and
weaknesses. Below are some examples of sorting algorithms along with a step-
by-step example of how they work and what their output might look like.
1. Bubble Sort:
Bubble Sort is a simple sorting algorithm that repeatedly steps through the
list, compares adjacent elements and swaps them if they are in the wrong
order.
Example:
Consider an unsorted list of numbers: [6, 3, 9, 1, 5]
Step 1: Compare the first two elements of the list, 6 and 3. Since 6 is greater
than 3, swap them. List becomes [3, 6, 9, 1, 5].
Step 2: Compare the next two elements of the list, 6 and 9. Since they are in
the correct order, no swap is needed. List remains [3, 6, 9, 1, 5].
Step 3: Compare the next two elements of the list, 9 and 1. Since 9 is greater
than 1, swap them. List becomes [3, 6, 1, 9, 5].
Step 4: Compare the next two elements of the list, 9 and 5. Since 9 is greater
than 5, swap them. List becomes [3, 6, 1, 5, 9].
Step 5: The last two elements of the list, 5 and 9, are in the correct order. The
algorithm has completed one pass through the list.
Step 6: Repeat the previous steps until no swaps are needed.
Output:
The sorted list is [1, 3, 5, 6, 9].
90
Code:
import { setArray } from "../reducers/array";
import { setCurrentBubbleTwo } from "../reducers/bubbleSort";
import { setCurrentSwappers } from "../reducers/swappers";
import { setCurrentSorted } from "../reducers/sorted";
import { setRunning } from "../reducers/running";
91
setCurrentSorted : setCurrentBubbleTwo;
dispatch(dispatchFunction(toDispatch.shift()));
setTimeout(() => {
handleDispatch(toDispatch, dispatch, array, speed);
}, speed);
}
Output:
2. Merge Sort:
Merge Sort is a divide and conquer algorithm that divides the unsorted list
into n sublists, each containing one element, and then repeatedly merges
sublists to produce new sorted sublists until there is only one sublist
remaining.
Example:
Consider an unsorted list of numbers: [6, 3, 9, 1, 5]
92
Step 1: Divide the list into two sublists of roughly equal size: [6, 3, 9] and [1,
5].
Step 2: Recursively divide the sublists until each sublist contains only one
element.
Step 3: Merge the sublists by comparing the first element of each sublist and
adding the smaller element to the new list. List becomes [1, 5, 3, 6, 9].
Step 4: Repeat the previous step until all sublists have been merged into one
sorted list.
Output:
The sorted list is [1, 3, 5, 6, 9].
Code:
import { setArray } from "../reducers/array";
import { setCurrentMergeX } from "../reducers/mergeSort";
import { setCurrentSwappers } from "../reducers/swappers";
import { setCurrentSorted } from "../reducers/sorted";
import { setRunning } from "../reducers/running";
93
return actualSort(actualFirst, actualSecond, toDispatch, obj, start, end, isFinalMerge);
}
94
if (dispatchFunction === setArray) {
let currentToDispatch = toDispatch.shift();
dispatch(dispatchFunction(currentToDispatch.slice(0, currentToDispatch.length - 2)));
dispatch(setCurrentSwappers([]));
dispatch(setCurrentMergeX([]));
dispatch(setCurrentSwappers([currentToDispatch[currentToDispatch.length - 2],
currentToDispatch[currentToDispatch.length - 1]]));
dispatch(setCurrentMergeX([currentToDispatch[currentToDispatch.length - 2],
currentToDispatch[currentToDispatch.length - 1]]));
} else {
dispatch(dispatchFunction(toDispatch.shift()));
}
setTimeout(() => {
handleDispatch(toDispatch, dispatch, array, speed);
}, speed);
}
Output:
95
3. Quick Sort:
Quick Sort is a divide and conquer algorithm that selects a pivot element and
partitions the array around the pivot, such that elements less than the pivot
are moved to the left of the pivot and elements greater than the pivot are
moved to the right of the pivot. The algorithm then recursively sorts the
subarrays on either side of the pivot.
Example:
Consider an unsorted list of numbers: [6, 3, 9, 1, 5]
Step 1: Select a pivot element. For this example, we will use the first element,
6.
Step 2: Partition the array around the pivot by moving all elements less than
the pivot to the left and all elements greater than the pivot to the right. List
becomes [3, 1, 5, 6, 9].
Step 3: Recursively sort the subarrays on either side of the pivot. For the left
subarray [3, 1, 5], select the pivot element 3 and repeat the previous steps. The
left subarray becomes [1, 3, 5]. For the right subarray [9], there is only one
element and it is already sorted.
Step 4: Merge the sorted subarrays into one final sorted array.
Output:
The sorted list is [1, 3, 5, 6, 9].
Note: These examples show the steps and output for sorting an array of
integers. However, sorting algorithms can be used to sort other types of data
structures as well, such as strings, floats, or objects, depending on the
implementation.
96
Code:
import { setArray } from "../reducers/array";
import { setCurrentQuickTwo, setPivot } from "../reducers/quickSort";
import { setCurrentSwappers } from "../reducers/swappers";
import { setCurrentSorted } from "../reducers/sorted";
import { setRunning } from "../reducers/running";
97
toDispatch.push([pivot, right, true]);
toDispatch.push(array.slice(0));
toDispatch.push([]);
toDispatch.push([true, right]);
}
quickSortHelper(array, start, right - 1, toDispatch);
quickSortHelper(array, right + 1, end, toDispatch);
}
98
Output:
4. Heap Sort:
Heap Sort is a comparison-based sorting algorithm that works by first creating
a max heap from the unsorted list, then repeatedly extracting the maximum
element and swapping it with the last element in the heap until the heap is
empty.
Example:
Consider an unsorted list of numbers: [6, 3, 9, 1, 5]
Step 1: Build a max heap from the unsorted list. List becomes [9, 6, 3, 1, 5].
Step 2: Swap the first element (the maximum element) with the last element
in the heap. List becomes [5, 6, 3, 1, 9].
Step 3: Discard the last element (which is now sorted) and re-heapify the
remaining elements to maintain the max heap property. List becomes [6, 5, 3,
1].
Step 4: Repeat the previous steps until the heap is empty.
99
Output:
The sorted list is [1, 3, 5, 6, 9].
Code:
import { setArray } from "../reducers/array";
import { setCurrentHeapThree } from "../reducers/heapSort";
import { setCurrentSwappers } from "../reducers/swappers";
import { setCurrentSorted } from "../reducers/sorted";
import { setRunning } from "../reducers/running";
101
Output:
102
8. Conclusion
Sorting algorithms, such as bubble sort and quicksort, are used to sort a list of
items in ascending or descending order. Algorithm visualizers can be used to
help users understand how these algorithms work by displaying the unsorted
list and highlighting the comparisons and swaps that are made during the
execution of the algorithm. This can help users to gain a deeper understanding
of the algorithm and to identify any potential issues or limitations, such as
worst-case time complexity.
103
Furthermore, algorithm visualizers can be customized to suit different
learning styles and levels of experience. For example, some visualizers may
provide detailed explanations of each step of the algorithm, while others may
allow users to interact with the algorithm and make modifications to the input
or parameters.
104
Appendix
Code:
Pathfinding Visualizer:
<html>
<head>
<title>Pathfinding Visualizer</title>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link id="cssTheme" rel="stylesheet" href="public/styling/cssBasic.css"/>
<link rel="shortcut icon" type="image/png" href="public/styling/c_icon.png"/>
</head>
<body>
<div id='navbarDiv'>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
<a id="refreshButton" class="navbar-brand" href="#">Pathfinding Visualizer</a>
</div>
<ul class="nav navbar-nav">
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Algorithms
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li id='startButtonDijkstra'><a href="#">Dijkstra's Algorithm</a></li>
<li id='startButtonAStar2'><a href="#">A* Search</a></li>
<li id='startButtonGreedy'><a href="#">Greedy Best-first Search</a></li>
<li id='startButtonAStar'><a href="#">Swarm Algorithm</a></li>
<li id='startButtonAStar3'><a href="#">Convergent Swarm Algorithm</a></li>
<li id='startButtonBidirectional'><a href="#">Bidirectional Swarm
Algorithm</a></li>
<li id='startButtonBFS'><a href="#">Breadth-first Search</a></li>
<li id='startButtonDFS'><a href="#">Depth-first Search</a></li>
</ul>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Mazes & Patterns
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li id='startButtonCreateMazeTwo'><a href="#">Recursive Division</a></li>
<li id='startButtonCreateMazeThree'><a href="#">Recursive Division (vertical
skew)</a></li>
105
<li id='startButtonCreateMazeFour'><a href="#">Recursive Division (horizontal
skew)</a></li>
<li id='startButtonCreateMazeOne'><a href="#">Basic Random Maze</a></li>
<li id='startButtonCreateMazeWeights'><a href="#">Basic Weight Maze</a></li>
<li id='startStairDemonstration'><a href="#">Simple Stair Pattern</a></li>
</ul>
</li>
<li id='startButtonAddObject'><a href="#">Add Bomb</a></li>
<li id='startButtonStart'><button id="actualStartButton" class="btn btn-default
navbar-btn" type="button">Visualize!</button></li>
<li id='startButtonClearBoard'><a href="#">Clear Board</a></li>
<li id='startButtonClearWalls'><a href="#">Clear Walls & Weights</a></li>
<li id='startButtonClearPath'><a href="#">Clear Path</a></li>
<li class="dropdown">
<a id="adjustSpeed" class="dropdown-toggle" data-toggle="dropdown"
href="#">Speed: Fast
<span class="caret"></span></a>
<ul class="dropdown-menu">
<li id='adjustFast'><a href="#">Fast</a></li>
<li id='adjustAverage'><a href="#">Average</a></li>
<li id='adjustSlow'><a href="#">Slow</a></li>
</ul>
</li>
</ul>
</div>
</nav>
</div>
<div id="tutorial">
<h3>Welcome to Pathfinding Visualizer!</h3>
<h6>This short tutorial will walk you through all of the features of this
application.</h6>
<p>If you want to dive right in, feel free to press the "Skip Tutorial" button below.
Otherwise, press "Next"!</p>
<div id="tutorialCounter">1/9</div>
<img id="mainTutorialImage" src="public/styling/c_icon.png">
<button id="nextButton" class="btn btn-default navbar-btn" type="button">Next</button>
<button id="previousButton" class="btn btn-default navbar-btn"
type="button">Previous</button>
<button id="skipButton" class="btn btn-default navbar-btn" type="button">Skip
Tutorial</button>
</div>
<div id='mainGrid'>
<div id='mainText'>
<ul>
<li>
<div class="start"></div>Start Node</li>
<li>
<div class="target"></div>Target Node</li>
106
<li id="bombLegend">
<div class="object"></div>Bomb Node</li>
<li id="weightLegend">
<div class="borderlessWeight"></div>Weight Node</li>
<li>
<div class="unvisited"></div>Unvisited Node</li>
<li>
<div class="visited"></div><div class="visitedobject"></div>Visited Nodes</li>
<li>
<div class="shortest-path"></div>Shortest-path Node</li>
<li>
<div class="wall"></div>Wall Node</li>
</ul>
</div>
<div id="algorithmDescriptor">Pick an algorithm and visualize it!</div>
<table id='board'/>
</div>
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src='public/browser/bundle.js'></script>
</html>
Sorting Visualizer:
<html>
<head>
<meta charset="utf-8">
<title>Sorting Visualizer</title>
<link rel="shortcut icon" type="image/ico" href="client/styling/icon.ico"/>
</head>
<body>
<div id="app" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="client/public/bundle.js" type="text/javascript"></script>
</body>
</html>
107
References
https://github.com/clementmihailescu/Sorting-Visualizer-Tutorial)
https://github.com/clementmihailescu/Pathfinding-Visualizer-Tutorial )
and Science
(https://www.irjmets.com/uploadedfiles/paper/volume3/issue_3_march_2021/6743/16
28083287.pdf)
ChatGPT (https://chat.openai.com/c/3da29522-95f6-47e5-9e47-77fc1be2f6d7)
(https://www.crio.do/projects/javascript-sorting-visualiser/)
Github (https://algorithm-visualizer.org/)
108