DEV Community

loading...
Cover image for Visualizing Bubble Sort (Vue.js)

Visualizing Bubble Sort (Vue.js)

James Easter
Creative, coffee-drinking software developer
・4 min read

As an attempt to dive into Vue.js and brushing up on my algorithm chops I decided to make an algorithm sort visualizer app: Algo-Visualizer

It was a lot of fun and there is still so much to explore, but I immediately was hit with some really cool insights I'd love to share.

I'll start at the beginning: I first created the shell of the app, removed all of the dummy data, and put placeholders for the header, the array with random values, and the buttons.

Then I made created the array which is simply iterated over as the vue component renders. Each value in the array is an object with two properties: color & value. The color property is used to give the initial background color to the div that holds it so we can see each of the objects in the array, and the value is the height of the bar.

Once I had my header, array, and buttons I was off to the races. I starting by writing the code for each algorithm and would then test them against hundreds of randomly generated arrays and JavaScripts built in sort function. Once I was sure that my functions were working as desired I attempted to visualize them.

Visualizing something for human appreciation that normally happens in a split second presents a whole set of challenges. I Somehow needed to slow down or pause the sorting function as it was happening, possibly change the colors of the values that were being compared, and then show if a value was in its final sorted position.

Fortunately, bubble sort is quite simple in its make up. While brainstorming possible visualizing solutions I recalled a blog I prepared on the ES8 keywords async/await (you can find it here). Realizing I could actually slow down the code by pausing it, I concocted a fun way to pause the code during the sorting algorithm to better visualize what is going on. This is the super secret special (kinda hacky) line of code that become oh so helpful for this specific algorithm:

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

In short you can give your functions asynchronous capabilities when you use the async and await keywords. I simply put async in front of my function declaration and use this line of code in the middle of my bubble sort loop so I could change the colors of the two values in the array that were being compared, then pause the code to await the resolve of a setTimeout inside of a Promise, and then continue the sorting algorithm.

If we pick apart this line we are asking our code to sit and wait (or await) for the result of the Promise which is passed into a setTimeout function for 1 millisecond. The code then continues at its normal lighting speed until the next time it hits this line of code in our loop causing it to pause again for 1 millisecond.

While this is await usage is anything but helpful in the normal application of a sorting algorithm, here, it allows the sorting to be visualized in a way that helps us see and appreciate how bubble sort actually works and sorts values!

Below is my entire bubble sort function from my Algo-Visualizer app. The code comments help guide the overall explanation:

async function bubbleSort(ref, array) {
  // change the color to primary to start sorting algorithm
  array.forEach((num, index) => {
    ref.$set(array, index, {
      value: num.value,
      color: ref.primary,
    });
  });
  let counter = 0;
  let swap = true;

  while (counter < array.length && swap) {
    swap = false;
    for (let i = 0; i < array.length - 1 - counter; i++) {
      // change color of two indeces that are being compared
      let { value: a } = array[i];
      let { value: b } = array[i + 1];
      ref.$set(array, i, { value: a, color: ref.compare });
      ref.$set(array, i + 1, { value: b, color: ref.compare });

      // pauses the event loop to better visualize the algo
      await new Promise((resolve) => setTimeout(resolve, 1));

      // if the first index is greater than the second
      if (array[i].value > array[i + 1].value) {
        swap = true;
        // swap indeces
        let { value, color } = array[i];
        let { value: tempValue } = array[i + 1];
        ref.$set(array, i + 1, { value, color });
        ref.$set(array, i, { value: tempValue, color });
      }

      // change colors back to primary and set the final index color to sorted
      let { value: newA } = array[i];
      let { value: newB } = array[i + 1];
      ref.$set(array, i, { value: newA, color: ref.primary });
      ref.$set(array, i + 1, { value: newB, color: ref.sorted });
    }
    // increment counter
    counter += 1;
  }
  // change the color to sorted on the final iteration
  array.forEach((num, index) => {
    ref.$set(array, index, {
      value: num.value,
      color: ref.sorted,
    });
  });
}

module.exports = bubbleSort;

I extracted each of my sorting algorithms into their own separate JavaScript file as to not clutter the main Vue component.

In order for Vue to actively change the DOM elements that are created from the height of each value in the array I needed to pass in a reference to the Vue component which is passed in as "ref" and utilizes the .$set() method.

Otherwise, it's a the plain old tried and true bubble sort algorithm plus or minus some async/await tricks. Manipulating the timing of function calls in JavaScript is always interesting and initiates some fun learning opportunities.

While this simple async/await adaptation worked with Bubble Sort, other algorithms, specifically recursive sorting algorithms, required an entirely different approach. More to come on those tough dudes, hope you enjoy!

Discussion (0)

Forem Open with the Forem app