Data structure and algorithm (Golang implementation) (22) Sorting algorithm-Hill sorting

Hill Sort

In 1959, a named Donald L. Shell (March 1, 1924 – November 2, 2015)American Communications of the ACM 国际计算机学会月刊released a sorting algorithm, and the algorithm named Hill sorting was born.

Note: The ACM = Association for Computing MachineryInternational Computer Society, a worldwide professional organization for computer practitioners, founded in 1947, is the world's first scientific and educational computer society.

Hill sorting is an improved version of direct insertion sorting. Because direct insertion sorting is very efficient for those sequences that are almost already sorted, it achieves O(n)linear complexity, but it can only move the data one bit at a time. In the creative sorting of Hill, the data can be shifted by a nbit, and then it will nalways be reduced to the same as the direct insertion sort 1. Please see the following analysis.

Hill sorting is an insertion sorting algorithm.

1. Algorithm introduction

There is a Nsequence of numbers:

  1. First take an Ninteger less than d1, d1group the numbers whose position is an integer multiple into a group, and insert and sort these numbers directly.
  2. Then take an d1integer less than d2, d2group the numbers whose position is an integer multiple into a group, and insert and sort the numbers directly.
  3. Then take an d2integer less than d3, d3group the numbers whose position is an integer multiple into a group, and insert and sort the numbers directly.
  4. ...
  5. Until you get the integer d=1, then use direct insertion sort.

This is a grouping insertion method. The last iteration is equivalent to direct insertion sorting. The other iterations are equivalent to ndirect insertion sorting moving a distance each time . These integers are the distance between two numbers. We call them incremental.

We take half of the length of the sequence as an increment and then halve it each time until the increment is 1.

As a simple example, Hill sorts a sequence of 12 elements:, [5 9 1 6 8 14 6 49 25 4 6 3]and the increment dvalues ​​are in order 6,3,1::

x 表示不需要排序的数


取 d = 6 对 [5 x x x x x 6 x x x x x] 进行直接插入排序,没有变化。
取 d = 3 对 [5 x x 6 x x 6 x x 4 x x] 进行直接插入排序,排完序后:[4 x x 5 x x 6 x x 6 x x]。
取 d = 1 对 [4 9 1 5 8 14 6 49 25 6 6 3] 进行直接插入排序,因为 d=1 完全就是直接插入排序了。

The more ordered the sequence, the higher the efficiency of direct insertion sorting. Hill sorting uses direct insertion sorting by grouping. Because the step size is 1larger, the unordered sequence can be quickly changed into less disordered at the beginning. The number of exchanges is also reduced, until the last step of 1the direct insertion sort is used, the sequence is already relatively ordered, so the time complexity will be slightly better.

In the best case, that is, when the sequence is ordered, Hill sorting needs to perform lognsub-incremental direct insertion sorting, because the optimal time complexity of each direct insertion sorting is:, O(n)so the best time for Hill sorting O(nlogn)complexity: .

In the worst case, each iteration is the worst, assuming that the incremental sequence is:, d8 d7 d6 ... d3 d2 1then the number of directly inserted sort elements is:, n/d8 n/d7 n/d6 .... n/d3 n/d2 nthen the time complexity is calculated as the worst complexity of the direct insertion :

假设增量序列为 ⌊N/2⌋ ,每次增量取值为比上一次的一半小的最大整数。

O( (n/d8)^2 + (n/d7)^2 + (n/d6)^2 + ... + (n/d2)^2 + n^2)

= O(1/d8^2 + 1/d7^2 + 1/d6^2 + ... + 1/d2^2 + 1) * O(n^2)
= O(等比为1/2的数列和) * O(n^2)
= O(等比求和公式) * O(n^2)
= O( (1-(1/2)^n)/(1-1/2) ) * O(n^2)
= O( (1-(1/2)^n)*2 ) * O(n^2)
= O( 2-2*(1/2)^n ) * O(n^2)
= O( < 2 ) * O(n^2)

Therefore, the worst time complexity of Hill sorting is O(n^2).

Different grouping increment sequences have different time complexity, but no one can prove which sequence is the best. HibbardIncremental Sequence: 1,3,7,···,2n−1a sequence of packets can be proven widely, time complexity is: Θ(n^1.5).

The time complexity of Hill's sorting is about this range: O(n^1.3)~O(n^2)It is impossible to prove it strictly by mathematics.

Hill sorting is not stable, because each round of grouping uses direct insertion sorting, but the grouping will span npositions, resulting in two identical numbers, and the order change cannot be found if the other party cannot be found.

2. Algorithm implementation

package main

import "fmt"

// 增量序列折半的希尔排序
func ShellSort(list []int) {
    // 数组长度
    n := len(list)

    // 每次减半,直到步长为 1
    for step := n / 2; step >= 1; step /= 2 {
        // 开始插入排序,每一轮的步长为 step
        for i := step; i < n; i += step {
            for j := i - step; j >= 0; j -= step {
                // 满足插入那么交换元素
                if list[j+step] < list[j] {
                    list[j], list[j+step] = list[j+step], list[j]
                    continue
                }
                break
            }
        }
    }
}

func main() {
    list := []int{5}
    ShellSort(list)
    fmt.Println(list)

    list1 := []int{5, 9}
    ShellSort(list1)
    fmt.Println(list1)

    list2 := []int{5, 9, 1, 6, 8, 14, 6, 49, 25, 4, 6, 3}
    ShellSort(list2)
    fmt.Println(list2)

    list3 := []int{5, 9, 1, 6, 8, 14, 6, 49, 25, 4, 6, 3, 2, 4, 23, 467, 85, 23, 567, 335, 677, 33, 56, 2, 5, 33, 6, 8, 3}
    ShellSort(list3)
    fmt.Println(list3)
}

Output:

[5]
[5 9]
[1 3 4 5 6 6 6 8 9 14 25 49]
[1 2 2 3 3 4 4 5 5 6 6 6 6 8 8 9 14 23 23 25 33 33 49 56 85 335 467 567 677]

According to several sorting algorithms analyzed before, it is generally recommended to use direct insertion sorting when the array to be sorted is small-scale. Hill sorting can be used in medium-sized cases, but quick sorting, merge sorting or heaping is still required in large-scale Sort.

Series article entry

I am the star Chen, Welcome I have personally written data structures and algorithms (Golang achieve) , starting in the article to read more friendly GitBook .

Guess you like

Origin www.cnblogs.com/nima/p/12724858.html