Structure de données et algorithme (implémentation Golang) (22) Algorithme de tri - Tri Hill

Tri des collines

En 1959, un Donald L. Shell (March 1, 1924 – November 2, 2015)Américain nommé a Communications of the ACM 国际计算机学会月刊publié un algorithme de tri, et l'algorithme nommé Hill sorting est né.

Remarque: La ACM = Association for Computing MachineryInternational Computer Society, une organisation professionnelle mondiale pour les praticiens de l'informatique, fondée en 1947, est la première société informatique et scientifique au monde.

Le tri en côte est une version améliorée du tri par insertion directe. Étant donné que le tri par insertion directe est très efficace pour les séquences qui sont presque déjà triées, il atteint O(n)une complexité linéaire, mais il ne peut déplacer les données qu'un bit à la fois. Dans le tri créatif de Hill, les données peuvent être nlégèrement décalées , puis elles seront ntoujours réduites au même que le tri par insertion directe 1. Veuillez consulter l'analyse suivante.

Le tri en côte est un algorithme de tri par insertion.

1. Introduction à l'algorithme

Il y a une Nséquence de nombres:

  1. Prenez d'abord un Nentier inférieur à d1, d1groupez les nombres dont la position est un multiple entier dans un groupe, puis insérez et triez ces nombres directement.
  2. Prenez ensuite un d1entier inférieur à d2, d2groupez les nombres dont la position est un multiple entier dans un groupe, puis insérez et triez les nombres directement.
  3. Prenez ensuite un d2entier inférieur à d3, d3groupez les nombres dont la position est un multiple entier dans un groupe, puis insérez et triez les nombres directement.
  4. ...
  5. Jusqu'à ce que vous obteniez l'entier d=1, utilisez le tri par insertion directe.

Il s'agit d'une méthode d'insertion par regroupement. La dernière itération équivaut à un tri par insertion directe. Les autres itérations sont équivalentes à nun tri par insertion directe se déplaçant chaque fois sur une distance. Ces nombres entiers sont la distance entre deux nombres. Nous les appelons incrémentiels.

Nous prenons la moitié de la longueur de la séquence comme un incrément, puis la divisons par deux jusqu'à ce que l'incrément soit égal à 1.

Comme exemple simple, Hill trie une séquence de 12 éléments:, [5 9 1 6 8 14 6 49 25 4 6 3]et les dvaleurs d' incrémentation sont dans l'ordre 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 完全就是直接插入排序了。

Plus la séquence est ordonnée, plus l'efficacité du tri par insertion directe est élevée. Le tri par colline utilise le tri par insertion directe par regroupement. La taille de l'étape étant 1plus grande, la séquence non ordonnée peut être rapidement transformée en moins désordonnée au début. Le nombre d'échanges est également réduit, jusqu'à ce que la dernière étape du 1tri par insertion directe soit utilisée, la séquence est déjà relativement ordonnée, donc la complexité temporelle sera légèrement meilleure.

Dans le meilleur des cas, c'est-à-dire lorsque la séquence est ordonnée, le tri Hill doit effectuer lognun tri par insertion directe sous-incrémentiel, car la complexité temporelle optimale de chaque tri par insertion directe est:, O(n)donc le meilleur moment pour le tri Hill. O(nlogn)complexité: .

Dans le pire des cas, chaque itération est la pire, en supposant que la séquence incrémentielle est:, d8 d7 d6 ... d3 d2 1alors le nombre d'éléments de tri directement insérés est:, n/d8 n/d7 n/d6 .... n/d3 n/d2 nalors la complexité temporelle est calculée comme la pire complexité de l'insertion directe :

假设增量序列为 ⌊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)

Par conséquent, la pire complexité temporelle du tri Hill est O(n^2).

Différentes séquences d'incrément de regroupement ont une complexité temporelle différente, mais personne ne peut prouver quelle séquence est la meilleure. HibbardSéquence incrémentale: 1,3,7,···,2n−1une séquence de paquets peut être largement prouvé, la complexité temporelle est: Θ(n^1.5).

La complexité temporelle du tri de Hill porte sur cette plage: O(n^1.3)~O(n^2)il est impossible de le prouver strictement par les mathématiques.

Le tri en côte n'est pas stable, car chaque cycle de regroupement utilise le tri par insertion directe, mais le regroupement s'étendra sur les npositions, résultant en deux nombres identiques, et le changement d'ordre ne pourra pas être trouvé si l'autre partie ne peut pas être trouvée.

2. Implémentation de l'algorithme

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)
}

Sortie:

[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]

Selon plusieurs algorithmes de tri analysés précédemment, il est généralement recommandé d'utiliser le tri par insertion directe lorsque le tableau à trier est à petite échelle. Le tri par colline peut être utilisé dans des cas de taille moyenne, mais un tri rapide, un tri par fusion ou un amoncellement est toujours requis à grande échelle. Trier.

Entrée d'article de série

Je suis la star Chen, bienvenue J'ai personnellement écrit des structures de données et algorithmes (golang atteindre) , à partir de l'article à lire GitBook plus convivial .

Je suppose que tu aimes

Origine www.cnblogs.com/nima/p/12724858.html
conseillé
Classement