Tri par tas de base

1. Concept et introduction

Le tri par tas est un algorithme de tri conçu en utilisant la structure de données tas.

Un tas est une structure qui approxime un arbre binaire complet et satisfait simultanément la propriété de tas : c'est-à-dire que la clé ou l'indice d'un nœud enfant est toujours inférieur (ou supérieur) à celui de son nœud parent.

II. Instructions d'application

Notre processus précédent de construction d'un tas consistait à insérer les données une par une dans le tas en appelant la méthode insert à l'aide de shift up ; la complexité temporelle de cet algorithme estO(nlogn), le processus de construction d'un tri par tas introduit dans cette section est appeléHeapify, la complexité temporelle de l'algorithme estO(n)。

III. Diagramme du processus

Un arbre binaire complet possède une propriété importante : l'indice du premier nœud non-feuille estn/2la valeur d'indice obtenue en prenant la partie entière, oùnest le nombre d'éléments (en supposant que les indices de tableau commencent à 1).

La position à l'indice 5 est le premier nœud non-feuille. À partir de celui-ci, nous avançons un par un, en effectuant l'opération de descente sur chaque élément en tant que nœud racine afin de satisfaire la propriété du tas max.

Après l'opération de descente à l'indice 5, 22 et 62 échangent leurs positions.

Effectuer l'opération de descente sur l'élément à l'indice 4.

Effectuer l'opération de descente sur l'élément à l'indice 3.

Effectuer l'opération de descente sur l'élément à l'indice 2.

Enfin, effectuez l'opération de descente sur le nœud racine, et l'ensemble du processus de tri par tas est terminé.

IV. Exemple de code Java

Téléchargement du paquet de code source :Télécharger

Code du fichier src/example/heap/Heapify.java :

package example.heap;

import example.sort.SortTestHelper;

/**
* Utiliser heapify pour effectuer le tri par tas
 */

public class Heapify<T extends Comparable> {

    protected T[] data;
    protected int count;
    protected int capacity;

    // Constructeur, crée un tas max à partir d'un tableau donné
    // Le processus de construction du tas a une complexité temporelle O(n)
    public Heapify(T arr[]){

        int n = arr.length;

        data = (T[])new Comparable[n+1];
        capacity = n;

        for( int i = 0 ; i < n ; i ++ )
            data[i+1] = arr[i];
        count = n;
        // Commencer à partir du premier élément qui n'est pas un nœud feuille
        for( int i = count/2 ; i >= 1 ; i -- )
            shiftDown(i);
    }
    // Retourne le nombre d'éléments dans le tas
    public int size(){
        return count;
    }
    // Retourne un booléen indiquant si le tas est vide
    public boolean isEmpty(){
        return count == 0;
    }
    // Insérer un nouvel élément item dans le tas max
    public void insert(T item){
        assert count + 1 <= capacity;
        data⟦⟧count[count+1] = item;
        count ++;
        shiftUp(count);
    }
    // le sommet du tas max, c'est-à-dire la plus grande donnée stockée dans le tas
    public T extractMax(){
        assert count > 0;
        T ret = data[1];
        swap( 1 , count );
        count --;
        shiftDown(1);
        return ret;
    }
    // Obtenir l'élément au sommet du tas max
    public T getMax(){
        assert( count > 0 );
        return data[1];
    }


    // Échanger les deux éléments aux indices i et j dans le tas
    private void swap(int i, int j){
        T t = data[i];
        data[i] = data[j];
        data[j] = t;
    }

    //********************
    //* Fonctions utilitaires de base du tas max
    //********************
    private void shiftUp(int k){

        while( k > 1 && data[k/2].compareTo(data[k]) < 0 ){
            swap(k, k/2);
            k /= 2;
        }
    }

    private void shiftDown(int k){

        while( 2*k <= count ){
            int j = 2*k; // Dans cette itération de boucle, data[k] et data[j] échangent leurs positions
            if( j+1 <= count && data[j+1].compareTo(data[j]) > 0 )
                j ++;
            // data[j] est le maximum de data[2*k] et data[2*k+1]

            if( data[k].compareTo(data[j]) >= 0 ) break;
            swap(k, j);
            k = j;
        }
    }

    // Tester heapify
    public static void main(String[] args) {
        int N = 100;
        Integer[] arr = SortTestHelper.generateRandomArray(N, 0, 100000);
        Heapify<Integer> heapify = new Heapify<Integer>(arr);
        // Extraire progressivement les données dans heapify à l'aide de extractMax
        // L'ordre d'extraction doit être du plus grand au plus petit
        for( int i = 0 ; i < N ; i ++ ){
            arr[i] = heapify.extractMax();
            System.out.print(arr[i] + " ");
        }

        // S'assurer que le tableau arr est trié du plus grand au plus petit
        for( int i = 1 ; i < N ; i ++ )
            assert arr[i-1] >= arr[i];
    }
}
autres extensions