JavaScript 归并排序可视化
图形用户界面(GUI) 有助于用户更好地理解程序。在本文中,我们将使用JavaScript对归并排序进行可视化。我们将看到数组在排序后是如何被分割和合并以得到最终排序好的数组的。
参考:
- 归并排序
- HTML中的画布(Canvas)
- JavaScript中的异步函数
方法:
- 首先,我们将使用Math.random()函数生成一个随机数组。
- 使用画布(canvas)的属性来创建矩形条和动画效果。
- 使用不同的颜色来表示哪些数组被分割和合并。
- 使用JavaScript的 mergeSort() 函数执行排序。
- 该算法执行操作非常快,因此使用 timeout() 函数来减慢过程。
未排序的列表:
排序列表:
index.html: 下面是可视化归并排序算法的程序。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0">
</head>
<body>
<h1 class="title" style = "color: green; font:lighter; ">
Merge Sort Visualizer using JS</h1>
<h2 class="title1" style = "background: green;
color: white; font: italic;">Array is not sorted
</h2>
<canvas id="Canvas"></canvas>
<script src="mergeSort.js"></script>
</body>
</html>
HTML
mergeSort.js :下面是上述HTML代码中使用的“mergeSort.js”文件的内容。
// Canvas variables
var canvas, canvaswidth, canvasheight, ctrl;
// Call canvasElements() to store height width
// in above canvas variables
canvasElements();
// 3 array are declared
//1) arr is for storing array element
//2) itmd for storing intermediate values
//3) visited is for element which has been sorted
var arr = [], itmd = [], visited = []
// Length of unsorted array
var len_of_arr = 40;
// Store random value in arr[]
for (var i = 0; i < len_of_arr; i++) {
arr.push(Math.round(Math.random() * 250) )
}
// Initialize itmd and visited array with 0
for (var i = 0; i < len_of_arr; i++) {
itmd.push(0)
visited.push(0)
}
// Merging of two sub array
// https://www.geeksforgeeks.org/merge-two-sorted-arrays/
function mergeArray(start, end) {
let mid = parseInt((start + end) >> 1);
let start1 = start, start2 = mid + 1
let end1 = mid, end2 = end
// Initial index of merged subarray
let index = start
while (start1 <= end1 && start2 <= end2) {
if (arr[start1] <= arr[start2]) {
itmd[index] = arr[start1]
index = index + 1
start1 = start1 + 1;
}
else if(arr[start1] > arr[start2]) {
itmd[index] = arr[start2]
index = index + 1
start2 = start2 + 1;
}
}
// Copy the remaining elements of
// arr[], if there are any
while (start1 <= end1) {
itmd[index] = arr[start1]
index = index + 1
start1 = start1 + 1;
}
while (start2 <= end2) {
itmd[index] = arr[start2]
index = index + 1
start2 = start2 + 1;
}
index = start
while (index <= end) {
arr[index] = itmd[index];
index++;
}
}
// Function for showing visualization
// effect
function drawBars(start, end) {
// Clear previous unsorted bars
ctrl.clearRect(0, 0, 1000, 1500)
// Styling of bars
for (let i = 0; i < len_of_arr; i++) {
// Changing styles of bars
ctrl.fillStyle = "black"
ctrl.shadowOffsetX = 2
ctrl.shadowColor = "chocolate";
ctrl.shadowBlur = 3;
ctrl.shadowOffsetY =5;
// Size of rectangle of bars
ctrl.fillRect(25 * i, 300 - arr[i], 20, arr[i])
if (visited[i]) {
ctrl.fillStyle = "#006d13"
ctrl.fillRect(25 * i, 300 - arr[i], 20, arr[i])
ctrl.shadowOffsetX = 2
}
}
for (let i = start; i <= end; i++) {
ctrl.fillStyle = "orange"
ctrl.fillRect(25 * i, 300 - arr[i], 18, arr[i])
ctrl.fillStyle = "#cdff6c"
ctrl.fillRect(25 * i,300, 18, arr[i])
visited[i] = 1
}
}
// Waiting interval between two bars
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Merge Sorting
const mergeSort = async (start, end) => {
if (start < end) {
let mid = parseInt((start + end) >> 1)
await mergeSort(start, mid)
await mergeSort(mid + 1, end)
await mergeArray(start, end)
await drawBars(start, end)
// Waiting time is 800ms
await timeout(800)
}
}
// canvasElements function for storing
// width and height in canvas variable
function canvasElements() {
canvas = document.getElementById("Canvas")
canvas.width = canvas.height = 1000
canvaswidth = canvas.width
canvasheight = canvas.height
ctrl = canvas.getContext("2d")
}
// Asynchronous MergeSort function
const performer = async () => {
await mergeSort(0, len_of_arr - 1)
await drawBars()
// Code for change title1 text
const title1_changer = document.querySelector(".title1")
title1_changer.innerText = "Array is completely sorted"
}
performer()
JavaScript