0

I am trying to implement bubble sort visualization after getting the array from user in DOM. I have used setTimeout to delay the loop but it is not working, the loop is executing fast and some iterations are skipped while using setTimeout. It works fine without setTimeout. I wanted to slow the sorting so that people can visualize.

var btn1=document.getElementById("btn");
var btn2=document.getElementById("clr");
var btn3=document.getElementById("start");
var container=document.getElementById("contain");
let squares=[];
let timeout=1000;
btn1.onclick=function display(){
    var j=0;
    var i=0;
    swap=0;
    var temp=array.value;
    const result=temp.split(" ");
    for(i=0;i<result.length;i++)
    {
        var array_item=document.createElement("div");
        array_item.setAttribute("id",i+1);
        array_item.innerHTML=result[i];
        array_item.classList.add("box");
        container.append(array_item);
        squares.push(array_item);
    }
}
btn3.onclick=function bubble_sort(){
    for(i=0;i<squares.length-1;i++){
        for(j=0;j<squares.length-i-1;j++){   
            setTimeout(()=>{
                console.log(squares[i].innerHTML);
                if(parseInt(squares[j].innerHTML)>parseInt(squares[j+1].innerHTML)){
                    if(j>0){
                        squares[j-1].classList.remove("active")
                        squares[j].classList.remove("active")
                    }
                    squares[j].classList.add("active")
                    squares[j+1].classList.add("active")
                    setTimeout(()=>{
                        swap=squares[j].innerHTML;
                        squares[j].innerHTML=squares[j+1].innerHTML;
                        squares[j+1].innerHTML=swap;
                    },1000)
                    if(j===squares.length-i-2){
                        setTimeout(()=>{
                            squares[j].classList.remove("active")
                            squares[j+1].classList.remove("active")
                        },2000)
                    }  
                }
            },2000)
            timeout+=2000;
        }      
    }
    array.value="";
}
btn2.onclick=function reset(){
    while(container.firstChild)
    {
        container.removeChild(container.firstChild);
    }
    while(squares.length){
        squares.pop();
    }
    
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Poppins:wght@500&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="linearsearch.css">
    <title>Document</title>
</head>
<body>
    <div class="main">
        <div class="search">
            <h1>Bubble-Sort</h1>
            <label for="array-elements" id="labl">Enter array elements</label>
            <input type=" text" id="array-elements" name="array-elements" placeholder="separated with space"><br>
            <!--<label for="item">Enter array element to search for</label>
            <input type="text" id="item"><br>-->
            <div class="buttons">
                <button id="btn" class="button">insert</button><br>
                <button id="start" class="button">start</button><br>
                <button id="clr" class="button">Clear</button><br>
                
            </div>
            <div class="contain" id="contain"></div>
        </div>
    </div>
    <script src="linearsearch.js"></script>
</body>
</html>
Brian Tompsett - 汤莱恩
  • 5,438
  • 68
  • 55
  • 126

1 Answers1

0

This is relatively simple in ES6:

let a = [33, 103, 3, 726, 200, 984, 198, 764, 9];
// encapsulate setTimeout in a promise, so we can await it below
const wait = (timeout)=>{
    return new Promise((resolve)=>{
        setTimeout(resolve, timeout)
    })
}
// bubbleSort implementation copy-pasted from https://stackoverflow.com/a/37901176/3083470 - use yours of course
async function bubbleSort(a) {
    let swapped;
    do {
        swapped = false;
        for (let i=0; i < a.length-1; i++) {
            if (a[i] > a[i+1]) {
                let temp = a[i];
                a[i] = a[i+1];
                a[i+1] = temp;
                swapped = true;
                console.log(`swapped ${a[i]} and ${a[i + 1]}`)
                // here's where we wait for a predefined amount of time
                // you might want to move this outside the if to pause after every comparison, not only every swap
                await wait(1000);
            }
        }
    } while (swapped);
}

bubbleSort(a);

If you can't use ES6 the approach could look like this:

  • make a function that does just one step of the sorting
  • call that from a recursive function like so (assuming you keep the array defined outside the function):
function sortOneStep(currentIndex, swapped){
    // TODO: implement one step of sorting
    return [currentIndex + 1, swapped];
}

function loop(currentIndex, swapped) {
    var result = sortOneStep(currentIndex, swapped);
    var newIndex = result[0];
    var swapped = result[1];
    if(newIndex >= arrayToSort.length - 1){
        // we traversed the array fully. are we done yet?
        if(swapped){
           // nope, we're not done
           newIndex = 0;
           swapped = false;
        } else {
            // Yup, array is sorted
            return;
        }
    }
    setTimeout(function(){
       loop(newIndex, swapped);
    }, 2000);
}
Taxel
  • 2,985
  • 15
  • 31