Un problema di heap d-ary da CLRS


10

Mi sono confuso mentre risolvo il seguente problema (domande 1–3).

Domanda

Un heap d -ary è come un heap binario, ma (con una possibile eccezione) i nodi non foglia hanno d figli invece di 2 figli.

  1. Come rappresenteresti un heap d -ary in un array?

  2. Qual è l'altezza di un heap d -ary di n elementi in termini di n e d ?

  3. Fornire un'implementazione efficiente di EXTRACT-MAX in un d -ary max-heap. Analizzare il suo tempo di esecuzione in termini di d e n .

  4. Fornire un'implementazione efficiente di INSERT in un max-heap d -ary. Analizzare il suo tempo di esecuzione in termini di d e n .

  5. Fornire un'implementazione efficiente di INCREASE-KEY ( A , i , k ), che contrassegna un errore se k <A [i] = k e quindi aggiorna la struttura heap della matrice d -ary in modo appropriato. Analizzare il suo tempo di esecuzione in termini di d e n .

La mia soluzione

  1. Assegna un arrayA[a1..an]

    root:a1level 1:a2…a2+d−1level 2:a2+d…a2+d+d2−1⋮level k:a2+∑i=1k−1di…a2+∑i=1kdi−1

    → La mia notazione sembra un po 'sofisticata. Ce n'è un altro più semplice?

  2. Let h indica l'altezza dell'heap d -ary.

    Supponiamo che l'heap sia un albero d -ary completo

    1+d+d2+..+dh=ndh+1−1d−1=nh=logd[nd−1+1]−1
  3. Questa è la mia implementazione:

    EXTRACT-MAX(A)
    1  if A.heapsize < 1
    2      error "heap underflow"
    3  max = A[1]
    4  A[1] = A[A.heapsize]
    5  A.heap-size = A.heap-size - 1
    6  MAX-HEAPIFY(A, 1)
    7  return max
    
    MAX-HEAPIFY(A, i)
    1  assign depthk-children to AUX[1..d]
    2  for k=1 to d
    3      compare A[i] with AUX[k]
    4      if A[i] <= AUX[k]
    5          exchange A[i] with AUX[k]
    6          k = largest
    7  assign AUX[1..d] back to A[depthk-children]
    8  if largest != i
    9      MAX-HEAPIFY(A, (2+(1+d+d^2+..+d^{k-1})+(largest-1) )
    
    • Il tempo di esecuzione di MAX-HEAPIFY:

      TM=d(c8∗d+(c9+..+c13)∗d+c14∗d)
      dove denota il costo dei -esimo linea sopra.ci
    • EXTRACT-MAX:

      TE=(c1+..+c7)+TM≤C∗d∗h=C∗d∗(logd[n(d−1)+1]−1)=O(dlogd[n(d−1)])

    → È una soluzione efficiente? O c'è qualcosa di sbagliato nella mia soluzione?


Penso che ci sia un piccolo errore nella domanda e nella spiegazione: L'altezza dell'heap d-ary arriva a h = (log [nd - n + 1]) - 1 // NOTA è "-n" e non "-1" e non h = (log [nd−1+1])− 1Pertanto la spiegazione sopra l'altezza non sarà valida. h = log [nd − 1 + 1] −1 = log [nd] -1 = log [n] Sebbene comunque, l'altezza dell'albero è scritta come Θ(log(n)).Nota: il log è sempre alla base d per un heap d-ary .
— Surabhi Raje,

Risposte:


10
  1. La tua soluzione è valida e segue la definizione di heap d -ary. Ma come hai sottolineato la tua notazione è un po 'sofisticata.

    È possibile utilizzare le due seguenti funzioni per recuperare parent of i -th element e j -th child of i -th element.

    d-ary-parent(i)    return ⌊(i−2)/d+1⌋

    d-ary-child(i,j)    return d(i−1)+j+1

    Ovviamente . Puoi verificare quelle funzioni controllando che1≤j≤dd-ary-parent(d-ary-child(i,j))=i

    È anche facile vedere che l'heap binario è un tipo speciale di heap -ary dove , se sostituisci con , vedrai che corrispondono alle funzioni PARENT, LEFT e RIGHT menzionate nel libro.dd=2d2

  2. Se capisco correttamente la tua risposta, usi una progressione geometrica . Nel tuo caso vai go , che è ovviamente , che in realtà è una soluzione valida e corretta. Ma solo per gestire fluttuazioni costanti potresti voler scrivere .h=logd(nd−1+1)−1logd⁡(nd)−1=logd⁡(n)+logd⁡(d)−1=logd⁡(n)+1−1=logd⁡(n)Θ(logd⁡(n))

    La ragione di ciò è che alcuni cumuli potrebbero non essere bilanciati, quindi il loro percorso più lungo e il percorso più breve possono variare di qualche costante , usando la notazione si elimina questo problema.cΘ

  3. Non è necessario implementare nuovamente la procedura fornita nel libro di testo, ma è necessario modificarla un po ', ad es. Assegnando tutti i bambini alla tabella usando e funzioni.AUXd-ary-parentd-ary-child

    Poiché non è stato modificato, dipende dal tempo di esecuzione di . Nella tua analisi ora devi usare il tempo peggiore proporzionale all'altezza e al numero di bambini che ciascun nodo deve esaminare (che è al massimo d ). Ancora una volta la tua analisi è molto precisa, alla fine hai ottenuto , che può essere trasformato in:EXTRACT-MAXMAX-HEAPIFYO(d logd⁡(n(d−1)))

    O(d logd⁡(n(d−1)))=O(d(logd⁡(n)+log⁡(d−1)))=O(d logd(n)+d logd⁡(d−1))

    Per motivi pratici possiamo sempre presumere che , quindi possiamo perdere la parte della notazione O , quindi otterremo . Qual è anche una soluzione valida. Ma non sorprende che tu possa anche analizzare il tempo di esecuzione della funzione usando il teorema del Maestro , che mostrerà che non è solo ma anche .d≪ndlogd⁡(d−1)O(dlogd⁡(n))MAX-HEAPIFYOΘ

  4. Il libro CLRS fornisce già la procedura INSERT. Che assomiglia a questo:

    INSERT(A,key)    A.heap_size=A.heap_size+1    A[A.heap_size]=−∞    INCREASE-KEY(A,A.heap_size,key)

    Può essere facilmente provato, ma il buon senso impone che la sua complessità temporale sia . È perché l'heap potrebbe essere attraversato fino alla radice.O(logd⁡(n))

  5. Proprio come INSERT, INCREASE-KEY è anche definito nel libro di testo come:

    INCREASE-KEY(A,i,key)    if key<A[i]        error"new key is smaller then current"    A[i]=key    while i>1 and A[i]>A[d-ary-parent(i)]        A[i]↔A[d-ary-parent(i)]        i=d-ary-parent(i)

    La complessità è ovviamente (vedi punto precedente).O(logd⁡(n))


Grazie! Che ne dici dell'implementazione di INCREASE-KEY e INSERT? Provo a scriverlo, ma mi ha dato due volte ricorsive di MAX-HEAPIFY. C'è una soluzione migliore? Ho trovato poche informazioni su web e wiki
— lucasKo

È quel resto dell'esercizio? In tal caso, aggiorna la tua domanda e sarò felice di rispondere al tema.
— Bartosz Przybylski,

Ho posto quelle domande sul post modificato.
— lucasKo

reimplementare la procedura INSERT? Vuoi dire, non deve chiamare la procedura che regola l'ordine all'interno dell'heap, dopo aver inserito un nuovo elemento? Non capisco ...
— lucasKo

Quella descrizione è stata un po 'sfortunata, vedi le modifiche per la clearificazione.
— Bartosz Przybylski,

1

Questa non è una risposta completa. parte b) la soluzione non è Its come sottolineato dall'utente 55463 (perché non può commentare, ma rispondere), ma ha effettuato il downgrade per mancanza di spiegazioni . Anche la risposta votata ha risolto per errore. La risposta sarà ancora Fonte: Problema 2-2. Analisi di cumuli di dary, parte b)

h=logd[nd−1+1]−1
h = Θ ( log d ( n ) )
1+d+d2+..+dh=ndh+1−1d−1=nh=logd[n(d−1)+1]−1
h=Θ(logd⁡(n))

-1

La risposta alla seconda domanda è h = log d (n (d-1) + 1) - 1 Quindi, h = log d (nd - n + 1) - 1


4
Perché questa è la risposta? Una formula senza spiegazione non aiuta davvero nessuno.
— David Richerby,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.