Sortierte Folgen (Operationen, Anwendungen)

Werbung
Sortierte Folgen
250
Sortierte Folgen:
he1 , . . . , en i mit e1  · · ·  en
„kennzeichnende“ Funktion:
M.locate(k):= addressof min {e 2 M : e
k}
Navigations−Datenstruktur
2
3
5
7
11
13
17
19
00
Annahme: Dummy-Element mit Schlüssel •
Achtung: In Abbildungen sieht • wie 00 aus
251
Statisch: Sortiertes Feld mit binärer Suche
// Find min {i 2 1..n + 1 : a[i] k}
Function locate(a[1..n], k : Element)
(`, r ):= (0, n + 1)
// Assume a[0] = •, a[n + 1] = •
while ` + 1 < r do
invariant 0  ` < r  n + 1 and a[`] < k  a[r ]
m:= b(r + `)/2c
// ` < m < r
if k  a[m] then r := m else `:= m
return r
Übung: Müssen die Sentinels • / • tatsächlich vorhanden sein?
Übung: Variante von binärer Suche:
bestimme `, r so dass a[`..r 1] = [k, . . . , k], a[` 1] < k und a[r ] > k
252
Statisch: Sortiertes Feld mit binärer Suche
// Find min {i 2 1..n + 1 : a[i] k}
Function locate(a[1..n], k : Element)
(`, r ):= (0, n + 1)
// Assume a[0] = •, a[n + 1] = •
while ` + 1 < r do
invariant 0  ` < r  n + 1 and a[`] < k  a[r ]
m:= b(r + `)/2c
// ` < m < r
if k  a[m] then r := m else `:= m
return r
Zeit: O(log n)
Beweisidee: r ` „halbiert“ sich in jedem Schritt
253
Binäre Suche – Beispiel: k = 15
Function locate(a[1..n], k : Element) // min {i 2 1..n + 1 : a[i] k}
(`, r ):= (0, n + 1)
// Assume a[0] = •, a[n + 1] = •
while ` + 1 < r do
invariant 0  ` < r  n + 1 and a[`] < k  a[r ]
m:= b(r + `)/2c
// ` < m < r
if k  a[m] then r := m else `:= m
return r
Indizes:
Einträge:
[
[
[
[
[0,
•,
•,
•,
•,
1,
2,
2,
2,
2,
2,
3,
3,
3,
3,
3,
5,
5,
5,
5,
4,
7,
7,
7,
7,
5,
11,
11,
11,
11,
6,
13,
13,
13,
13,
7,
17,
17,
17,
17,
8,
19,
19,
19,
19,
9]
•]
•]
•]
•]
254
Dynamische Sortierte Folgen – Grundoperationen
insert, remove, update, locate
(M.locate(k):= min {e 2 M : e
O(log n)
k})
255
Mehr Operationen
hmin, . . . , a, . . . , b, . . . , maxi
min: Erstes Listenelement
Zeit O(1)
max: Letztes Listenelement
Zeit O(1)
rangeSearch(a, b)
result:= hi
h:= locate(a)
while h ! e  b do
result.pushBack(h ! e)
h:= h !next
return result
2
// O(log n + |result|)
Navigations−Datenstruktur
3
5
7
11
13
17
19
00
256
Noch mehr Operationen
I
I
I
(re)build: Navigationsstruktur für sortierte Liste aufbauen
O(n)
hw , . . . , xi.concat(hy , . . . , zi) = hw , . . . , x, y , . . . , zi
O(log n)
hw , . . . , x, y , . . . , zi.split(y ) = (hw , . . . , xi, hy , . . . , zi)
O(log n)
Zählen: rank, select, rangeSize
O(log n)
Fingersuche: = Abstand zu Fingerinfo
zusätzlicher Parameter für insert, remove, locate,. . . O(log n) ! log
Navigations−Datenstruktur
2
3
5
7
11
13
17
19
00
257
Abgrenzung
Hash-Tabelle: nur insert, remove, find. Kein locate, rangeQuery
Sortiertes Feld: nur bulk-Updates. Aber:
n
Hybrid-Datenstruktur oder log M
geometrisch wachsende
statische Datenstrukturen
Prioritätsliste: nur insert, deleteMin, (decreaseKey, remove). Dafür:
schnelles merge
Sortierte Folgen allgemein: die eierlegende Wollmilchdatenstruktur.
„Etwas“ langsamer als speziellere Datenstrukturen
258
Sortierte Folgen – Anwendungen
I
Best-First Heuristiken
I
Alg. Geometrie: Sweepline-Datenstrukturen
I
Datenbankindex
I
...
259
Anwendungsbeispiel: Best Fit Bin Packing
Procedure binPacking(s)
B : SortedSequence
// used bins sorted by free capacity
foreach e 2 s by decreasing element size
// sort
if ¬9b 2 B : free(b) e then B.insert(new bin)
locate b 2 B with smallest free(b) e
insert e into bin b
Zeit: O(|s| log |s|)
Qualität: „gut“. Details: nicht hier
260
Binäre Suchbäume
Blätter: Elemente
einer sortierten Folge.
Innere Knoten v = (k, `, r ),
(Spalt-Schlüssel, linker Teilbaum, rechter Teilbaum).
Invariante:
über ` erreichbare Blätter haben Schlüssel  k
über r erreichbare Blätter haben Schlüssel > k
17
7
3
13
2
2
5
3
5
11
7
11
19
13
17
19
00
261
Varianten, Bemerkungen
I
Dummy-Element im Prinzip verzichtbar
I
Oft speichern auch innere Knoten Elemente
I
„Suchbaum“ wird oft als Synomym für „sortierte Folge“ verwendet.
(Aber das vermischt (eine) Implementierung mit der Schnittstelle)
17
7
3
2
13
5
11
19
262
locate(k)
Idee: Benutze Spaltschlüssel x als Wegweiser.
Function locate(k, x)
if x is a leaf then
if k  x then return x
else return x !next
if k  x then
return locate(k, x !left)
else
return locate(k, x !right)
15?
<
7
17
>
3
13
2
2
5
3
5
11
7
11
>
13
17
19
19
00
263
locate(k) – anderes Beispiel
Idee: Benutze Spaltschlüssel x als Wegweiser.
Function locate(k, x)
if x is a leaf then
if k  x then return x
else return x !next
if k  x then
return locate(k, x !left)
else
return locate(k, x !right)
18?
<
7
18
>
3
13
2
2
5
3
5
11
7
11
>
13
17
19
19
00
264
Invariante von locate(k)
Function locate(k, x)
if x is a leaf then
if k  x then return x
else return x !next
if k  x then
return locate(k, x !left)
else
return locate(k, x !right)
root
x
<k <x
>x >k
Invariante: Sei X die Menge aller von x erreichbaren Listenelemente.
Listenelemente links von X sind < k
Listenelemente rechts von X sind > k
265
Ergebnisberechnung von locate(k)
Function locate(k, x)
if x is a leaf then
if k  x then return x
else return x !next
if k  x then
return locate(k, x !left)
else
return locate(k, x !right)
Fall k = x: return x
Fall k < x: return x
Fall k > x: return x !next
root
x
<k
>k
Bingo!
links ist es auch nicht
nächstes ist > k und k gibt es nicht
266
Laufzeit von locate(k)
Function locate(k, x)
if x is a leaf then
if k  x then return x
else return x !next
if k  x then
return locate(k, x !left)
else
return locate(k, x !right)
15?
<
7
17
>
3
13
2
2
5
3
5
11
7
11
>
13
17
19
19
00
Laufzeit: O(Höhe).
Bester Fall: perfekt balanciert, d. h. Tiefe = blog nc
Schlechtester Fall: Höhe n
267
Naives Einfügen
Zunächst wie locate(e). Sei e 0 gefundenes Element, u der Elterknoten
insert e
v
u
k
e’
T
e
u
e’
T
T
k=key(e)
insert e
u
e’
u
k
T
e
v
e’
268
Beispiel
insert 17
insert 13
insert 11
19
19
19
19
19
17
17
00
17
17
13
13
19
00
13
11
17
19
00
11
13
17
19
00
Problem: Der Baum wird beliebig unbalanciert.
langsam
269
Herunterladen