Acht Sortieralgorithmen – Hill Sorting (Gift Understanding)

Inhaltsverzeichnis

Hill-Sorte

Konzept

Algorithmus-Idee

Animation

Code wird wie folgt angezeigt

Komplexitätsanalyse

Zeitkomplexitätstest

Operationsergebnis

 Vollständiger Code

 Es ist nicht einfach zu erstellen. Wenn dieser Blog für Sie hilfreich ist, denken Sie bitte daran, eine Nachricht zu hinterlassen und ihn zu liken.


Hill-Sorte

Konzept

Die Hill-Sortierung ist eine Art Einfügungssortierung, die eine Optimierung der Direkteinfügungssortierung darstellt. Seine Besonderheit liegt im Gruppieren und Sortieren.

Algorithmus-Idee

Die Hill-Sortierung ist nach ihrem Erfinder Hill benannt, der die Effizienz der Einfügungssortierung analysierte und zu folgenden Schlussfolgerungen kam:

        1. Im schlimmsten Fall, wenn die zu sortierende Sequenz in umgekehrter Reihenfolge ist, dauert es O(n^2) Zeit.
        2. Im besten Fall, wenn die zu sortierende Sequenz in der richtigen Reihenfolge ist, dauert es O(n) Zeit


Also dachte Hill: Wenn die zu sortierende Sequenz zuerst vorsortiert werden kann, sodass die zu sortierende Sequenz nahe an der Reihenfolge liegt, wird dann eine Einfügungssortierung für die Sequenz durchgeführt. Daher beträgt die zeitliche Komplexität der direkten Einfügungssortierung zu diesem Zeitpunkt O(n) , sodass nur die zeitliche Komplexität der Vorsortierstufe so gesteuert werden muss, dass sie kleiner als O(n^2) und dann die Gesamtzeitkomplexität ist ist niedriger als die der Einfügungssortierung.

Wie sollte also die konkrete Vorsortierung erfolgen, damit die zeitliche Komplexität den Anforderungen gerecht werden kann?

        1. Wählen Sie zunächst eine ganzzahlige Lücke kleiner als n (im Allgemeinen wird n/2 als Lücke verwendet) als erstes Inkrement aus, gruppieren Sie dann alle Elemente mit einem Abstand von Lücke in einer Gruppe und führen Sie eine Einfügungssortierung für jede Gruppe durch. 2.
        Wiederholen Schritt 1, bis die Lücke gleich 1 ist, und Stopp. Zu diesem Zeitpunkt wird die gesamte Sequenz in eine Gruppe unterteilt, eine Direkteinfügungssortierung durchgeführt und die Sortierung abgeschlossen.

Sie fragen sich vielleicht, warum der Unterschied zwischen groß und klein ist?

Denn je größer die Lücke, desto schneller bewegen sich die Daten und benötigen weniger Zeit; je kleiner die Lücke, desto langsamer bewegen sich die Daten und benötigen mehr Zeit. Vergrößern Sie die Lücke in der Anfangsphase, damit die Daten schnell in die Nähe ihrer entsprechenden Position verschoben werden können, wodurch die Anzahl der Verschiebungen verringert wird.

Animation

[Bildübertragung mit externem Link fehlgeschlagen, die Quellseite verfügt möglicherweise über einen Anti-Leeching-Mechanismus. Es wird empfohlen, das Bild zu speichern und direkt hochzuladen (img-3Is6Arbg-1668608929993) (Hillsort.assets/animation.gif)]

 

Nehmen wir ein Beispiel:

 

Zunächst beträgt die Lücke 5. Zu diesem Zeitpunkt werden die Elemente mit einem Abstand von 5 in eine Gruppe unterteilt (insgesamt fünf Gruppen mit jeweils zwei Elementen), und dann wird jede Gruppe separat eingefügt und sortiert.

 

Die Lücke wird auf 2 halbiert. Zu diesem Zeitpunkt werden die Elemente mit einem Abstand von 2 in eine Gruppe unterteilt (insgesamt zwei Gruppen mit fünf Elementen in jeder Gruppe), und dann wird jede Gruppe separat eingefügt und sortiert.

 

Die Lücke wird erneut auf 1 halbiert. Zu diesem Zeitpunkt werden alle Elemente in eine Gruppe unterteilt, diese wird eingefügt und sortiert, und die Einfügungssortierung ist abgeschlossen.

 

In diesem Beispiel handelt es sich bei den ersten beiden Fahrten um die Vorsortierung der Hill-Sortierung und bei der letzten Fahrt um die Einfügungssortierung der Hill-Sortierung
 

Code wird wie folgt angezeigt

public static void shellSort(int[] a){
        int gal = a.length;
        while(gal>1) {
            int j = 0;
            gal/=2;   //特别之处gal  分组排序 5 3 1.。。

            //核心
            for (int i = gal; i < a.length; i++) {
                j = i-gal;
                if(a[j] > a[i]) {
                    int tmp = a[j];
                    a[j] = a[i];
                    a[i] = tmp;
                }
            }

        }
    }

Komplexitätsanalyse

Die zeitliche Komplexität der Hill-Sortierung ist nicht einfach zu berechnen, da es viele Möglichkeiten gibt, den Wert der Lücke zu berechnen, was die Berechnung erschwert. Das Folgende ist die Erklärung der beiden Lehrer im Buch.

 

 „Datenstruktur Beschreibung mit objektorientierter Methode und C++ “ --- Yin Renkun

     Zeitkomplexität  n^1,3 - n^1,5 Kann ich nicht sagen. Sie hängt mit der Anzahl der Lücken in jeder Gruppe zusammen.
     Raumkomplexität O(1)
     Stabilität Instabil Wenn mehrere identische Zahlen vorhanden sind, ändert sich die relative Position nach dem Sortieren

Zeitkomplexitätstest

Versuchen wir als Nächstes, es mit vielen Daten zu testen.

int[] a = new int[10_0000]; //100.000 Datentest

1. Die Funktion orderArray wird implementiert, um eine grundlegende geordnete Sequenz zu generieren, die von klein nach groß angeordnet ist.

public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
    }


2. Die Funktion notOrderArray generiert eine umgekehrte Reihenfolge, die vom größten zum kleinsten sortiert ist.

public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        }
 
    }


3. Die Funktion randomArray generiert ein zufälliges ungeordnetes Array.

 public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
    }


4. Die Funktion testInsertSort testet den Rückgabewert von System.currentTimeMillis() in Millisekunden .

 

 public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        shellSort(tmpArray);
        long endTime = System.currentTimeMillis();  //返回单位是毫秒
        System.out.println("直接插入排序耗时:"+(endTime-startTime));
    }


5. Ausführung des Hauptfunktionsaufrufs

public static void main(String[] args) {
 
 
        int[] a = new int[10_0000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);
 
        //倒序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);
 
        //随机乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);
 
    }

Operationsergebnis

         

 Sowohl die Hill-Sortierung als auch die Direkteinfügungssortierung sind Einfügungssortierungen, und die Hill-Sortierung ist eine Optimierung der Direkteinfügungssortierung. Vergleichen Sie die Testergebnisse der Direkteinfügungssortierung oben .

            

 Es ist ersichtlich, dass die Hill-Sortierung tatsächlich viel schneller ist. Und zeitaufwändig und stabil.

 Vollständiger Code

import java.util.Random;

public class sort {

    public static void main(String[] args) {
       
        int[] a = new int[10_0000];
        //有序
        System.out.println("基本有序数列");
        orderArray(a);
        testInsertSort(a);

        //无序
        System.out.println("逆序数列");
        notOrderArray(a);
        testInsertSort(a);

        //乱序
        System.out.println("无序数列");
        randomArray(a);
        testInsertSort(a);


    }

    //希尔排序  是插入排序的优化
    //时间复杂度  n^1.3 -- n^1.5  说不准  与每次分组的个数有关
    //空间复杂度 O(1)
    //稳定性 不稳定 当有几个相同的数字时,排序后相对位置会改变
    public static void shellSort(int[] a){
        int gal = a.length;
        while(gal>1) {
            int j = 0;
            gal/=2;   //特别之处gal  分组排序 5 3 1.。。

            //核心
            for (int i = gal; i < a.length; i++) {
                j = i-gal;
                if(a[j] > a[i]) {
                    int tmp = a[j];
                    a[j] = a[i];
                    a[i] = tmp;
                }
            }

        }
    }

    //生成有序数组  从小到大排列
    public static void orderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = i;
        }
    }

    //n无序 其实就是从大到小排列
    public static void notOrderArray(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] = a.length-i;
        }

    }

    //乱序 随机生成序列
    public static void randomArray(int[] a) {
        Random random = new Random();
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(10_0000);
        }
    }

    //大量数据测试
    public static void testInsertSort(int[] a){
        int[] tmpArray = Arrays.copyOf(a,a.length);
        long startTime = System.currentTimeMillis();    //注意用long接收
        shellSort(tmpArray);
        long endTime = System.currentTimeMillis();
        System.out.println("希尔排序耗时:"+(endTime-startTime));
    }

}

 Es ist nicht einfach zu erstellen. Wenn dieser Blog für Sie hilfreich ist, denken Sie bitte daran, eine Nachricht zu hinterlassen und ihn zu liken.

Ich denke du magst

Origin blog.csdn.net/m0_73381672/article/details/132020520
Empfohlen
Rangfolge