• Keine Ergebnisse gefunden

Datenstrukturen und Algorithmen Vorlesung 8: Heapsort (K6) Joost-Pieter Katoen

N/A
N/A
Protected

Academic year: 2022

Aktie "Datenstrukturen und Algorithmen Vorlesung 8: Heapsort (K6) Joost-Pieter Katoen"

Copied!
178
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Heapsort

Datenstrukturen und Algorithmen

Vorlesung 8: Heapsort (K6)

Joost-Pieter Katoen

Lehrstuhl für Informatik 2 Software Modeling and Verification Group

https://moves.rwth-aachen.de/teaching/ss-18/dsal/

14. Mai 2018

(2)

Heapsort

Übersicht

1 Heaps

2 Heapaufbau

3 Heapsort

4 Anwendung: Prioritätswarteschlangen

(3)

Heapsort Heaps

Übersicht

1 Heaps

2 Heapaufbau

3 Heapsort

4 Anwendung: Prioritätswarteschlangen

(4)

Heapsort Heaps

Heaps

Heap (Haufen)

Ein Heapist ein Binärbaum, der Elemente mit Schlüsseln enthält und in ein Array eingebettet ist. Die Heap-Bedingung für Max-Heaps fordert:

I Der Schlüssel eines Knotens ist stets größer als (bzw. mindestens so groß wie) die Schlüssel seiner Kinder.

Weiter gilt:

I Alle Ebenen, abgesehen von evtl. der untersten, sind komplett gefüllt.

I Die Blätter befinden sich damit alle auf einer (höchstens zwei) Ebene(n).

I Die Blätter der untersten Ebene sind linksbündig angeordnet.

(5)

Heapsort Heaps

Heaps

Heap (Haufen)

Ein Heapist ein Binärbaum, der Elemente mit Schlüsseln enthält und in ein Array eingebettet ist. Die Heap-Bedingung für Max-Heaps fordert:

I Der Schlüssel eines Knotens ist stets größer als (bzw. mindestens so groß wie) die Schlüssel seiner Kinder.

Weiter gilt:

I Alle Ebenen, abgesehen von evtl. der untersten, sind komplett gefüllt.

I Die Blätter befinden sich damit alle auf einer (höchstens zwei) Ebene(n).

I Die Blätter der untersten Ebene sind linksbündig angeordnet.

(6)

Heapsort Heaps

Heaps

Heap (Haufen)

Ein Heapist ein Binärbaum, der Elemente mit Schlüsseln enthält und in ein Array eingebettet ist. Die Heap-Bedingung für Max-Heaps fordert:

I Der Schlüssel eines Knotens ist stets größer als (bzw. mindestens so groß wie) die Schlüssel seiner Kinder.

Weiter gilt:

I Alle Ebenen, abgesehen von evtl. der untersten, sind komplett gefüllt.

I Die Blätter befinden sich damit alle auf einer (höchstens zwei) Ebene(n).

I Die Blätter der untersten Ebene sind linksbündig angeordnet.

(7)

Heapsort Heaps

Heaps

Heap (Haufen)

Ein Heapist ein Binärbaum, der Elemente mit Schlüsseln enthält und in ein Array eingebettet ist. Die Heap-Bedingung für Max-Heaps fordert:

I Der Schlüssel eines Knotens ist stets größer als (bzw. mindestens so groß wie) die Schlüssel seiner Kinder.

Weiter gilt:

I Alle Ebenen, abgesehen von evtl. der untersten, sind komplett gefüllt.

I Die Blätter befinden sich damit alle auf einer (höchstens zwei) Ebene(n).

I Die Blätter der untersten Ebene sind linksbündig angeordnet.

(8)

Heapsort Heaps

Heaps

Heap (Haufen)

Ein Heapist ein Binärbaum, der Elemente mit Schlüsseln enthält und in ein Array eingebettet ist. Die Heap-Bedingung für Max-Heaps fordert:

I Der Schlüssel eines Knotens ist stets größer als (bzw. mindestens so groß wie) die Schlüssel seiner Kinder.

Weiter gilt:

I Alle Ebenen, abgesehen von evtl. der untersten, sind komplett gefüllt.

I Die Blätter befinden sich damit alle auf einer (höchstens zwei) Ebene(n).

I Die Blätter der untersten Ebene sind linksbündig angeordnet.

(9)

Heapsort Heaps

Arrayeinbettung eines Heaps

Arrayeinbettung

Das Array awird wie folgt als Binärbaum aufgefasst:

I Die Wurzel liegt in E[0].

I Das linke Kind vona[i] liegt in E[2 * i + 1].

I Das rechte Kind von a[i] liegt in E[2 * i + 2].

Beispiel

16 14 8 2 4

7 1

10

9 3

16 14 10 8 7 9 3 2 4 1

0

0 1

1

2

2 3

3 4

4 5

5

6

6 7

7 8

8 9

9

I Durch die möglichst vollständige Füllung der Ebenen werden „Löcher“ im Array vermieden.

I Vergrößert man den Baum um ein Element, so wird das Array gerade um ein Element länger.

(10)

Heapsort Heaps

Arrayeinbettung eines Heaps

Arrayeinbettung

Das Array awird wie folgt als Binärbaum aufgefasst:

I Die Wurzel liegt in E[0].

I Das linke Kind vona[i] liegt in E[2 * i + 1].

I Das rechte Kind von a[i] liegt in E[2 * i + 2].

Beispiel

16 14 8 2 4

7 1

10

9 3

16 14 10 8 7 9 3 2 4 1

0

0 1

1

2

2 3

3 4

4 5

5

6

6 7

7 8

8 9

9

I Durch die möglichst vollständige Füllung der Ebenen werden „Löcher“ im Array vermieden.

I Vergrößert man den Baum um ein Element, so wird das Array gerade um ein Element länger.

(11)

Heapsort Heaps

Arrayeinbettung eines Heaps

Arrayeinbettung

Das Array awird wie folgt als Binärbaum aufgefasst:

I Die Wurzel liegt in E[0].

I Das linke Kind vona[i] liegt in E[2 * i + 1].

I Das rechte Kind von a[i] liegt in E[2 * i + 2].

Beispiel

16 14 8 2 4

7 1

10

9 3

16 14 10 8 7 9 3 2 4 1

0

0 1

1

2

2 3

3 4

4 5

5

6

6 7

7 8

8 9

9

I Durch die möglichst vollständige Füllung der Ebenen werden „Löcher“ im Array vermieden.

I Vergrößert man den Baum um ein Element, so wird das Array gerade um ein Element länger.

(12)

Heapsort Heaps

Arrayeinbettung eines Heaps

Arrayeinbettung

Das Array awird wie folgt als Binärbaum aufgefasst:

I Die Wurzel liegt in E[0].

I Das linke Kind vona[i] liegt in E[2 * i + 1].

I Das rechte Kind von a[i] liegt in E[2 * i + 2].

Beispiel

16 14 8 2 4

7 1

10

9 3

16 14 10 8 7 9 3 2 4 1

0

0 1

1

2

2 3

3 4

4 5

5

6

6 7

7 8

8 9

9 I Durch die möglichst vollständige Füllung der Ebenen werden „Löcher“

im Array vermieden.

I Vergrößert man den Baum um ein Element, so wird das Array gerade um ein Element länger.

(13)

Heapsort Heaps

Arrayeinbettung eines Heaps

Arrayeinbettung

Das Array awird wie folgt als Binärbaum aufgefasst:

I Die Wurzel liegt in E[0].

I Das linke Kind vona[i] liegt in E[2 * i + 1].

I Das rechte Kind von a[i] liegt in E[2 * i + 2].

Beispiel

16 14 8 2 4

7 1

10

9 3

16 14 10 8 7 9 3 2 4 1

0

0 1

1

2

2 3

3 4

4 5

5

6

6 7

7 8

8 9

9 I Durch die möglichst vollständige Füllung der Ebenen werden „Löcher“

im Array vermieden.

I Vergrößert man den Baum um ein Element, so wird das Array gerade um ein Element länger.

(14)

Heapsort Heaps

Heaps – Eigenschaften

Lemma

Vergrößert man den Schlüssel der Wurzel, dann bleibt der Baum ein Heap.

Lemma

Jedes Array „ist ein Heap“ ab Position bn2c.

I Ein Heap hat bn2cinnere Knoten.

(15)

Heapsort Heaps

Heaps – Eigenschaften

Lemma

Vergrößert man den Schlüssel der Wurzel, dann bleibt der Baum ein Heap.

Lemma

Jedes Array „ist ein Heap“ ab Position bn2c.

I Ein Heap hat bn2cinnere Knoten.

(16)

Heapsort Heaps

Heaps – Eigenschaften

Lemma

Vergrößert man den Schlüssel der Wurzel, dann bleibt der Baum ein Heap.

Lemma

Jedes Array „ist ein Heap“ ab Position bn2c.

I Ein Heap hat bn2c innere Knoten.

(17)

Heapsort Heapaufbau

Übersicht

1 Heaps

2 Heapaufbau

3 Heapsort

4 Anwendung: Prioritätswarteschlangen

(18)

Heapsort Heapaufbau

Naiver Heapaufbau

2 7

3

9 4

14 15

10

8 16

2 7 10 3 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(19)

Heapsort Heapaufbau

Naiver Heapaufbau

2 7

3

9 4

14 15

10

8 16

2 7 10 3 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(20)

Heapsort Heapaufbau

Naiver Heapaufbau

7 2

3

9 4

14 15

10

8 16

7 2 10 3 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(21)

Heapsort Heapaufbau

Naiver Heapaufbau

7 2

3

9 4

14 15

10

8 16

7 2 10 3 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(22)

Heapsort Heapaufbau

Naiver Heapaufbau

10 2

3

9 4

14 15

7

8 16

10 2 7 3 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(23)

Heapsort Heapaufbau

Naiver Heapaufbau

10 2

3

9 4

14 15

7

8 16

10 2 7 3 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(24)

Heapsort Heapaufbau

Naiver Heapaufbau

10 3

2

9 4

14 15

7

8 16

10 3 7 2 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(25)

Heapsort Heapaufbau

Naiver Heapaufbau

10 3

2

9 4

14 15

7

8 16

10 3 7 2 14 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(26)

Heapsort Heapaufbau

Naiver Heapaufbau

10 14

2

9 4

3 15

7

8 16

10 14 7 2 3 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(27)

Heapsort Heapaufbau

Naiver Heapaufbau

14 10

2

9 4

3 15

7

8 16

14 10 7 2 3 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(28)

Heapsort Heapaufbau

Naiver Heapaufbau

14 10

2

9 4

3 15

7

8 16

14 10 7 2 3 8 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(29)

Heapsort Heapaufbau

Naiver Heapaufbau

14 10

2

9 4

3 15

8

7 16

14 10 8 2 3 7 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(30)

Heapsort Heapaufbau

Naiver Heapaufbau

14 10

2

9 4

3 15

8

7 16

14 10 8 2 3 7 16 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(31)

Heapsort Heapaufbau

Naiver Heapaufbau

14 10

2

9 4

3 15

16

7 8

14 10 16 2 3 7 8 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(32)

Heapsort Heapaufbau

Naiver Heapaufbau

16 10

2

9 4

3 15

14

7 8

16 10 14 2 3 7 8 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(33)

Heapsort Heapaufbau

Naiver Heapaufbau

16 10

2

9 4

3 15

14

7 8

16 10 14 2 3 7 8 9 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(34)

Heapsort Heapaufbau

Naiver Heapaufbau

16 10

9

2 4

3 15

14

7 8

16 10 14 9 3 7 8 2 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(35)

Heapsort Heapaufbau

Naiver Heapaufbau

16 10

9

2 4

3 15

14

7 8

16 10 14 9 3 7 8 2 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(36)

Heapsort Heapaufbau

Naiver Heapaufbau

16 10

9

2 4

3 15

14

7 8

16 10 14 9 3 7 8 2 4 15

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(37)

Heapsort Heapaufbau

Naiver Heapaufbau

16 10

9

2 4

15 3

14

7 8

16 10 14 9 15 7 8 2 4 3

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

I rekursiv nach oben getauscht wird, solange es größer als sein Elternknoten ist.

(38)

Heapsort Heapaufbau

Naiver Heapaufbau

16 15

9

2 4

10 3

14

7 8

16 15 14 9 10 7 8 2 4 3

Heapaufbau, naiv

Der Heap wird von oben nach unten (top-down) aufgebaut, indem

I ein neues Element möglichst weit links angefügt wird und

(39)

Heapsort Heapaufbau

Naiver Heapaufbau – Algorithmus und Analyse

1void bubble(int E[], int pos) {

2 while (pos > 0) {

3 int parent = (pos - 1) / 2;

4 if (E[parent] > E[pos]) {

5 break;

6 }

7 swap(E[parent], E[pos]);

8 pos = parent;

9 }

10}

Die Höhe k eines Heaps mit n Elementen ist beschränkt durch: n62k+1−1 ⇒ k =blog2nc

I Damit kostet jedes Einfügen k≈log2n Vergleiche.

⇒ Zum Aufbau eines Heaps mitn Elementen benötigt man Θ(n·log(n)) Vergleiche.

Es geht effizienter: heapify (auch: sink, fixheap) [Floyd 1964]

(40)

Heapsort Heapaufbau

Naiver Heapaufbau – Algorithmus und Analyse

1void bubble(int E[], int pos) {

2 while (pos > 0) {

3 int parent = (pos - 1) / 2;

4 if (E[parent] > E[pos]) {

5 break;

6 }

7 swap(E[parent], E[pos]);

8 pos = parent;

9 }

10}

Die Höhe k eines Heaps mit n Elementen ist beschränkt durch:

n62k+1−1 ⇒ k =blog2nc

I Damit kostet jedes Einfügen k≈log2n Vergleiche.

⇒ Zum Aufbau eines Heaps mitn Elementen benötigt man Θ(n·log(n)) Vergleiche.

Es geht effizienter: heapify (auch: sink, fixheap) [Floyd 1964]

(41)

Heapsort Heapaufbau

Naiver Heapaufbau – Algorithmus und Analyse

1void bubble(int E[], int pos) {

2 while (pos > 0) {

3 int parent = (pos - 1) / 2;

4 if (E[parent] > E[pos]) {

5 break;

6 }

7 swap(E[parent], E[pos]);

8 pos = parent;

9 }

10}

Die Höhe k eines Heaps mit n Elementen ist beschränkt durch:

n62k+1−1 ⇒ k =blog2nc

I Damit kostet jedes Einfügen k≈log2n Vergleiche.

⇒ Zum Aufbau eines Heaps mitn Elementen benötigt man Θ(n·log(n)) Vergleiche.

Es geht effizienter: heapify (auch: sink, fixheap) [Floyd 1964]

(42)

Heapsort Heapaufbau

Naiver Heapaufbau – Algorithmus und Analyse

1void bubble(int E[], int pos) {

2 while (pos > 0) {

3 int parent = (pos - 1) / 2;

4 if (E[parent] > E[pos]) {

5 break;

6 }

7 swap(E[parent], E[pos]);

8 pos = parent;

9 }

10}

Die Höhe k eines Heaps mit n Elementen ist beschränkt durch:

n62k+1−1 ⇒ k =blog2nc

I Damit kostet jedes Einfügen k≈log2n Vergleiche.

⇒ Zum Aufbau eines Heaps mitn Elementen benötigt man Θ(n·log(n))

Es geht effizienter: heapify (auch: sink, fixheap) [Floyd 1964]

(43)

Heapsort Heapaufbau

Naiver Heapaufbau – Algorithmus und Analyse

1void bubble(int E[], int pos) {

2 while (pos > 0) {

3 int parent = (pos - 1) / 2;

4 if (E[parent] > E[pos]) {

5 break;

6 }

7 swap(E[parent], E[pos]);

8 pos = parent;

9 }

10}

Die Höhe k eines Heaps mit n Elementen ist beschränkt durch:

n62k+1−1 ⇒ k =blog2nc

I Damit kostet jedes Einfügen k≈log2n Vergleiche.

⇒ Zum Aufbau eines Heaps mitn Elementen benötigt man Θ(n·log(n)) Vergleiche.

Es geht effizienter: heapify (auch: sink, fixheap) [Floyd 1964]

(44)

Heapsort Heapaufbau

Heapify – Strategie

Betrachte E[i] unter der Annahme, dass der rechte und linke Teilbaum bereits ein Heap ist.

I E[i] kann kleiner als seine Kinder sein.

I Wir wollen die beiden Teilbäume – Heaps – zusammen mit E[i] zu einem (Gesamt-)Heap verschmelzen.

I Dazu lassen wirE[i] in den Heap hineinsinken, sodass der Teilbaum mit WurzelE[i] ein Heap ist.

Heapify

I Finde das Maximumder Werte E[i] und seiner Kinder.

I IstE[i] bereits das größte Element, dann ist dieser gesamte Teilbaum auch ein Heap. Fertig.

I Andernfalls tauscheE[i]mit dem größten Element und führe Heapify in diesem Unterbaum weiter aus.

(45)

Heapsort Heapaufbau

Heapify – Strategie

Betrachte E[i] unter der Annahme, dass der rechte und linke Teilbaum bereits ein Heap ist.

I E[i] kann kleiner als seine Kinder sein.

I Wir wollen die beiden Teilbäume – Heaps – zusammen mit E[i] zu einem (Gesamt-)Heap verschmelzen.

I Dazu lassen wirE[i] in den Heap hineinsinken, sodass der Teilbaum mit WurzelE[i] ein Heap ist.

Heapify

I Finde das Maximumder Werte E[i] und seiner Kinder.

I IstE[i] bereits das größte Element, dann ist dieser gesamte Teilbaum auch ein Heap. Fertig.

I Andernfalls tauscheE[i]mit dem größten Element und führe Heapify in diesem Unterbaum weiter aus.

(46)

Heapsort Heapaufbau

Heapify – Strategie

Betrachte E[i] unter der Annahme, dass der rechte und linke Teilbaum bereits ein Heap ist.

I E[i] kann kleiner als seine Kinder sein.

I Wir wollen die beiden Teilbäume – Heaps – zusammen mit E[i] zu einem (Gesamt-)Heap verschmelzen.

I Dazu lassen wirE[i] in den Heap hineinsinken, sodass der Teilbaum mit WurzelE[i] ein Heap ist.

Heapify

I Finde das Maximumder Werte E[i] und seiner Kinder.

I IstE[i] bereits das größte Element, dann ist dieser gesamte Teilbaum auch ein Heap. Fertig.

I Andernfalls tauscheE[i]mit dem größten Element und führe Heapify in diesem Unterbaum weiter aus.

(47)

Heapsort Heapaufbau

Heapify – Strategie

Betrachte E[i] unter der Annahme, dass der rechte und linke Teilbaum bereits ein Heap ist.

I E[i] kann kleiner als seine Kinder sein.

I Wir wollen die beiden Teilbäume – Heaps – zusammen mit E[i] zu einem (Gesamt-)Heap verschmelzen.

I Dazu lassen wirE[i] in den Heap hineinsinken, sodass der Teilbaum mit WurzelE[i] ein Heap ist.

Heapify

I Finde das Maximumder Werte E[i] und seiner Kinder.

I IstE[i] bereits das größte Element, dann ist dieser gesamte Teilbaum auch ein Heap. Fertig.

I Andernfalls tauscheE[i]mit dem größten Element und führe Heapify in diesem Unterbaum weiter aus.

(48)

Heapsort Heapaufbau

Heapify – Strategie

Betrachte E[i] unter der Annahme, dass der rechte und linke Teilbaum bereits ein Heap ist.

I E[i] kann kleiner als seine Kinder sein.

I Wir wollen die beiden Teilbäume – Heaps – zusammen mit E[i] zu einem (Gesamt-)Heap verschmelzen.

I Dazu lassen wirE[i] in den Heap hineinsinken, sodass der Teilbaum mit WurzelE[i] ein Heap ist.

Heapify

I Finde das Maximumder Werte E[i] und seiner Kinder.

I IstE[i] bereits das größte Element, dann ist dieser gesamte Teilbaum auch ein Heap. Fertig.

I Andernfalls tauscheE[i]mit dem größten Element und führe Heapify in diesem Unterbaum weiter aus.

(49)

Heapsort Heapaufbau

Heapify – Strategie

Betrachte E[i] unter der Annahme, dass der rechte und linke Teilbaum bereits ein Heap ist.

I E[i] kann kleiner als seine Kinder sein.

I Wir wollen die beiden Teilbäume – Heaps – zusammen mit E[i] zu einem (Gesamt-)Heap verschmelzen.

I Dazu lassen wirE[i] in den Heap hineinsinken, sodass der Teilbaum mit WurzelE[i] ein Heap ist.

Heapify

I Finde das Maximumder Werte E[i] und seiner Kinder.

I IstE[i] bereits das größte Element, dann ist dieser gesamte Teilbaum auch ein Heap. Fertig.

I Andernfalls tauscheE[i] mit dem größten Element und führe Heapify in diesem Unterbaum weiter aus.

(50)

Heapsort Heapaufbau

Heapify – Algorithmus und Beispiel

1void heapify(int E[], int n, int pos) {

2 int next = 2 * pos + 1;

3 while (next < n) {

4 if (next + 1 < n &&

5 E[next + 1] > E[next]) {

6 next = next + 1;

7 }

8 if (E[pos] >= E[next]) {

9 break;

10 }

11 swap(E[pos], E[next]);

12 pos = next;

13 next = 2 * pos + 1;

14 }

15}

12 16

14

2 8

7 1

10

9 3

12 16 10 14 7 9 3 2 8 1

0

1 2

3 4 5 6

7 8 9

(51)

Heapsort Heapaufbau

Heapify – Algorithmus und Beispiel

1void heapify(int E[], int n, int pos) {

2 int next = 2 * pos + 1;

3 while (next < n) {

4 if (next + 1 < n &&

5 E[next + 1] > E[next]) {

6 next = next + 1;

7 }

8 if (E[pos] >= E[next]) {

9 break;

10 }

11 swap(E[pos], E[next]);

12 pos = next;

13 next = 2 * pos + 1;

14 }

15}

16 12

14

2 8

7 1

10

9 3

16 12 10 14 7 9 3 2 8 1

0

1 2

3 4 5 6

7 8 9

(52)

Heapsort Heapaufbau

Heapify – Algorithmus und Beispiel

1void heapify(int E[], int n, int pos) {

2 int next = 2 * pos + 1;

3 while (next < n) {

4 if (next + 1 < n &&

5 E[next + 1] > E[next]) {

6 next = next + 1;

7 }

8 if (E[pos] >= E[next]) {

9 break;

10 }

11 swap(E[pos], E[next]);

12 pos = next;

13 next = 2 * pos + 1;

14 }

15}

16 14

12

2 8

7 1

10

9 3

16 14 10 12 7 9 3 2 8 1

0

1 2

3 4 5 6

7 8 9

(53)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

3

9 4

14 15

10

8 16

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

Schleifeninvariant: Nach jedem Aufruf vonheapify(E, E.length, i) sind die Knoteni, . . . , E.length - 1 schon Wurzeln von Heaps.

(54)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

3

9 4

14 15

10

8 16

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

(55)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

3

9 4

15 14

10

8 16

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

Schleifeninvariant: Nach jedem Aufruf vonheapify(E, E.length, i) sind die Knoteni, . . . , E.length - 1 schon Wurzeln von Heaps.

(56)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

3

9 4

15 14

10

8 16

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

(57)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

9

3 4

15 14

10

8 16

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

Schleifeninvariant: Nach jedem Aufruf vonheapify(E, E.length, i) sind die Knoteni, . . . , E.length - 1 schon Wurzeln von Heaps.

(58)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

9

3 4

15 14

10

8 16

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

(59)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

9

3 4

15 14

16

8 10

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

Schleifeninvariant: Nach jedem Aufruf vonheapify(E, E.length, i) sind die Knoteni, . . . , E.length - 1 schon Wurzeln von Heaps.

(60)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 7

9

3 4

15 14

16

8 10

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

(61)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 15 9

3 4

7 14

16

8 10

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

Schleifeninvariant: Nach jedem Aufruf vonheapify(E, E.length, i) sind die Knoteni, . . . , E.length - 1 schon Wurzeln von Heaps.

(62)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 15 9

3 4

14 7

16

8 10

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

(63)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

2 15 9

3 4

14 7

16

8 10

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

Schleifeninvariant: Nach jedem Aufruf vonheapify(E, E.length, i) sind die Knoteni, . . . , E.length - 1 schon Wurzeln von Heaps.

(64)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

16 15

9

3 4

14 7

2

8 10

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

(65)

Heapsort Heapaufbau

Heapaufbau – Algorithmus und Beispiel

Strategie: Wandle das Array von unten nach oben (bottom-up) in einen Heap um.

16 15

9

3 4

14 7

10

8 2

1void buildHeap(int E[]) {

2 for (int i = E.length / 2 - 1; i >= 0; i--) {

3 heapify(E, E.length, i);

4 }

5}

Schleifeninvariant: Nach jedem Aufruf vonheapify(E, E.length, i) sind die Knoteni, . . . , E.length - 1 schon Wurzeln von Heaps.

(66)

Heapsort Heapaufbau

Konstruktion eines Heaps

Lemma

Der Algorithmus buildHeapist korrekt und terminiert.

I Initialisierung: Jeder Knoteni =bn/2c, bn/2c+ 1,. . . ist ein Blatt und damit Wurzel eines trivialen Heaps.

I Schleifeninvariante: Zu Beginn derfor-Schleife ist jeder Knoten i+1,. . .,E.length die Wurzel eines Heaps.

I In jeder Iteration sind alle Kinder des Knotensi bereits Wurzeln eines Heaps (Schleifeninvariante).

⇒ Bedingung für den Aufruf von heapifyist erfüllt.

I Dekrementierung von i stellt Schleifeninvariante wieder her.

I Terminierung: Beii = 0 ist gemäß Schleifeninvariante jeder Knoten 1, 2,. . .,n die Wurzel eines Heaps.

(67)

Heapsort Heapaufbau

Konstruktion eines Heaps

Lemma

Der Algorithmus buildHeapist korrekt und terminiert.

I Initialisierung: Jeder Knoteni =bn/2c, bn/2c+ 1,. . . ist ein Blatt und damit Wurzel eines trivialen Heaps.

I Schleifeninvariante: Zu Beginn derfor-Schleife ist jeder Knoten i+1,. . .,E.length die Wurzel eines Heaps.

I In jeder Iteration sind alle Kinder des Knotensi bereits Wurzeln eines Heaps (Schleifeninvariante).

⇒ Bedingung für den Aufruf von heapifyist erfüllt.

I Dekrementierung von i stellt Schleifeninvariante wieder her.

I Terminierung: Beii = 0 ist gemäß Schleifeninvariante jeder Knoten 1, 2,. . .,n die Wurzel eines Heaps.

(68)

Heapsort Heapaufbau

Konstruktion eines Heaps

Lemma

Der Algorithmus buildHeapist korrekt und terminiert.

I Initialisierung: Jeder Knoteni =bn/2c, bn/2c+ 1,. . . ist ein Blatt und damit Wurzel eines trivialen Heaps.

I Schleifeninvariante: Zu Beginn derfor-Schleife ist jeder Knoten i+1,. . .,E.length die Wurzel eines Heaps.

I In jeder Iteration sind alle Kinder des Knotensi bereits Wurzeln eines Heaps (Schleifeninvariante).

⇒ Bedingung für den Aufruf von heapifyist erfüllt.

I Dekrementierung von i stellt Schleifeninvariante wieder her.

I Terminierung: Beii = 0 ist gemäß Schleifeninvariante jeder Knoten 1, 2,. . .,n die Wurzel eines Heaps.

(69)

Heapsort Heapaufbau

Konstruktion eines Heaps

Lemma

Der Algorithmus buildHeapist korrekt und terminiert.

I Initialisierung: Jeder Knoteni =bn/2c, bn/2c+ 1,. . . ist ein Blatt und damit Wurzel eines trivialen Heaps.

I Schleifeninvariante: Zu Beginn derfor-Schleife ist jeder Knoten i+1,. . .,E.length die Wurzel eines Heaps.

I In jeder Iteration sind alle Kinder des Knotensi bereits Wurzeln eines Heaps (Schleifeninvariante).

⇒ Bedingung für den Aufruf von heapifyist erfüllt.

I Dekrementierung von i stellt Schleifeninvariante wieder her.

I Terminierung: Beii = 0 ist gemäß Schleifeninvariante jeder Knoten 1, 2,. . .,n die Wurzel eines Heaps.

(70)

Heapsort Heapaufbau

Konstruktion eines Heaps

Lemma

Der Algorithmus buildHeapist korrekt und terminiert.

I Initialisierung: Jeder Knoteni =bn/2c, bn/2c+ 1,. . . ist ein Blatt und damit Wurzel eines trivialen Heaps.

I Schleifeninvariante: Zu Beginn derfor-Schleife ist jeder Knoten i+1,. . .,E.length die Wurzel eines Heaps.

I In jeder Iteration sind alle Kinder des Knotensi bereits Wurzeln eines Heaps (Schleifeninvariante).

⇒ Bedingung für den Aufruf von heapifyist erfüllt.

I Dekrementierung von i stellt Schleifeninvariante wieder her.

I Terminierung: Beii = 0 ist gemäß Schleifeninvariante jeder Knoten 1, 2,. . .,n die Wurzel eines Heaps.

(71)

Heapsort Heapaufbau

Konstruktion eines Heaps

Lemma

Der Algorithmus buildHeapist korrekt und terminiert.

I Initialisierung: Jeder Knoteni =bn/2c, bn/2c+ 1,. . . ist ein Blatt und damit Wurzel eines trivialen Heaps.

I Schleifeninvariante: Zu Beginn derfor-Schleife ist jeder Knoten i+1,. . .,E.length die Wurzel eines Heaps.

I In jeder Iteration sind alle Kinder des Knotensi bereits Wurzeln eines Heaps (Schleifeninvariante).

⇒ Bedingung für den Aufruf von heapifyist erfüllt.

I Dekrementierung von i stellt Schleifeninvariante wieder her.

I Terminierung: Beii = 0 ist gemäß Schleifeninvariante jeder Knoten 1, 2,. . .,n die Wurzel eines Heaps.

(72)

Heapsort Heapsort

Übersicht

1 Heaps

2 Heapaufbau

3 Heapsort

4 Anwendung: Prioritätswarteschlangen

(73)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

19 69 12

17 17

4 2

8 13 34

41 26 17 25 19 17 8 3 6 69 12 4 2 13 34 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

5 heapify(E, i, 0);

6 }

7}

(74)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

19 69 12

17 17

4 2

8 13 34

41 26 17 25 19 17 8 3 6 69 12 4 2 13 34 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

(75)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

19 69 12

17 17

4 2

8 13 34

41 26 17 25 19 17 8 3 6 69 12 4 2 13 34 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

5 heapify(E, i, 0);

6 }

7}

(76)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

19 69 12

17 17

4 2

34 13 8

41 26 17 25 19 17 34 3 6 69 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

(77)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

19 69 12

17 17

4 2

34 13 8

41 26 17 25 19 17 34 3 6 69 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

5 heapify(E, i, 0);

6 }

7}

(78)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

19 69 12

17 17

4 2

34 13 8

41 26 17 25 19 17 34 3 6 69 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

(79)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

69 19 12

17 17

4 2

34 13 8

41 26 17 25 69 17 34 3 6 19 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

5 heapify(E, i, 0);

6 }

7}

(80)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

69 19 12

17 17

4 2

34 13 8

41 26 17 25 69 17 34 3 6 19 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

(81)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

69 19 12

17 17

4 2

34 13 8

41 26 17 25 69 17 34 3 6 19 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

5 heapify(E, i, 0);

6 }

7}

(82)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

69 19 12

34 17

4 2

17 13 8

41 26 34 25 69 17 17 3 6 19 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

(83)

Heapsort Heapsort

Heapsort – Algorithmus und Beispiel

41 26

25 3 0

6

69 19 12

34 17

4 2

17 13 8

41 26 34 25 69 17 17 3 6 19 12 4 2 13 8 0

1void heapSort(int E[]) {

2 buildHeap(E);

3 for (int i = E.length - 1; i > 0; i--) {

4 swap(E[0], E[i]);

5 heapify(E, i, 0);

6 }

7}

Referenzen

ÄHNLICHE DOKUMENTE

Teile-und-Beherrsche Algorithmen (divide and conquer) teilen das Problem in mehrere Teilprobleme auf, die dem Ausgangsproblem ähneln, jedoch von kleinerer Größe

I Ein AVL-Baum ist ein balancierter BST, bei dem für jeden Knoten die Höhe der beiden Teilbäume höchstens um 1 differiert. I Bei AVL-Bäumen wird die Höhe der Teilbäume der

2 Offene Adressierung Lineares Sondieren Quadratisches Sondieren Doppeltes Hashing.. Effizienz der

I Die Priorität eines Randknotens muss nach jeder gefundenen Kante angepasst werden. Bei einem Graph mit n Knoten und m Kanten

Wir werden zeigen, dass ein Fluss in G genau dann maximal ist, wenn sein Restnetzwerk keine augmentierende Pfade enthält. Dazu benutzen

Die Worst-Case-Laufzeit ist abhängig vom Wert eines maximalen Flusses, da der Wert des Flusses im schlimmsten Fall sich jeweils nur um eine Einheit erhöht. Joost-Pieter

Splay Trees, Fibonacci Heaps, Google’s Pagerank Algorithm, Cocktail Sort, B-Bäume, Deutsch-Schorr-Waite Baumtraversierung, Bit-State Hashing, Binäre Entscheidungsdiagramme,

I Entweder das Gummiband liegt weiterhin an, oder der neue Punkt hebt das Gummiband vom vorigen Punkt weg.. Dann ist der vorige Punkt sicherlich nicht Teil der