Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 算法可视化:实现无循环的插入排序,但每次调用函数时都以可变增量执行_Java_Algorithm_Sorting_Processing_Data Visualization - Fatal编程技术网

Java 算法可视化:实现无循环的插入排序,但每次调用函数时都以可变增量执行

Java 算法可视化:实现无循环的插入排序,但每次调用函数时都以可变增量执行,java,algorithm,sorting,processing,data-visualization,Java,Algorithm,Sorting,Processing,Data Visualization,我正在处理中构建一个排序算法可视化工具(java的扩展,带有额外的可视化库),我非常专注于这个问题,我认为其他人可以帮助我解决这个问题。 在处理过程中,有一个名为draw()的函数每秒被调用60次。每次调用draw()时,我都要在这里执行插入算法的一个步骤。我已经用冒泡排序实现了它。(见下面的代码)。 updateBubble()在draw()中被调用,“colors”是我用来保存不同颜色值以进行排序的arraylist的名称 通过图片更好地了解: [![可视化算法预览][1][1] ... i

我正在处理中构建一个排序算法可视化工具(java的扩展,带有额外的可视化库),我非常专注于这个问题,我认为其他人可以帮助我解决这个问题。 在处理过程中,有一个名为draw()的函数每秒被调用60次。每次调用draw()时,我都要在这里执行插入算法的一个步骤。我已经用冒泡排序实现了它。(见下面的代码)。 updateBubble()在draw()中被调用,“colors”是我用来保存不同颜色值以进行排序的arraylist的名称

通过图片更好地了解: [![可视化算法预览][1][1]

...
int j = 0
...
void updateBubble() {
  bubble.sort(j);
  j++;
  if (i<bubble.colors.size()) {
    if (j >= bubble.colors.size()-i-1) {
      j = 0;
      i++;
    }
  } else {
    bubble.sorted = true;
  }
}
void排序(){
int n=colors.size();
对于(inti=1;i=0&&colors.get(j)>key){
colors.set(j+1,colors.get(j));
j=j-1;
} 
颜色。设置(j+1,键);
}
}
这就是我现在得到的:这仍然是错误的,但它越来越接近并明确了我试图达到的目标,生成了一个只使用递增和if语句而不是whiles和fors的函数,因此每个不同的步骤都是通过方法的每次调用来执行的

  // i resembles for loop variable
  if (i<insertion.colors.size()) {
    if (j<0 || insertion.colors.get(j) <= insertion.colors.get(i)) { // negative check to go out of while loop
      insertion.colors.set(j+1, keap);
      if(notSortedYet()){
      i++;
      keap = insertion.colors.get(i);
      j = i - 1;
      }
    } else { // resembles being in the while loop
      insertion.colors.set((j+1), insertion.colors.get(j));
      j = j - 1;
    }
  }
}                                                                                                                                       
//我类似于for循环变量

如果(i实现这一点的一种方法是通过某种存储状态。下面是我所说的高层

// Starts the procedure. Must be called before draw().
void init() {
    state = "forLoop";

    i = 1;
    n = colors.size();
}

// Single iteration of a loop.
void draw(){
    switch(state) {
        case "forLoop":
            doForBody();
            break;
        case "whileLoop":
            doWhileLoopBody();
            break;
        ...
    }
}

// Executes everything in the while loop and the one or two things
// just after it.
void doWhileLoopBody() {
    if (isThisIterationOfWhileDone()) {
        // Get out of the while loop and prepare for the next iteration of for.
        // A better way to what I'm doing on the next couple lines here would
        // be to introduce an additional state (ex: "postWhile") that would
        // execute just after this method and would handle the colors.set(),
        // incrementing i, etc.
        state = "forLoop";
        colors.set(j+1, key);
        i++;
        return;
    }
    // update colors, value of j, etc...
}


// Executes everything before the while loop.
void doForLoopBody() {
    if (isThisIterationOfForDone()) {
        state = "END";
        return;
    }

    // update colors, get values of key and j initialized, etc

    // switch to processing the body of the while loop
    state = "whileLoop";
}
我喜欢这个项目

Processing还有一个
millis()
方法,该方法返回自开始绘制草图以来所花费的毫秒数。我有时使用它来计时动画,这在这里很有用。下面是计时器类的一个实现:

class Delay {
  int limit;
  
  Delay (int l) {
    limit = millis() + l;
  }
  
  boolean expired () {    
    return (millis() > limit);
  }
}
我建议您使用这个类,而不是调整FPS。通过使用延迟来减慢排序的实现,您让计算机按照自己的节奏工作,并且只在需要时绘制一个新的帧。像这样(请原谅我说“做东西”的部分):

您可以微调数据的排序速度,并仅在数据发生变化时绘制数据。这是双赢的

玩得开心


编辑

为了帮助您实现,这里有一个示例。您可以将此代码复制并粘贴到一个空的处理草图中,它将按原样运行。为了让我的工作更轻松,我将打印到控制台,而不是使用图形显示,但您应该能够了解我正在执行的操作

这里的秘密是,我的排序算法被巧妙地修改了,所以当我调用它们时,它们总是只运行一个排序步骤。请参见:

int _numberOfItems = 10;
int _sortingStep = 0;
IntList _bubbleList = new IntList();
boolean _bubbleListSorted = false;
IntList _selectionList = new IntList();
IntList _insertionList = new IntList();
Delay _delay = new Delay(1);

void setup() {  
  for (int i=0; i<_numberOfItems; i++) {
    _bubbleList.append((int)random(10, 99));
  }
  for (int i=0; i<_numberOfItems; i++) {
    _selectionList.append((int)random(10, 99));
  }
  for (int i=0; i<_numberOfItems; i++) {
    _insertionList.append((int)random(10, 99));
  }
}

void draw() {
  if (_delay.expired()) {
    _delay = new Delay(500);

    // sort one step with every algo you want to display
    if (!_bubbleListSorted) {
      singleStepBubbleSort(_bubbleList);
    }
    if (_sortingStep < _numberOfItems) {
      singleStepSelectionSort(_selectionList, _sortingStep);
      singleStepInsertionSort(_insertionList, _sortingStep);
    }
    _sortingStep++;

    // update the display (I'm printing to console instead for simplicity)
    for (int i : _bubbleList) {
      print(i + " ");
    }
    print("  |  ");
    for (int i : _selectionList) {
      print(i + " ");
    }
    print("  |  ");
    for (int i : _insertionList) {
      print(i + " ");
    }
    print("\n");
  }
}

// An "single-step" implementation of Insertion Sort
void singleStepInsertionSort(IntList list, int step) {
  int k = list.get(step); 
  int j = step - 1; 
  while (j >= 0 && list.get(j) > k) { 
    list.set(j+1, list.get(j));
    j = j - 1;
  } 
  list.set(j+1, k);
}

// An "single-step" implementation of Bubble Sort
void singleStepBubbleSort(IntList list) { 
  int temp; 
  boolean swapped = false;

  for (int i=0; i<list.size()-1; i++)  
  { 
    if (list.get(i) > list.get(i + 1))  
    { 
      // swap arr[j] and arr[j+1] 
      temp = list.get(i); 
      list.set(i, list.get(i+1)); 
      list.set(i+1, temp); 
      swapped = true;
    }
  }

  if (!swapped) {
    _bubbleListSorted = true;
  }
}

// An "single-step" implementation of Selection Sort
void singleStepSelectionSort(IntList list, int step) 
{ 
  int min_idx = step; 
  for (int j = step+1; j < list.size(); j++) {
    if (list.get(j) < list.get(min_idx)) {
      min_idx = j;
    }
  }

  int temp = list.get(min_idx); 
  list.set(min_idx, list.get(step)); 
  list.set(step, temp);
}

class Delay {
  int limit;

  Delay (int l) {
    limit = millis() + l;
  }

  boolean expired () {    
    return (millis() > limit);
  }
}
int\u numberOfItems=10;
int _sortingStep=0;
IntList _bubbleList=新的IntList();
布尔值_bubbleListSorted=false;
IntList _selectionList=new IntList();
IntList _insertionList=new IntList();
延迟_延迟=新延迟(1);
无效设置(){
对于(int i=0;i极限;
}
}

如果我这次理解正确的话,这应该可以解决您最初的问题!

我会像中一样使用迭代器。现在您可以逐步完成算法,并将绘图代码置于控制之下。嘿,感谢您的快速评论!我不太明白这将如何帮助我,或者我将如何实现它?有一个循环和一段时间的loop、 在这个过程中,每次使用迭代器调用draw()时,我怎么能只执行一个步骤呢?嘿!谢谢你的回答,我肯定会实现一个algo计时器:)问题是,我希望这4种算法在同一时间以相同的速度生成步骤。因此,它们生成步骤的方法都应该在绘图中调用。如果我在绘图中延迟,我仍然无法一步一步地执行排序算法:)是有意义的。信不信由你,但我昨晚想了想:你可以把延迟放在排序算法中。这样,每个算法都可以在您选择的时间进行调整。确保每个延迟对象都是不同的对象,否则可能会意外放弃某些排序步骤。如果这种实现让你感到奇怪,让我知道,我会给你看一段代码片段,让你看得更清楚。如果我在算法中加了一个延迟,是不是下一个算法不会被调用,除非上一个算法结束了?还是我错了?我能假设你希望所有的排序算法都以同样的速度逐步前进吗?@Arnepanemans我用一些代码更新了答案,这应该能帮助你理解我的意思。
void updateInsertion() {

  // i resembles for loop variable

  if (i<insertion.colors.size()) {
    if (j>=0 && insertion.colors.get(j) > firstUnsorted) {
      int temp = insertion.colors.get(j+1);
      insertion.colors.set((j+1), insertion.colors.get(j));
      insertion.colors.set(j,temp);
      j = j - 1;
    } else {
      insertion.colors.set(j+1, firstUnsorted);
      if (i<insertion.colors.size()-1) {
        i++;
      }
      firstUnsorted = insertion.colors.get(i);
      j = i - 1;
    }
  }
}
// Starts the procedure. Must be called before draw().
void init() {
    state = "forLoop";

    i = 1;
    n = colors.size();
}

// Single iteration of a loop.
void draw(){
    switch(state) {
        case "forLoop":
            doForBody();
            break;
        case "whileLoop":
            doWhileLoopBody();
            break;
        ...
    }
}

// Executes everything in the while loop and the one or two things
// just after it.
void doWhileLoopBody() {
    if (isThisIterationOfWhileDone()) {
        // Get out of the while loop and prepare for the next iteration of for.
        // A better way to what I'm doing on the next couple lines here would
        // be to introduce an additional state (ex: "postWhile") that would
        // execute just after this method and would handle the colors.set(),
        // incrementing i, etc.
        state = "forLoop";
        colors.set(j+1, key);
        i++;
        return;
    }
    // update colors, value of j, etc...
}


// Executes everything before the while loop.
void doForLoopBody() {
    if (isThisIterationOfForDone()) {
        state = "END";
        return;
    }

    // update colors, get values of key and j initialized, etc

    // switch to processing the body of the while loop
    state = "whileLoop";
}
class Delay {
  int limit;
  
  Delay (int l) {
    limit = millis() + l;
  }
  
  boolean expired () {    
    return (millis() > limit);
  }
}
Delay holdTheFrame = new Delay(1);
void draw() {
  if(holdTheFrame.expired()) {
    holdTheFrame = new Delay(500); // half a second before the next frame
    // Advance one step forward in your sorting
    // Draw the visualization of the data
  }
}
int _numberOfItems = 10;
int _sortingStep = 0;
IntList _bubbleList = new IntList();
boolean _bubbleListSorted = false;
IntList _selectionList = new IntList();
IntList _insertionList = new IntList();
Delay _delay = new Delay(1);

void setup() {  
  for (int i=0; i<_numberOfItems; i++) {
    _bubbleList.append((int)random(10, 99));
  }
  for (int i=0; i<_numberOfItems; i++) {
    _selectionList.append((int)random(10, 99));
  }
  for (int i=0; i<_numberOfItems; i++) {
    _insertionList.append((int)random(10, 99));
  }
}

void draw() {
  if (_delay.expired()) {
    _delay = new Delay(500);

    // sort one step with every algo you want to display
    if (!_bubbleListSorted) {
      singleStepBubbleSort(_bubbleList);
    }
    if (_sortingStep < _numberOfItems) {
      singleStepSelectionSort(_selectionList, _sortingStep);
      singleStepInsertionSort(_insertionList, _sortingStep);
    }
    _sortingStep++;

    // update the display (I'm printing to console instead for simplicity)
    for (int i : _bubbleList) {
      print(i + " ");
    }
    print("  |  ");
    for (int i : _selectionList) {
      print(i + " ");
    }
    print("  |  ");
    for (int i : _insertionList) {
      print(i + " ");
    }
    print("\n");
  }
}

// An "single-step" implementation of Insertion Sort
void singleStepInsertionSort(IntList list, int step) {
  int k = list.get(step); 
  int j = step - 1; 
  while (j >= 0 && list.get(j) > k) { 
    list.set(j+1, list.get(j));
    j = j - 1;
  } 
  list.set(j+1, k);
}

// An "single-step" implementation of Bubble Sort
void singleStepBubbleSort(IntList list) { 
  int temp; 
  boolean swapped = false;

  for (int i=0; i<list.size()-1; i++)  
  { 
    if (list.get(i) > list.get(i + 1))  
    { 
      // swap arr[j] and arr[j+1] 
      temp = list.get(i); 
      list.set(i, list.get(i+1)); 
      list.set(i+1, temp); 
      swapped = true;
    }
  }

  if (!swapped) {
    _bubbleListSorted = true;
  }
}

// An "single-step" implementation of Selection Sort
void singleStepSelectionSort(IntList list, int step) 
{ 
  int min_idx = step; 
  for (int j = step+1; j < list.size(); j++) {
    if (list.get(j) < list.get(min_idx)) {
      min_idx = j;
    }
  }

  int temp = list.get(min_idx); 
  list.set(min_idx, list.get(step)); 
  list.set(step, temp);
}

class Delay {
  int limit;

  Delay (int l) {
    limit = millis() + l;
  }

  boolean expired () {    
    return (millis() > limit);
  }
}
int numberOfItems = 10;
int sortingStep = 0;
Delay delay = new Delay(1);
ManagedSelectionSort managedSelectionSort;  // I created a class just to manage this madness

void setup() {
  IntList list = new IntList();
  for (int i=0; i<numberOfItems; i++) {
    list.append((int)random(10, 99));  // some random numbers to sort later 
  }

  managedSelectionSort = new ManagedSelectionSort(list);  // take a look at the instantiation of this class

  print("Step " + String.format("%02d", sortingStep) + ": ");
  printArray(managedSelectionSort.list);
  print("\n");
}

void draw() {
  if (delay.expired()) {    
    delay = new Delay(100);  // i put a very short delay, you'll probably want to tweak this

    managedSelectionSort.sortOneStep();  // this is not what it seems
    sortingStep++;

    print("Step " + String.format("%02d", sortingStep) + ": ");
    printArray(managedSelectionSort.list);
    print("\n");
  }
}

// this class is where the magic happens
// we'll sort the array all at once while recording every move
// then we'll play back those moves on a copy of the array
class ManagedSelectionSort {
  IntList list, hiddenList;  // list is the "official" list, while hiddenList is where the heavy lifting happens
  ArrayList<SwapIndex> swapList;  // this is where I record how to sort the array

  ManagedSelectionSort(IntList baseList) {  // this way I can instantiate several similar objects with the same list
    list = new IntList();
    hiddenList = new IntList();
    swapList = new ArrayList<SwapIndex>();

    for (int i : baseList) {
      // both lists have the same initial numbers
      list.append(i);
      hiddenList.append(i);
    }

    // as soon as this object is instantiated, it knows how it'll sort the array
    // because it already did...
    hiddenSort();
  }

  // this method plays the moves which were recorded earlier according to the current sortingStep
  // the swapList array was filled with every swap needed to sort the array, one by one
  // now it's just a matter of playing them back on a copy of the initial array
  void sortOneStep() {
    if (sortingStep < swapList.size()) {
      swap(list, swapList.get(sortingStep).index1, swapList.get(sortingStep).index2);
    }
  }

  // this is the real implementation of the insertion sort
  void hiddenSort() 
  {
    for (int i=1; i<hiddenList.size(); i++) {
      int j = i;

      while (j>0 && hiddenList.get(j) < hiddenList.get(j-1)) {
        swap(hiddenList, j, j-1, true);  // swap is a class specific helper method, it swaps the numbers and also records the move
        j--;
      }
    }
  }

  // this is an overload, i could have done without but it's confortable
  void swap(IntList list, int index1, int index2) {
    swap(list, index1, index2, false);
  }
  void swap(IntList list, int index1, int index2, boolean recordMove) {
    // the swap first
    int temp = list.get(index1);
    list.set(index1, list.get(index2));
    list.set(index2, temp);

    // if the method is set on 'record', it adds this move to the swapList array
    if (recordMove) {      
      swapList.add(new SwapIndex(index1, index2));
    }
  }
}

// this class could have been a struct, but I like to start in OOP right from the bat in case things gets complicated
class SwapIndex {
  int index1;
  int index2;

  SwapIndex(int index1, int index2) {
    this.index1 = index1;
    this.index2 = index2;
  }
}

// this method is just an helper method to print to console
void printArray(IntList list) {
  for (int i : list) {
    print(i + " ");
  }
}

class Delay {
  int limit;

  Delay (int l) {
    limit = millis() + l;
  }

  boolean expired () {    
    return millis() > limit;
  }
}