为啥这种方法不适用于通过反应可视化快速排序?

Posted

技术标签:

【中文标题】为啥这种方法不适用于通过反应可视化快速排序?【英文标题】:Why this approach is not working in visualizing quicksort with react?为什么这种方法不适用于通过反应可视化快速排序? 【发布时间】:2021-09-27 05:42:06 【问题描述】:

我正在制作一个排序可视化工具。使用绝对位置,我正在交换条形的变换。这种方法适用于 BubbleSort,但在 QuickSort 中会产生不需要的结果。下面是问题的详细解释。

const PIVOT_COLOR = '#FF4949';
const SORTED_COLOR = '#CB6BF9';

async function pivot(blocks, start = 0, end = blocks.length + 1) 
    let pivot = Number(blocks[start].childNodes[0].innerhtml);
    let swapIdx = start;
    let value;

    blocks[start].childNodes[1].style.backgroundColor = PIVOT_COLOR;

    for (let i = start + 1; i < blocks.length; i++) 
        value = Number(blocks[i].childNodes[0].innerHTML);

        blocks[i].childNodes[1].style.backgroundColor = 'blue';

        await new Promise((resolve) =>
            setTimeout(() => 
                resolve();
            , 500)
        );

        if (pivot > value) 
            swapIdx++;

            let arr = [];
            blocks.forEach(el => arr.push(el.childNodes[0].innerHTML));
            console.log(arr);

            //swap(arr, swapIdx, i);
            await swap(blocks[swapIdx], blocks[i]);
        

        blocks[i].childNodes[1].style.backgroundColor = SORTED_COLOR;
    

    await swap(blocks[start], blocks[swapIdx]);
    console.log(swapIdx)
    blocks[start].childNodes[1].style.backgroundColor = SORTED_COLOR;
    return swapIdx;


export async function QuickSort(blocks, left = 0, right = blocks.length - 1) 
    if (left < right) 
        let pivotIndex = await pivot(blocks, left, right);
        //left
        await QuickSort(blocks, left, pivotIndex - 1);
        //right
        await QuickSort(blocks, pivotIndex + 1, right);
    


function swap(el1, el2) 
    let wrapper = document.getElementById('wrapper')
    let container = wrapper.childNodes[0];
    return new Promise((resolve) => 
        var temp = el1.style.transform;
        el1.style.transform = el2.style.transform;
        el2.style.transform = temp;

        window.requestAnimationFrame(function () 

            // For waiting for .25 sec
            setTimeout(() => 
                container.insertBefore(el2, el1);
                resolve();
            , 250);
        );
    );



var naming reference

当我交换 swapIdx 和 i swap(blocks[swapIdx], blocks[i]) 时,条形图未在正确的 swapIdx 中交换,如下图所示,但它们被插入到 DOM 中的正确位置。

Image showing bars not swapping in the correct position

【问题讨论】:

【参考方案1】:

两个问题:

您的代码并没有真正通过调用 insertBefore... 来交换 DOM 节点...而是旋转两个给定元素之间范围内的元素:元素 2 插入之前元素 1,这意味着发生在元素 1 和 2 之间的所有元素都被移动了。

您的blocks 数组保持不变。那里什么都没有交换。然而,您还应该交换 blocks 数组中的节点,因为这是您的算法执行比较的基础。

要真正交换两个 DOM 元素,请执行以下操作:

创建临时虚拟元素 调用replaceWith将该元素交换到文档中,同时取出第一个元素。 调用replaceWith 将该元素(已取出)与另一个元素交换 调用replaceWith 将第二个元素与临时元素交换。

【讨论】:

正如你所说的块数组本身没有更新。另外我正在使用 insertBefore ,它没有做我打算做的事情。所以我认为我应该创建另一个包含我的条的当前值的数组,并使用该数组进行排序。 这是个好主意。但是,您仍然需要交换 DOM 节点。所以实际上交换它们而不是在另一个之前移动它们。 在我的回答中添加了一段关于此的内容。试一试。如果你不能让它工作,问一个关于交换 DOM 节点的新问题,并提供一段简单的代码(不是完整的快速排序实现)来做,解释你在哪里卡住了。 我删除了我之前的评论,因为我在询问如何交换节点,这是另一个问题的单独主题。无论如何也感谢您添加交换部分。

以上是关于为啥这种方法不适用于通过反应可视化快速排序?的主要内容,如果未能解决你的问题,请参考以下文章

八大排序之快速排序

算法篇:快速排序

快速排序(经典快排以及随机快排)

快速排序:递归与非递归

您如何在中间位置实现枢轴快速排序,这种变化称为啥? [关闭]

快速排序和二分查找