merge-sort

let articleContent = document.querySelector(".article-content");
let sortSpace = document.createElement("div");
sortSpace.classList.add("sort-space");
articleContent.appendChild(sortSpace);
let size = 10;

// Create sorting elements
let sortItems = [];
for (let i = 0; i < size; i++) {
    let sortItem = document.createElement("div");
    sortItem.classList.add("sortItem");
    sortItem.style = "display: inline-block; border: solid black 2px; padding: 1rem; margin: 0.5rem;";
    sortItem.innerHTML = Math.floor(Math.random() * 20);
    sortItems.push(sortItem); // Store the sortItem in the array
    sortSpace.appendChild(sortItem);
}

// Create a button for stepping through the sort
let stepButton = document.createElement("button");
stepButton.style = "display: block; margin-top: 1rem;";
stepButton.innerHTML = "Next Step";

// State variables for merge sort
let mergeSortStack = []; // Stack to simulate recursion
let currentStep = null; // Current task
let sortedArray = null; // Final sorted array

// Initialize the stack with the first task
mergeSortStack.push({
    array: sortItems,
    left: 0,
    right: sortItems.length,
    step: "split", // First step is always splitting
});

// Add event listener to the "Next Step" button
stepButton.addEventListener("click", function () {
    // If the stack is empty, sorting is complete
    if (mergeSortStack.length === 0) {
        stepButton.innerHTML = "Done!";
        stepButton.disabled = true;
        return;
    }

    // Process the current step
    currentStep = mergeSortStack.pop();

    if (currentStep.step === "split") {
        // Split the array into two halves
        const mid = Math.floor((currentStep.left + currentStep.right) / 2);
        console.log(currentStep)
        if (currentStep.left + 1 < currentStep.right) {
            mergeSortStack.push({
                array: currentStep.array,
                left: currentStep.left,
                right: currentStep.right,
                step: "merge",
            });
            mergeSortStack.push({
                array: currentStep.array,
                left: currentStep.left,
                right: mid,
                step: "split",
            });
            mergeSortStack.push({
                array: currentStep.array,
                left: mid,
                right: currentStep.right,
                step: "split",
            });

        }

        // Visualize the current split
        visualizeArray(currentStep.array, currentStep.left, currentStep.right, "Splitting");
    } else if (currentStep.step === "merge") {
        // Merge two halves
        const mid = Math.floor((currentStep.left + currentStep.right) / 2);
        const leftArray = currentStep.array.slice(currentStep.left, mid);
        const rightArray = currentStep.array.slice(mid, currentStep.right);

        const mergedArray = combine(leftArray, rightArray);

        // Replace the original array section with the merged result
        let index = currentStep.left;
        for (let item of mergedArray) {
            currentStep.array[index] = item;
            index++;
        }

        // Visualize the current merge
        visualizeArray(currentStep.array, currentStep.left, currentStep.right, "Merging");
    }
});

articleContent.appendChild(stepButton);

// Combine function for merge sort
function combine(left, right) {
    let sortedArray = [];
    let leftIndex = 0;
    let rightIndex = 0;

    while (leftIndex < left.length && rightIndex < right.length) {
        if (parseInt(left[leftIndex].innerHTML) <= parseInt(right[rightIndex].innerHTML)) {
            sortedArray.push(left[leftIndex]);
            leftIndex++;
        } else {
            sortedArray.push(right[rightIndex]);
            rightIndex++;
        }
    }

    return sortedArray.concat(left.slice(leftIndex)).concat(right.slice(rightIndex));
}

// Function to visualize the array
function visualizeArray(array, start, end, operation) {
    // Clear the sort space
    sortSpace.innerHTML = "";

    // Display operation type
    let operationLabel = document.createElement("div");
    operationLabel.style = "margin-bottom: 1rem; font-weight: bold;";
    operationLabel.innerHTML = `${operation} (Index ${start} to ${end - 1})`;
    sortSpace.appendChild(operationLabel);

    // Display the current state of the array
    for (let i = 0; i < array.length; i++) {
        let clone = array[i].cloneNode(true);
        if (i >= start && i < end) {
            clone.style.backgroundColor = operation === "Merging" ? "lightblue" : "lightgreen";
        }
        sortSpace.appendChild(clone);
    }
}
🌐Check out other language versions!
網站使用 Hugo 製作
模板 StackJimmy 設計