Review of data structures and algorithms (a) sorting algorithm (I)

This article will introduce the most common sorting algorithm (using the JavaScript language)

PS: Here I will try to use language independent syntax to write, we should not be too concerned about the language, it is important to realize the idea of ​​the algorithm

1, bubble sort

The array is divided into ordered regions (left) and disordered region (on the right)

Every beginning from the last element of disorder, has been bubbling to the first position ahead of disorder so that it becomes ordered

function swap(A, i, j) {
    if (i === j) return
    [A[i], A[j]] = [A[j], A[i]]
}

function bubbleSort(A) {
    for (let i = 0, ii = A.length - 1; i < ii; i++) {
        let done = true
        for (let j = A.length - 1; j > i; j--) {
            if (A[j] < A[j - 1]) {
                swap(A, j, j - 1)
                done = false
            }
        }
        if (done) break
    }
}

2. Select Sort

The array is divided into ordered regions (left) and disordered region (on the right)

From each of disorder in an appropriate element, and to exchange their position to the first disordered region, so that it becomes an orderly

function swap(A, i, j) {
    if (i === j) return
    [A[i], A[j]] = [A[j], A[i]]
}

function selectionSort(A) {
    for (let i = 0, ii = A.length; i < ii; i++) {
        let minIdx = i
        for (let j = i, jj = A.length; j < jj; j++) {
            if (A[j] < A[minIdx]) minIdx = j
        }
        swap(A, i, minIdx)
    }
}

3, insertion sort

The array is divided into ordered regions (left) and disordered region (on the right)

Each time the first element of disorder in the area, has been ordered into position forward exchange area, so that it becomes ordered

function insertionSort(A) {
    for (let i = 1, ii = A.length; i < ii; i++) {
        let v = A[i]
        let j = i - 1
        while (j >= 0) {
            if (A[j] > v) {
                A[j + 1] = A[j]
                j -= 1
            } else break
        }
        A[j + 1] = v
    }
}

4, merge sort

Recursively, each time the array is divided into two, and after two arrays sort, merge two arrays

function mergeSort(arr) {
    if (arr.length <= 1) return arr
    let mid = Math.floor(arr.length / 2)
    let left = arr.slice(0, mid)
    let right = arr.slice(mid)
    return merge(mergeSort(left), mergeSort(right))
}

function merge(left, right) {
    let rs = [], lp = 0, rp = 0
    while (lp < left.length && rp < right.length)
        (left[lp] < right[rp]) ? rs.push(left[lp++]) : rs.push(right[rp++])
    while (lp < left.length)
        rs.push(left[lp++])
    while (rp < right.length)
        rs.push(right[rp++])
    return rs
}

Optimization: In-situ sequencing, thus reducing the new array

function mergeSortHelper(A, T, i, j) {
    if (i === j) return
    let m = Math.floor((i + j) / 2)
    mergeSortHelper(A, T, i, m)
    mergeSortHelper(A, T, m + 1, j)
    // merge
    for (let k = i; k <= j; k++) T[k] = A[k]
    let l = i, r = m + 1
    for (let curr = i; curr <= j; curr++) {
        if (l > m) A[curr] = T[r++]
        else if (r > j) A[curr] = T[l++]
        else if (T[l] < T[r]) A[curr] = T[l++]
        else A[curr] = T[r++]
    }
}

function mergeSort(A) {
    mergeSortHelper(A, [], 0, A.length - 1)
}

Optimization: temporary array latter part of reverse insertion, which can not detect the boundary case

function mergeSortHelper(A, T, i, j) {
    if (i === j) return
    let m = Math.floor((i + j) / 2)
    mergeSortHelper(A, T, i, m)
    mergeSortHelper(A, T, m + 1, j)
    // merge
    for (let k = i; k <= m; k++) T[k] = A[k]
    for (let k = 1; k <= j - m; k++) T[j - k + 1] = A[k + m]
    let l = i, r = j
    for (let curr = i; curr <= j; curr++) {
        if (T[l] < T[r]) A[curr] = T[l++]
        else A[curr] = T[r--]
    }
}

function mergeSort(A) {
    mergeSortHelper(A, [], 0, A.length - 1)
}

5, Quick Sort

Recursively, each time selecting a reference in the array, the array according to the reference will be divided into two, and after two sorted arrays, arrays and splicing two reference

function quickSort(arr) {
    if (arr.length <= 1) return arr
    // find pivot
    let pivotIndex = Math.floor(arr.length / 2)
    let pivot = arr.splice(pivotIndex, 1)[0]
    // partition
    let left = arr.filter(item => item <= pivot)
    let right = arr.filter(item => item > pivot)
    // recursive
    return [...quickSort(left), pivot, ...quickSort(right)]
}

Optimization: In-situ sequencing, thus reducing the new array

function swap(A, i, j) {
    if (i === j) return
    [A[i], A[j]] = [A[j], A[i]]
}

function quickSortHelper(A, i, j) {
    if (j <= i) return
    // find pivot
    let pivotIndex = Math.floor((i + j) / 2)
    let pivot = A[pivotIndex]
    // put pivot at last
    swap(A, pivotIndex, j)
    // partition
    let l = i - 1
    let r = j
    do {
        while (A[++l] < pivot) {}
        while (l < r && pivot < A[--r]) {}
        swap(A, l, r)
    } while (l < r);
    // put pivot in place
    swap(A, j, l)
    // recursive
    quickSortHelper(A, i, l - 1)
    quickSortHelper(A, l + 1, j)
}

function quickSort(A) {
    quickSortHelper(A, 0, A.length - 1)
}

Optimization: use recursion stack replacement

function swap(A, i, j) {
    if (i === j) return
    [A[i], A[j]] = [A[j], A[i]]
}

function quickSortHelper(A, i, j) {
    let stack = []
    stack.push(i)
    stack.push(j)
    while (stack.length > 0) {
        j = stack.pop()
        i = stack.pop()
        // find pivot
        let pivotIndex = Math.floor((i + j) / 2)
        let pivot = A[pivotIndex]
        // put pivot at last
        swap(A, pivotIndex, j)
        // partition
        let l = i - 1
        let r = j
        do {
            while (A[++l] < pivot) {}
            while (l < r && pivot < A[--r]) {}
            swap(A, l, r)
        } while (l < r);
        // undo the last swap
        swap(A, l, r)
        // put pivot in place
        swap(A, l, j)
        // load up stack
        if (l - 1 > i) {
            stack.push(i)
            stack.push(l - 1)
        }
        if (j > l + 1) {
            stack.push(l + 1)
            stack.push(j)
        }
    }
}

function quickSort(A) {
    quickSortHelper(A, 0, A.length - 1)
}

6, the test program

var origin = Array.from({ length: 100000 }, x => Math.floor(Math.random() * 100000))
var arr4bubble = JSON.parse(JSON.stringify(origin))
var arr4selection = JSON.parse(JSON.stringify(origin))
var arr4insertion = JSON.parse(JSON.stringify(origin))
var arr4merge = JSON.parse(JSON.stringify(origin))
var arr4quick = JSON.parse(JSON.stringify(origin))

console.time('q')
quickSort(arr4quick)
console.timeEnd('q')

console.time('m')
mergeSort(arr4merge)
console.timeEnd('m')

console.time('i')
insertionSort(arr4insertion)
console.timeEnd('i')

console.time('s')
selectionSort(arr4selection)
console.timeEnd('s')

console.time('b')
bubbleSort(arr4bubble)
console.timeEnd('b')

[Read More Data Structures and Algorithms series of articles, look at the data structures and algorithms review ]

Guess you like

Origin www.cnblogs.com/wsmrzx/p/12545457.html