JavaScript合并排序可视化

时间:2019-03-21 19:41:11

标签: javascript mergesort p5.js

我设法在p5.js中完成了一个合并排序,以对不同的长度行进行排序,但无法弄清楚如何真正显示它们正在排序。即显示它们未排序,然后在排序时更新其位置。我不确定是否可以通过一种简便的方式来实现当前代码的编写方式,或者是否需要在每个阶段之后拆分排序功能并重新绘制?

LRESULT CALLBACK MainWindow::MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_NCCREATE:
{
    CREATESTRUCT *pcs = (CREATESTRUCT*)lParam;
    //MainWindow* mainWindow = (MainWindow*)pcs->lpCreateParams;
    //mainWindow->hwnd = hWnd;
    SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG)pcs->lpCreateParams);

    /*Taskbar *taskbar = new Taskbar();
    taskbar->RegisterTaskbarWindow();
    taskbar->CreateTaskbarWindow(hWnd);*/

    /*WorkSpace *workspace = new WorkSpace();
    workspace->RegisterWorkSpaceWindow();
    workspace->CreateWorkSpaceWindow(hWnd);*/
    return TRUE;
}
break;
case WM_CREATE:
{
    ShowWindow(hWnd, SW_SHOW);
}
break;
case WM_CLOSE:
{
    PostQuitMessage(0);
}
break;
case WM_DESTROY:
{
    MainWindow *mainWindow = (MainWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    if (mainWindow) mainWindow->hwnd = 0;
    return TRUE;
}
break;
case WM_LBUTTONDOWN:
{
    MainWindow *mainWindow = (MainWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    POINT pointer;
    pointer.x = GET_X_LPARAM(lParam);
    pointer.y = GET_Y_LPARAM(lParam);
    mainWindow->OnClk(&pointer);
    return TRUE;
}
break;
case WM_RBUTTONDOWN:
{
    MainWindow *mainWindow = (MainWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    POINT pointer;
    pointer.x = GET_X_LPARAM(lParam);
    pointer.y = GET_Y_LPARAM(lParam);

    return TRUE;
}
break;
default:
    return DefWindowProc(hWnd, message, wParam, lParam);
}

return 0;
}
var values = [];
var numLines = 500;

function setup() {
  createCanvas(900, 600);
  colorMode(HSB, height);
  for (i = 0; i < numLines; i++) {
    values[i] = (round(random(height)));
  }
  
	values = mergeSort(values);
	
  noLoop();
 }


function draw() {
  background(51);

  for (let i = 0; i < values.length; i++) {
    let col = color(values[i], height, height);
    stroke(col);
    fill(col);
    var location = map(i, 0, values.length, 0, width);
    rect(location, height - values[i], width/numLines, height);
  } 
}

function mergeSort(a) {
  if (a.length <= 1) {
    return a;
  }
  var mid = Math.round((a.length / 2));
  var left = a.slice(0, mid);
  var right = a.slice(mid);
  return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right) {
  sorted = [];
  
  while (left && left.length > 0 && right && right.length > 0) {
    if (left[0] <= right[0]) {
      sorted.push(left.shift());
    }
    else {
      sorted.push(right.shift());
    }
  }
  return sorted.concat(left, right);
}

2 个答案:

答案 0 :(得分:0)

为了可视化排序,我们需要在排序过程中间隔绘制。在这里,我添加了一个depth变量,以便可以控制排序的范围。每次抽奖被称为“我增加深度”,以便我们可以看到进度。

var values = [];
var numLines = 500;

function setup() {
  createCanvas(900, 600);
  colorMode(HSB, height);
  for (i = 0; i < numLines; i++) {
    values[i] = (round(random(height)));
  }
  frameRate(1);
 }

var depth = 1;
function draw() {
  background(51);
  values = mergeSort(values, depth);
  depth++;
  for (i = 0; i < values.length; i++) {
    let col = color(values[i], height, height);
    stroke(col);
    fill(col);
    var location = map(i, 0, values.length, 0, width);
    rect(location, height - values[i], width/numLines, height);
  } 
  if (depth > 10){
   noLoop();
  }
}

function mergeSort(a, d) {
  if (a.length <= 1) {
    return a;
  }
  d--;
  if (d < 1){
    return a;
  }
  var mid = Math.round((a.length / 2));
  var left = a.slice(0, mid);
  var right = a.slice(mid);
  return merge(mergeSort(left,d), mergeSort(right, d));
}

function merge(left, right) {
  sorted = [];
  while (left && left.length > 0 && right && right.length > 0) {
    if (left[0] <= right[0]) {
      sorted.push(left.shift());
    }
    else {
      sorted.push(right.shift());
    }
  }
  return sorted.concat(left, right);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>

答案 1 :(得分:0)

此答案使用非递归合并排序,保留排序阶段的历史记录。整个排序是在绘制之前执行的,然后绘制所有阶段的步骤,以便我们可以看到算法如何移动线条来实现排序。该代码改编自Mike Bostock的可视化算法。

https://bost.ocks.org/mike/algorithms/ https://bl.ocks.org/mbostock/1b5450d525babd28425f

var values = [];
var numLines = 500;
var sortHist = [];
function setup() {
  createCanvas(900, 600);
  colorMode(HSB, height);
  for (i = 0; i < numLines; i++) {
    values[i] =random(height);
  }
  sortHist = mergeSort(values);
  frameRate(1);
}
  
var historyIndex = 0;
function draw() {
  background(51);
  for (i = 0; i < sortHist[historyIndex].length; i++) {
    let col = color(sortHist[historyIndex][i], height, height);
    stroke(col);
    fill(col);
    var location = map(i, 0, sortHist[historyIndex].length, 0, width);
    rect(location, height - sortHist[historyIndex][i], width/numLines, height);
  } 
  historyIndex++;
  if (historyIndex > sortHist.length -1){
    noLoop();
  }
}

function mergeSort(array) {
  var arrays = [array.slice()],
  n = array.length,
  array0 = array,
  array1 = new Array(n);

  for (var m = 1; m < n; m <<= 1) {
    for (var i = 0; i < n; i += (m << 1)) {
      merge(i, Math.min(i + m, n), Math.min(i + (m << 1), n));
    }
    arrays.push(array1.slice());
    array = array0, array0 = array1, array1 = array;
  }

function merge(left, right, end) {
  for (var i0 = left, i1 = right, j = left; j < end; ++j) {
    array1[j] = array0[i0 < right && (i1 >= end || array0[i0] <=    array0[i1]) ? i0++ : i1++];
   }
 }
 return arrays;
}  
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>