快速排序(Quick Sort)是一种高效的排序算法,采用分治法(Divide and Conquer)策略来对数组进行排序。它的核心思想是通过一趟排序将待排序的数组分成两部分,其中一部分的所有元素比另一部分的所有元素都要小,然后递归地对这两部分分别进行快速排序,直到整个序列有序。
假设我们要对以下数组进行快速排序:
[3, 6, 8, 10, 1, 2, 1]
步骤如下:
3 作为基准。3 小的元素在其左边,比 3 大的元素在其右边。结果可能是 [1, 2, 1, 3, 6, 8, 10]。[1, 2, 1] 和 [6, 8, 10] 分别进行快速排序。[1, 2, 1] 选择 1 作为基准,重新排列得到 [1, 1, 2]。[6, 8, 10] 选择 6 作为基准,重新排列得到 [6, 8, 10]。[1, 1, 2, 3, 6, 8, 10]。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quick Sort Visualization</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
}
h2 {
color: #333;
margin-bottom: 20px;
}
#array-container {
display: flex;
justify-content: center;
align-items: flex-end;
height: 300px;
margin-bottom: 20px;
border: 1px solid #ccc;
background-color: #fff;
padding: 30px;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.array-bar {
display: flex;
justify-content: center;
align-items: flex-end;
margin: 0 2px;
background-color: teal;
border-radius: 4px;
position: relative;
transition: height 0.3s;
}
.array-bar p {
margin: 0;
color: rgb(228, 28, 28);
font-weight: bold;
font-size: 14px;
position: absolute;
bottom: -20px;
}
button {
padding: 10px 20px;
font-size: 16px;
color: #fff;
background-color: teal;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #005f5f;
}
</style>
</head>
<body>
<h2>Quick Sort Visualization</h2>
<div id="array-container"></div>
<button onclick="quickSort(array, 0, array.length - 1)">Start Quick Sort</button>
<script>
// Initial Array
let array = [3, 6, 8, 10, 1, 2, 1];
const container = document.getElementById("array-container");
// Function to create bars for visualization
function createBars(array) {
container.innerHTML = '';
for (let i = 0; i < array.length; i++) {
const bar = document.createElement('div');
bar.className = 'array-bar';
bar.style.height = `${array[i] * 20}px`;
bar.style.width = '40px';
const number = document.createElement('p');
number.textContent = array[i];
bar.appendChild(number);
container.appendChild(bar);
}
}
// Quick Sort Implementation
async function quickSort(arr, low, high) {
if (low < high) {
let pi = await partition(arr, low, high);
await quickSort(arr, low, pi - 1);
await quickSort(arr, pi + 1, high);
}
createBars(arr);
}
async function partition(arr, low, high) {
let pivot = arr[high];
let i = low - 1;
for (let j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
[arr[i], arr[j]] = [arr[j], arr[i]];
createBars(arr);
await new Promise(resolve => setTimeout(resolve, 300));
}
}
[arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
createBars(arr);
await new Promise(resolve => setTimeout(resolve, 300));
return i + 1;
}
// Initialize bars
createBars(array);
</script>
</body>
</html>
async function quickSort(arr, low, high) {
if (low < high) {
let pi = await partition(arr, low, high);
await quickSort(arr, low, pi - 1);
await quickSort(arr, pi + 1, high);
}
createBars(arr);
}- `arr`: 需要排序的数组。
- `low`: 数组的起始索引(即子数组的第一个元素的索引)。
- `high`: 数组的结束索引(即子数组的最后一个元素的索引)。async function partition(arr, low, high) {
let pivot = arr[high];
let i = low - 1;
for (let j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
[arr[i], arr[j]] = [arr[j], arr[i]];
createBars(arr);
await new Promise(resolve => setTimeout(resolve, 300));
}
}
[arr[i + 1], arr[high]] = [arr[high], arr[i + 1]];
createBars(arr);
await new Promise(resolve => setTimeout(resolve, 300));
return i + 1;
}arr: 需要分区的数组。low: 子数组的起始索引。high: 子数组的结束索引。arr 按基准点 pivot 分成两个部分:左侧部分小于 pivot,右侧部分大于 pivot。let pivot = arr[high];:选择数组中最后一个元素作为基准点(pivot)。let i = low - 1;:i 指向的是比 pivot 小的元素的最后一个位置。for (let j = low; j < high; j++):遍历数组从 low 到 high-1 位置的所有元素。if (arr[j] < pivot):如果当前元素 arr[j] 小于 pivot,则将其与 i+1 位置的元素交换,并将 i 加 1。这样就能保证所有小于 pivot 的元素都移动到左侧。createBars(arr);:每次元素交换后,更新可视化条形图,显示当前排序状态。await new Promise(resolve => setTimeout(resolve, 300));:添加延迟效果,让可视化过程更清晰。return i + 1;:返回新的基准点索引,将其用于后续递归调用。function createBars(array) {
container.innerHTML = '';
for (let i = 0; i < array.length; i++) {
const bar = document.createElement('div');
bar.className = 'array-bar';
bar.style.height = `${array[i] * 20}px`;
bar.style.width = '40px';
const number = document.createElement('p');
number.textContent = array[i];
bar.appendChild(number);
container.appendChild(bar);
}
}container.innerHTML = '';:清空容器中的现有内容,为新条形图腾出空间。for (let i = 0; i < array.length; i++):遍历数组中的每个元素,为其创建一个条形图。const bar = document.createElement('div');:为数组中的每个元素创建一个 div 元素,用于表示条形图。bar.style.height =${arrayi * 20}px;:根据数组元素的值设置条形图的高度。const number = document.createElement('p');:创建一个 p 元素,用于显示条形图下方的数字。bar.appendChild(number);:将数字添加到条形图中。container.appendChild(bar);:将条形图添加到容器中,显示在页面上。通过这些函数的配合,快速排序算法能够不仅高效地对数组进行排序,还能实时地动态展示排序过程,使算法的执行过程更加直观。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。