📜  使用JavaScript快速排序(Hoare分区)可视化(1)

📅  最后修改于: 2023-12-03 14:49:48.353000             🧑  作者: Mango

使用JavaScript快速排序(Hoare分区)可视化

快速排序是一种快速、高效的排序算法,常用于大量数据的排序场景中。Hoare分区是快速排序算法的核心思想之一,它实现了将数组划分为两部分的操作,以此实现快速排序。

在本文中,我们将介绍如何使用JavaScript编写Hoare分区的快速排序算法,并通过可视化的方法展示它的执行过程。

快速排序算法

快速排序算法的基本思路是选择一个支点(pivot),将数组分成两个部分,其中左边的部分元素值均小于支点,右边的部分元素值均大于支点。然后再对左右两边的数组递归地进行同样的操作,直到数组长度为1。

Hoare分区是一种同时从左右两边遍历数组的分区方式,它的核心思想是将数组分成两部分时不进行数据交换,而是通过左右指针的移动实现。

JavaScript代码实现

下面是使用JavaScript实现Hoare分区的快速排序算法的代码:

function quickSort(items, left, right) {
    var index;
    if (items.length > 1) {
        index = hoarePartition(items, left, right);
        if (left < index - 1) {
            quickSort(items, left, index - 1);
        }
        if (index < right) {
            quickSort(items, index, right);
        }
    }
    return items;
}
function hoarePartition(items, left, right) {
    var pivot = items[Math.floor((right + left) / 2)],
        i = left,
        j = right;
    while (i <= j) {
        while (items[i] < pivot) {
            i++;
        }
        while (items[j] > pivot) {
            j--;
        }
        if (i <= j) {
            swap(items, i, j);
            i++;
            j--;
        }
    }
    return i;
}
function swap(items, leftIndex, rightIndex) {
    var temp = items[leftIndex];
    items[leftIndex] = items[rightIndex];
    items[rightIndex] = temp;
}

函数quickSort是快速排序算法的主函数,它接受三个参数:待排序的数组、数组的左侧索引和右侧索引。在quickSort函数中,我们首先选择数组中的支点,然后通过hoarePartition函数对数组进行划分,最后对划分后的左右两部分递归调用quickSort函数,直到数组长度为1。

函数hoarePartition是Hoare分区的核心函数,它接受三个参数:待分区的数组、数组的左侧索引和右侧索引。在hoarePartition函数中,我们以支点的值为界限,从数组两端同时开始遍历,如果发现左侧元素大于支点,右侧元素小于支点,则交换这两个元素的位置,重复这个过程直到左右两端都结束遍历。

函数swap是用来交换数组中两个元素的位置的。

可视化展示

为了让读者更好地理解快速排序算法的执行过程,我们可以通过可视化的方式展示它的执行过程。下面是使用JavaScript和HTML/CSS实现的一个简单的快速排序算法的可视化示例:

<!DOCTYPE html>
<html>
<head>
    <title>Quick Sort Visualization</title>
    <style type="text/css">
        #container {
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        .bar {
            height: 30px;
            margin: 0 1px;
            background-color: gray;
            transition: height 0.2s;
        }
    </style>
</head>
<body>
    <button onclick="startVisualization()">Start Visualization</button>
    <button onclick="reset()">Reset</button>
    <div id="container"></div>
    <script type="text/javascript">
        var numbers = [];
        var barContainer = document.getElementById("container");
        var bars = [];
        var delay = 100;

        function startVisualization() {
            reset();
            var input = document.createElement("input");
            var sortButton = document.createElement("button");
            input.type = "number";
            input.value = 20;
            sortButton.textContent = "Sort";
            sortButton.onclick = function() {
                var count = parseInt(input.value);
                generateRandomNumbers(count);
                drawBars();
                quickSort(numbers, 0, numbers.length - 1);
            };
            barContainer.insertBefore(input, barContainer.firstChild);
            barContainer.insertBefore(sortButton, barContainer.firstChild);
        }

        function reset() {
            numbers = [];
            barContainer.innerHTML = "";
            bars = [];
        }

        function generateRandomNumbers(count) {
            numbers = [];
            for (var i = 0; i < count; i++) {
                numbers.push(Math.round(Math.random() * 100));
            }
        }

        function drawBars() {
            for (var i = 0; i < numbers.length; i++) {
                var bar = document.createElement("div");
                bar.className = "bar";
                bar.style.width = (100 / numbers.length) + "%";
                bar.style.height = (numbers[i] * 3) + "px";
                bars.push(bar);
                barContainer.appendChild(bar);
            }
        }

        function quickSort(items, left, right) {
            var index;
            if (items.length > 1) {
                index = hoarePartition(items, left, right);
                for (var i = 0; i < items.length; i++) {
                    bars[i].style.height = (items[i] * 3) + "px";
                    bars[i].style.backgroundColor = "gray";
                }
                setTimeout(function() {
                    bars[index].style.backgroundColor = "green";
                    if (left < index - 1) {
                        quickSort(items, left, index - 1);
                    }
                    if (index < right) {
                        quickSort(items, index, right);
                    }
                }, delay);
            }
            return items;
        }

        function hoarePartition(items, left, right) {
            var pivot = items[Math.floor((right + left) / 2)],
                i = left,
                j = right;
            while (i <= j) {
                while (items[i] < pivot) {
                    i++;
                }
                while (items[j] > pivot) {
                    j--;
                }
                if (i <= j) {
                    swap(items, i, j);
                    swapBars(i, j);
                    i++;
                    j--;
                }
            }
            return i;
        }

        function swap(items, leftIndex, rightIndex) {
            var temp = items[leftIndex];
            items[leftIndex] = items[rightIndex];
            items[rightIndex] = temp;
        }

        function swapBars(leftIndex, rightIndex) {
            var temp = bars[leftIndex].style.height;
            bars[leftIndex].style.height = bars[rightIndex].style.height;
            bars[leftIndex].style.backgroundColor = "red";
            bars[rightIndex].style.height = temp;
            bars[rightIndex].style.backgroundColor = "red";
        }
    </script>
</body>
</html>

我们首先在页面中添加了两个按钮:一个用来开始可视化,一个用来重置可视化。在点击开始可视化按钮时,会动态添加一个输入框和一个排序按钮,用来输入数组长度和开始排序。

quickSort函数中,我们在每次进行Hoare分区操作前,将当前数组的元素值和可视化元素的高度进行同步。然后,我们使用setTimeout函数来模拟算法的执行过程,以便让用户能够观察到算法的过程。

swapBars函数中,我们用来交换可视化元素的高度和背景色。

为了更好地演示算法的过程,我们将可视化元素的背景色设置为灰色,当某个元素从数组中被选中时,将其背景色变为绿色,当其位置确定后,将其背景色变为红色。

结论

在本文中,我们介绍了如何使用JavaScript编写Hoare分区的快速排序算法,并通过可视化的方式展示了它的执行过程。这种方法可以帮助读者更好地理解算法的思想、实现和执行过程。希望读者能够在日常开发中运用这种算法,提高程序的效率。