I'm trying to do a Mergesort algorithm with D3 visualization. In JS script I defined global variables (number of elements, time etc.), svg, labels and circles.

var count = 11;
var durationTime = 250;
var array = d3.shuffle(d3.range(1,count));
var unsortedArray = [...array];
var sortedArray = [];
var stop = false;
var steps = 0;

var margin = {top: 40, right: 40, bottom: 180, left: 40},
    width = 960 - margin.left - margin.right,
    height = 100 - margin.top - margin.bottom;

var space = width/count;

changeElementNumber = function (elementNumber) {
        count = elementNumber;
        console.log(count);
        reset();
    };

    changeElementSpeed = function (elementSpeedValue) {
            durationTime = elementSpeedValue*1000;
          }

var x = d3.scaleLinear().domain([0,count]).range([0, width]);

var svg = d3.select("#Merge").append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
          .append("g")
          .attr("border","1")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

  var circles = svg.append("g")
          .attr("transform", "translate(" + space + ",2)")
          .selectAll("circle")
          .data(unsortedArray)
          .enter().append("circle");

  circles.attr("id", function(d) {return "circle" + d})
          .attr("transform", function(d, i) {return "translate(" + (x(i) - space) + ",0)"})
          .attr("r","15")
          .attr("fill", "#262626");

  var labels = svg.selectAll("text")
          .data(unsortedArray)
          .enter().append("text")

  labels.attr("id", function(d) {return "text" + d})
          .attr("transform", function(d, i) {return "translate(" + (x(i) - 9) + ",8)"})
          .html(function(d) {return d;})
          .attr("fill", "#e2e2e2");

In HTML I can see 10 labeled circles (numbers are saved into an array). When I click a button to do the mergesort, It is fine. I can see animation and everything.

function mergeSort() {
              console.log(unsortedArray);
              var mergeReps = (unsortedArray.length).toString(2).length + 1;
              var mergeArrays = [[...unsortedArray], []];

              for (i=0; i<unsortedArray.length; i += 2) {
                  mergeArrays[1].push(mergeTwo([unsortedArray[i]], [unsortedArray[i+1]]))
              }
              for (n=2; n<mergeReps; n++) {
                  mergeArrays[n] = [];
                  var unMerged = mergeArrays[n-1];
                  for (i=0; i<unMerged.length; i += 2) {
                      mergeArrays[n].push(mergeTwo(unMerged[i], unMerged[i+1] ? unMerged[i+1] : []))
                  }
              }
              for (i=1; i<mergeArrays.length; i++) {
                  mergeArrays[i] = d3.merge(mergeArrays[i])
              }
              mergeMove(0);

              function mergeTwo(iArray, nArray) {
                  var newArray = [];
                  for (var i=0, n=0; i<iArray.length || n<nArray.length;) {
                      if (iArray[i] < nArray[n]) {
                          newArray.push(iArray[i++])
                      } else if (iArray[i] > nArray[n]) {
                          newArray.push(nArray[n++])
                      } else if (!(iArray[i])) {
                          newArray.push(nArray[n++])
                      } else if (!(nArray[n])) {
                          newArray.push(iArray[i++])
                      }
                  }
                  return newArray;
              }

              function mergeMove(j) {
                  var oldArray = mergeArrays[j],
                      newArray = [...mergeArrays[j+1]],
                      sortedArray = [];

                  moveStep(0);

                  function moveStep(n) {
                      if (stop) return stop = false;
                      d3.selectAll("circle").attr("class", "").attr("r", 15);

                      d3.select("#counter").html(++steps);
                      d3.select("#circle" + newArray[n]).attr("class", "testing").attr("r", 20);

                      sortedArray.push(newArray[n])
                      oldArray.shift()

                      circles.transition().duration(durationTime)
                          .attr("transform", function(d) {
                              var xVal = sortedArray.indexOf(d) > -1 ? sortedArray.indexOf(d) : oldArray.indexOf(d) + sortedArray.length;
                              return "translate(" + x(xVal - 1) + ",0)"
                          })

                      labels
                          .classed("sorted", function(d) {
                              return !mergeArrays[j + 2] && sortedArray.indexOf(d) == d - 1;
                          })
                          .transition().duration(durationTime)
                          .attr("transform", function(d) {
                              var xVal = sortedArray.indexOf(d) > -1 ? sortedArray.indexOf(d) : oldArray.indexOf(d) + sortedArray.length;
                              return "translate(" + (x(xVal) - 9) + ",8)"
                          })

                      d3.timeout(function() {
                          if (oldArray.length > 0) {
                              moveStep(++n)
                          } else if (mergeArrays[j + 2]) {
                              mergeMove(++j)
                          } else {
                              circles.classed("testing", false)
                          }
                      }, durationTime);
                  }
              }
          }

PROBLEM: And now, in HTML I put new number of elements (let's say 7) and new duration time (duration time is not important now, I'm trying to fix array issue.) and with "reset" function I define new global variables, delete svg and make a new one. Also I put console.log and it works okay: On every button press, elements in that array change. But after clicking a button to do mergesort, that first created array is used as new one. There is no animation and it's not even sorted at the end.

changeElementNumber = function (elementNumber) {
        count = elementNumber;
        console.log(count);
        reset();
    };

    changeElementSpeed = function (elementSpeedValue) {
            durationTime = elementSpeedValue*1000;
    }

function reset() {

                  var array = d3.shuffle(d3.range(1,count));
                  var unsortedArray = [...array];
                  var sortedArray = [];

                  console.log(unsortedArray);

                  d3.select("#counter").html(steps = 0)

                  d3.selectAll("svg").remove();

                  var x = d3.scaleLinear().domain([0,count]).range([0, width]);

                  var svg = d3.select("#Merge").append("svg")
                            .attr("width", width + margin.left + margin.right)
                            .attr("height", height + margin.top + margin.bottom)
                            .append("g")
                            .attr("border","1")
                            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

                    var circles = svg.append("g")
                            .attr("transform", "translate(" + space + ",2)")
                            .selectAll("circle")
                            .data(unsortedArray)
                            .enter().append("circle");

                    circles.attr("id", function(d) {return "circle" + d})
                            .attr("transform", function(d, i) {return "translate(" + (x(i) - space) + ",0)"})
                            .attr("r","15")
                            .attr("fill", "#262626");

                    var labels = svg.selectAll("text")
                            .data(unsortedArray)
                            .enter().append("text")

                    labels.attr("id", function(d) {return "text" + d})
                            .attr("transform", function(d, i) {return "translate(" + (x(i) - 9) + ",8)"})
                            .html(function(d) {return d;})
                            .attr("fill", "#e2e2e2");

                            array = d3.shuffle(d3.range(1,count));
                            unsortedArray = [...array];
                            sortedArray = [];
                            stop = false;
              }

Console log without changing number of elements:

mergeD3.js:8 Default array: 6,7,3,9,1,4,8,2,10,5
mergeD3.js:55 New array but in mergesort function: 6,7,3,9,1,4,8,2,10,5
mergeD3.js:130 Sorted: 6,7,3,9,1,4,8,2,10,5


Console log after changing number of elements:

mergeD3.js:8 Default array: 4,5,6,9,7,8,2,1,10,3
mergeD3.js:17 new number of elemets: 7
mergeD3.js:143 New array: 3,1,4,6,5,2
mergeD3.js:55 New array but in mergesort function: 4,5,6,9,7,8,2,1,10,3
mergeD3.js:130 Sorted: 4,5,6,9,7,8,2,1,10,3

0 Answers