JavaScript上的插入排序算法

时间:2015-11-04 19:59:15

标签: javascript algorithm

我最近开始根据书籍Data Structures and Algorithms with JavaScript from O'Reilly学习算法。

我停止了第12章 - 排序算法。

我无法理解插入排序的工作原理。

以下是我正在使用的代码:pasteBin - Insertion Sort

以下是令我困惑的部分:

function insertionSort() {
    var temp, inner;
    for (var outer = 1; outer <= this.dataStore.length - 1; ++outer) {
        temp = this.dataStore[outer];
        inner = outer;
        while (inner > 0 && (this.dataStore[inner-1] >= temp)) {
            this.dataStore[inner] = this.dataStore[inner-1];
            --inner;
        }
        this.dataStore[inner] = temp;
    }
    console.log(this.toString());
}

有人可以帮助和评论此代码吗?

4 个答案:

答案 0 :(得分:5)

它是一种排序算法,从数组的开头开始并一直持续到结束。对于每个索引处的项目,它会返回先前索引处的项目并检查它是否应放在它们之前。如果是这样,它会使用较大的值交换索引,直到它进入应该具有的索引。

这里的代码带有一些评论,希望它对你有所帮助。

function insertionSort() {
    /* Set up local vars */
    var temp, inner;
    /* Start at index 1, execute outer loop once per index from 1 to the last index */
    for (var outer = 1; outer <= this.dataStore.length - 1; ++outer) {
        /* Store the value at the current index */
        temp = this.dataStore[outer];
        /* Set up temporary index to decrement until we find where this value should be */
        inner = outer;
        /* As long as 'inner' is not the first index, and 
        there is an item in our array whose index is less than 
        inner, but whose value is greater than our temp value... */ 
        while (inner > 0 && (this.dataStore[inner-1] >= temp)) {
            /* Swap the value at inner with the larger value */
            this.dataStore[inner] = this.dataStore[inner-1];
            /* Decrement inner to keep moving down the array */
            --inner;
        }
        /* Finish sorting this value */
        this.dataStore[inner] = temp;
    }
    console.log(this.toString());
}

这是一个jsfiddle,其中包含许多控制台打印输出,因此您可以逐步浏览它,看看每一步都会发生什么。

答案 1 :(得分:2)

插入排序背后的主要概念是通过比较对元素进行排序。

对于dataStore数组,在您的情况下进行比较,其中包含我们假设为数字等可比元素的数组。

为了逐个元素地比较,这个插入排序算法从dataStore数组的开头开始,并将继续运行,直到到达数组的末尾。这是通过for循环完成的:

for (var outer = 1; outer <= this.dataStore.length - 1; ++outer)

当算法按顺序遍历每个元素时,它将:

  1. 将我们正在访问的当前元素存储在名为temp的变量中。
  2. 通过innerouter变量跟踪我们在数组中的位置,其中:
    • outer是我们的反击。
    • inner是一个标志,用于确定我们是否正在访问数组中的第一个元素。为什么这很重要?因为第一次尝试对第一个元素进行比较没有意义。
  3. 它会将当前元素tempdataStore数组中前面的每个元素进行比较。这是通过内部while循环实现的,如下所示:

    while (inner > 0 && (this.dataStore[inner-1] >= temp))

  4. 这告诉您,只要dataStore数组中所有先前访问过的元素都大于或等于temp,我们的临时变量就会用于存储当前元素;我们想要交换这些值。

    交换它们将完成以下任务:

    • 假设this.dataStore[inner]之前的所有元素都大于10,并且当前访问的元素this.dataStore[inner]等于5.这在逻辑上意味着5需要位于数组的开头。在这种情况下,由于while循环,我们将继续向下传递5到this.datastore[0]。从而使数组成为数组中的第一个元素。

    在此交换结束时,temp中的值相应地放置在我们在数组中的当前位置,只是为了提醒您这是一个位置,它存储了变量outer

    TLDR:我也很喜欢Justin Powell的答案,因为它坚持代码,但我认为根据你的理解水平,一个步骤会更有用。我希望它有所帮助!

答案 2 :(得分:0)

从内部循环开始,如果当前元素大于,则检查当前元素是否大于前一个元素,因为所有内容都针对迭代进行排序,请退出循环;如果不是,则交换元素,因为当前元素小于当前元素,因此需要向左移动以前的。内部循环确保交换元素,直到遇到排序元素,导致中断退出循环。

发生交换之后,请减小外部索引(i),因为您要向下检查即将到来的元素是否小于前一个元素,因此无法使外部索引(i)保持静态。

最后,memIndex变量用作重置索引,因为在内循环结束时,您想移至下一个索引。索引(i)应该始终放置在排序数组的最后一个元素上,以便内部循环可以再次开始比较。

function insertionSort(arr) {
  let memIndex = 0
  for (let i = 0; i < arr.length; i++) {
    memIndex = i;
    for (let j = i + 1; j >= 0; --j) {
      if (arr[j] >= arr[i]) {
        break;
      }
      if (arr[j] < arr[i]) {
        var temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        i = i - 1;
      }
    }
    i = memIndex;
  }
  return arr;
}
const arr = [5, 1, 6, 2, 4, 9, 9, 3, 1, 1, 1];
console.log('Unsorted array', arr);
console.log('Sorted array:', insertionSort(arr));

答案 3 :(得分:0)

const insertionSort = array => {
  const arr = Array.from(array); // avoid side effects

  for (let i = 1; i < arr.length; i++) {
    for (let j = i; j > 0 && arr[j] < arr[j - 1]; j--) {
      [arr[j], arr[j - 1]] = [arr[j - 1], arr[j]];
    }
  }
  return arr;
};