[JS data structure and algorithm] Algorithm implementation of Hill sorting and quick sorting

Preface

Several simple sorting algorithms have been introduced before. Before we formally enter the advanced sorting algorithm, let’s review the main idea of ​​insertion sorting: extracting a marked element, the data on the left forms a locally ordered sequence, and the data on the right is none. Ordered sequence, and then each element of the disordered sequence is inserted into the corresponding position of the ordered sequence.

text

review

If there is such a sequence:
Insert picture description here
when the last element 1 is arranged, it has the following structure:
Insert picture description here
then in the last pass, we need to move all the elements to put element 1 in the corresponding position.
Insert picture description here
This is the problem. How to make 1 move forward a little bit without having to move so many steps in the back? Then introduced Hill sorting.

Hill sort

The improvement of Hill sorting breaks through the time complexity of the previous sorting algorithm, which is O(N 2 ).

thought

Shell's Sort is a kind of insertion sort, also known as "diminishing incremental sort" (Diminishing Increment Sort), which is a more efficient and improved version of the direct insertion sort algorithm.

  • The first step is to group the subscript values ​​into certain increments, (usually N/2, and halve successively afterwards) to sort each group according to the insertion sort method.
  • In the second step, the increment is gradually reduced, and each group contains more and more keywords. When the increment is reduced to 1, the entire file is divided into one group, and the algorithm is terminated.

example
Insert picture description here

Choosing the right increment
In previous explorations, there are several well-known increment sequences.

  • Hill manuscript incremental sequence : among manuscripts sorted by Hill, the initial spacing is recommended to be N / 2 and the spacing of each pass is divided into two halves. For example, in an array of N = 100, the incremental spacing sequence will be: 50,25,12,6,3,1
  • Hibbard incremental sequence : the incremental algorithm is 2 k-1 , which is 1 , 3, 5, 7... etc. The worst complexity is O(N 3/2 ), and the average complexity is guessed to be O(N 5/4 ).
  • Sedgewick incremental sequence : The incremental algorithm is 4 i -32 i + 1, which is 1,5,19,41,109...etc.
    The worst complexity is O (N 4/3 ), and the average complexity is O (N 7/6 ).

The complexity of Hibbard incremental sequence and Sedgewick incremental sequence has not yet been confirmed, and it is also relatively difficult to implement, so we choose the incremental sequence of Hill manuscript. This method does not require additional calculation work before starting sorting.

Hill sorting algorithm implementation

// 希尔排序
ArrayList.prototype.sellSort = function () {
    
    
    // 1.获取数组的长度
    var length = this.array.length;

    // 2.选择希尔排序的原稿增量,初始间距是N / 2
    var gap = Math.floor(length / 2);

    //3.让间隔gap不断的减小
    while (gap >= 1) {
    
    
        // 4.以grp作为间隔,进行分组,分组进行插入排序
        for (var i = gap; i < length; i++) {
    
    
            var temp = this.array[i];
            var j = i;
            while (this.array[j - gap] > temp && j > gap - 1) {
    
    
                this.array[j] = this.array[j - gap];
                j -= gap;
            }

            // 5.将j位置的元素赋值给temp
            this.array[j] = temp;

        }
        // 6.重新计算新的间隔
        gap = Math.floor(gap / 2);
    }
}

Hill sorting efficiency

Time complexity is O(N 2 )

Hill sorting proposes an improved method based on the following two properties of insertion sorting:

  • Insertion sorting has high efficiency when operating on data that has almost been sorted, that is, it can achieve the efficiency of linear sorting.
  • But insertion sort is generally inefficient, because insertion sort can only move the data one bit at a time.

Quick sort

The Hill sort mentioned earlier is an improvement to insertion sort, while quick sort is an upgraded version of bubble sort. In fact, it is a lot better than bubble sort. It uses recursion.

thought

  • The first step: determine a benchmark ;
  • Step 2: Put all numbers smaller than the baseline before the baseline, and all numbers larger than the baseline after the baseline (the same numbers can be placed on either side). After this partition, the reference is located in the middle of the sequence. This process is called partition operation.
  • Recursively perform the first and second steps on the front and back of the benchmark until the sorting is completed.

Choose the right benchmark

    1. The last data of the partial sequence is selected as the reference, and then two moving pointers are used. If the number of the front pointer is greater than the number of the back pointer, they are exchanged. (The operation is simple, but not representative)
    1. A random index is used as a benchmark in the data range , and the benchmark is placed at the end of the partial sequence, and the operation is the same as the first method. (The probability is equal, but random numbers need to be implemented, no unified operation)
    1. Select the first, middle, and last three data of the partial sequence to sort the median , and use the median as the benchmark to place the second-to-last position in the sequence. (Representative, unified operation)

Comprehensive consideration, we finally choose the method of taking the median
Insert picture description here

Quick sort algorithm to achieve
2, exchange two numbers

// 交换两个数
ArrayList.prototype.swap = function (a, b) {
    
    
    var temp = this.array[a];
    this.array[a] = this.array[b];
    this.array[b] = temp;
}

1. Determine the benchmark

// 确定基准
ArrayList.prototype.median = function (left, right) {
    
    
    // 1.求出中间的位置
    var mid = Math.floor((left + right) / 2);
    // 2.判断并且进行交换 三数的冒泡思想
    if (this.array[left] > this.array[mid]) this.swap(left, mid);
    if (this.array[left] > this.array[right]) this.swap(left, right);
    if (this.array[mid] > this.array[right]) this.swap(mid, right);
    // 3.巧妙的操作: 将mid移动到right - 1的位置.
    this.swap(mid, right - 1);
    // 4.返回pivot
    return this.array[right - 1];
}
// 快速排序
ArrayList.prototype.quickSort = function () {
    
    
    this.quick(0, this.array.length - 1);
}

// 内部递归使用
ArrayList.prototype.quick = function (left, right) {
    
    

    // 1.递归结束条件
    if (left >= right) return false;
    // 2.获取基准
    var pivot = this.median(left, right);

    // 3.定义变量,开始进行交换
    var i = left;
    var j = right - 1;
    while (i < j) {
    
    
        // 3.1 找到比基准值大的数停止
        while (i < right && this.array[++i] < pivot) {
    
     }
        // 3.2 找到比基准值小的数停止
        while (j > left && this.array[--j] > pivot) {
    
     }
        // 3.3 交换与否
        if (i < j) {
    
    
            this.swap(i, j);
        } else {
    
    
            break;
        }
    }
    // 4.将基准放在正确的位置
    this.swap(i, right - 1);
    // 5.递归的调用左边序列
    this.quick(left, i - 1);
    // 6.递归的调用右边序列
    this.quick(i + 1, right);
}

Baidu Encyclopedia Lite Edition

const quickSort = (array) => {
    
    
    const sort = (arr, left = 0, right = arr.length - 1) => {
    
    
        if (left >= right) {
    
    //如果左边的索引大于等于右边的索引说明整理完毕
            return
        }
        let i = left
        let j = right
        const baseVal = arr[j] // 取无序数组最后一个数为基准值
        while (i < j) {
    
    //把所有比基准值小的数放在左边大的数放在右边
            while (i < j && arr[i] <= baseVal) {
    
     //找到一个比基准值大的数交换
                i++
            }
            arr[j] = arr[i] // 将较大的值放在右边如果没有比基准值大的数就是将自己赋值给自己(i 等于 j)
            while (j > i && arr[j] >= baseVal) {
    
     //找到一个比基准值小的数交换
                j--
            }
            arr[i] = arr[j] // 将较小的值放在左边如果没有找到比基准值小的数就是将自己赋值给自己(i 等于 j)
        }
        arr[j] = baseVal // 将基准值放至中央位置完成一次循环(这时候 j 等于 i )
        sort(arr, left, j - 1) // 将左边的无序数组重复上面的操作
        sort(arr, j + 1, right) // 将右边的无序数组重复上面的操作
    }
    const newArr = array.concat() // 为了保证这个函数是纯函数拷贝一次数组
    sort(newArr)
    return newArr
}

Hill sorting efficiency

Time complexity is O(N*logN)

to sum up

I only learned these two faster sorting algorithms. I haven't learned bucket sorting and merge sorting yet. I will share them when I have learned them. Come on together ヾ(◍°∇°◍)ノ゙.

Guess you like

Origin blog.csdn.net/weixin_42339197/article/details/102950030