web-dev-qa-db-fra.com

Pourquoi le tri en tas a-t-il une complexité d'espace de O (1)?

Je comprends que le tri rapide et le tri par fusion nécessitent O(n) un espace auxiliaire pour les sous-tableaux temporaires qui sont construits, et le tri rapide sur place nécessite O(log n) un espace auxiliaire pour les cadres de pile récursifs . Mais pour le tri de tas, il semble qu'il y ait aussi le pire des cas de l'espace auxiliaire O(n) pour construire le tas temporaire, même si les nœuds ne sont que des pointeurs vers les éléments réels.

Je suis tombé sur cette explication :

Seul O(1) espace supplémentaire est nécessaire car le tas est construit à l'intérieur du tableau à trier.

Mais je pense que cela signifie que le tableau d'origine devait nécessairement déjà être implémenté comme une sorte d'arbre? Si le tableau d'origine n'était qu'un vecteur, il semble que la mémoire d'un tas devrait encore être allouée.

32
Herman Tran

Les données d'un tableau peuvent être réorganisées en un tas, sur place. L'algorithme pour cela est en fait étonnamment simple, mais je n'entrerai pas dans les détails ici.

Pour un tri de segment de mémoire, vous organisez les données afin qu'elles forment un segment de mémoire en place, avec le plus petit élément à l'arrière (std::make_heap). Ensuite, vous permutez le dernier élément du tableau (le plus petit élément du tas), avec le premier élément du tableau (un grand nombre), puis mélangez ce grand élément dans le tas jusqu'à ce qu'il soit dans une nouvelle position appropriée et que le tas soit à nouveau un nouveau tas min, avec le plus petit élément restant dans le dernier élément du tableau. (std::pop_heap)

data:         1 4 7 2 5 8 9 3 6 0

make_heap:   [8 7 9 3 4 5 6 2 1 0] <- this is a min-heap, smallest on right

pop_heap(1): [0 7 9 3 4 5 6 2 1 8] <- swap first and last elements
pop_heap(2): 0 [7 9 3 4 8 6 2 5 1] <- shuffle the 8 down the heap

pop_heap(1): 0 1 [9 3 4 8 6 2 5 7] <- swap first and last elements
pop_heap(2): 0 1 [9 7 4 8 6 3 5 2] <- shuffle the 7 down the heap

etc

Aucune donnée ne doit donc être stockée ailleurs, sauf peut-être pendant l'étape de permutation.

Pour la visualisation, voici ce tas original affiché sous une forme standard

make_heap 
           0
     2           1
  3     4     5     6
               8   7 9
pop_heap
           8                           1                           1
     2           1               2           8               2           5 
  3     4     5     6    ->   3     4     5     6    ->   3     4     8     6 
                   7 9                         7 9                         7 9
31
Mooing Duck

L'astuce ici est que le tas est un arbre binaire complet, vous pouvez simplement utiliser un tableau simple, et pour l'élément i, son parent serait l'élément i/2.

2
zw324

Le tri en tas est un algorithme sur place; il ne nécessite aucun espace supplémentaire. Les éléments sont réorganisés lors de chaque récursivité uniquement à l'intérieur du même tableau.

Il donne la perception qu'un tas ou un arbre binaire est en cours de formation, mais dans le scénario réel, aucun arbre ou tas ne se forme.

0
Parveen Kumar
HEAP-SORT(A)
{
BUILD-MAX-HEAP(A)
if(i= A.length down to 2)
    exchange A[i] with A[1]
    A.heapSize = A.heapSize-1
    MAX-HEAPIFY(A,1)

}

i/p est stocké dans un tableau qui est transmis à l'algorithme de tri en tas - HEAP-SORT (A). Le tableau A est interprété comme un arbre et après BUILD-MAX-HEAP hors de celui-ci et en échangeant le dernier élément avec la racine et en réduisant la taille du tas à chaque fois, puis appelez MAX-HEAPIFY (A, 1) dessus.

ce toutes les opérations que nous effectuons à l'intérieur de ce tableau (A) seulement - qui est donné comme algorithme i/p. nous n'utilisons aucun espace supplémentaire lors de cette opération. Donc complexité de l'espace - O (1).

0
Rudra