Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端需要掌握的算法之——插入排序(Insertion sort) #4

Open
jnoodle opened this issue Aug 21, 2018 · 0 comments
Open
Labels
FrontEnd 前端

Comments

@jnoodle
Copy link
Owner

jnoodle commented Aug 21, 2018

Bad programmers worry about the code. Good programmers worry about data structures and their relationships. —— Linus Torvalds

插入排序(Insertion sort) 就是每一步都将一个待排序的元素,按照它的大小,插入到已经排序的元素中的适当位置,一直重复,直到全部待排序的元素插入完毕。

具体步骤如下(假设是从小到大排序):

  1. 将待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列
  2. 从后向前依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置

插入排序算法复杂度是:O(n2)。

  • 最坏时间复杂度 O(n2)
  • 最优时间复杂度 O(n)
  • 平均时间复杂度 O(n2)
  • 最坏空间复杂度 总共 O(n),需要辅助空间 O(1)

image

上代码:

// 随机生成一个乱序数组
let arr = Array.from(new Array(10), () => ~~(Math.random() * 100))

console.log('Source array is [ %s ]\n', arr.join(', '))

// 插入排序
function insertionSort(arr) {
    const len = arr.length
    let step = 1;
    // i 为未排序序列 index,j 为已排序序列 index,起始 arr[0] 作为已排序序列,所以 i 从 1 开始
    for (let i = 1; i < len; i++) {
        // 选取 arr[i] 作为待排序元素,从右到左依次与左侧的已排序序列比较
        let insertItem = arr[i]
        for (let j = i - 1; j >= -1; j--) {
            // j === -1 代表已经比较到第一个元素,都没有发现更小的,则需要插入到最前端
            // 这里采用直接插入的方式,也可以选择依次交换的方式
            if (j === -1 || arr[j] < insertItem) {
                if (j + 1 !== i) {
                    // 把元素从 i 插入到 j + 1 位置
                    arr.splice(j + 1, 0, insertItem); // 插入元素
                    arr.splice(i + 1, 1); // 删除元素
                }
                console.log('Step %d: [ %s ] (insert %s from %d to %d, %s)', step++, arr.join(', '), insertItem, i, j + 1, j + 1 !== i ? 'Moved' : 'No move')
                break;
            }
        }
    }
    console.log('\nSorted array is [ %s ]', arr.join(', '))
}

insertionSort(arr)

结果:

Source array is [ 38, 12, 34, 65, 10, 47, 51, 55, 27, 11 ]

Step 1: [ 12, 38, 34, 65, 10, 47, 51, 55, 27, 11 ] (insert 12 from 1 to 0, Moved)
Step 2: [ 12, 34, 38, 65, 10, 47, 51, 55, 27, 11 ] (insert 34 from 2 to 1, Moved)
Step 3: [ 12, 34, 38, 65, 10, 47, 51, 55, 27, 11 ] (insert 65 from 3 to 3, No move)
Step 4: [ 10, 12, 34, 38, 65, 47, 51, 55, 27, 11 ] (insert 10 from 4 to 0, Moved)
Step 5: [ 10, 12, 34, 38, 47, 65, 51, 55, 27, 11 ] (insert 47 from 5 to 4, Moved)
Step 6: [ 10, 12, 34, 38, 47, 51, 65, 55, 27, 11 ] (insert 51 from 6 to 5, Moved)
Step 7: [ 10, 12, 34, 38, 47, 51, 55, 65, 27, 11 ] (insert 55 from 7 to 6, Moved)
Step 8: [ 10, 12, 27, 34, 38, 47, 51, 55, 65, 11 ] (insert 27 from 8 to 2, Moved)
Step 9: [ 10, 11, 12, 27, 34, 38, 47, 51, 55, 65 ] (insert 11 from 9 to 1, Moved)

Sorted array is [ 10, 11, 12, 27, 34, 38, 47, 51, 55, 65 ]

注意:这里采用直接插入的方式,也可以选择依次交换的方式,代码相对会简单一点。

@jnoodle jnoodle added the FrontEnd 前端 label Aug 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
FrontEnd 前端
Projects
None yet
Development

No branches or pull requests

1 participant