3.1 Sortiernetzwerke

Wir kommen auf unsere Gadget-Metapher zurück. Zum Sortieren verwenden wir ein Minmax-Gate, dass zwei Inputs und zwei Outputs hat:

Aus diesem Minmax-Gate wollen wir einen Schaltkreis bauen, der Sortieren kann. Das nennt man in diesem Zusammenhang ein Sortiernetzwerk. Wir folgen der Idee von Mergesort: wir zerlegen die Eingabeliste in zwei Teile, die wir rekursiv sortieren; dann rufen wir eine Prozedur merge auf, die die zwei sortierten Teillisten X und Y zu einer großen sortierten Liste Z=merge(X,Y) zusammenfügt. Sequentiell ist die Prozedur merge einfach zu implementieren und tätigt im Worst-Case |X|+|Y|1 Vergleiche. Parallel ist das schon schwieriger. In diesem Teilkapitel beschreiben wir Batchers Odd-Even Merging Network und das mergesort-artige Sortiernetzwerk, das man daraus erhält.

Ein Netzwerk für Merge

Wir haben als Input zwei Listen gegeben: X=[x1,x2,,xn] und Y=[y1,y2,,yn]. Beide sind bereits sortiert. Wir wollen nun eine sortierte version der Vereinigung, also von [x1,,xn,y1,,yn] berechnen. Sequentiell kennen Sie das als die Subroutine merge von MergeSort, zum Beispiel aus Kapitel 2.3 von TI-1. Um es parallel berechnen zu können, zerlegen wir das Array X in die ungeraden und die geraden Indizes:

Xodd:=[x1,x3,x5,,xn1]Xeven:=[x2,x4,x6,,xn] ,

wobei wir davon ausgehen, dass n gerade ist. Das dient zum Großteil dazu, die Notation zu vereinfachen. Nach gleichem Schema zerlegen wir Y:

Yodd:=[y1,y3,y5,,yn1]Yeven:=[y2,y4,y6,,yn] ,

Nun führen wir rekursiv einen Merge auf XoddYodd durch, ebenso auf XevenYeven.

Wir erhalten also

U:=[u1,u2,,un]=merge(Xodd,Yodd)V:=[v1,v2,,vn]=merge(Xeven,Yeven)

Jetzt müssen wir uns noch parallel aus U und V den Merge der Gesamtliste XY zusammenbasteln - und zwar parallel. Wir können zum Beispiel bereits mit Sicherheit sagen, dass u1 das kleinste dieser Liste ist. Danach wird es schon schwieriger.

Definition 3.1.1(Rang). Sei Z=XY die Menge der Elemente in der Gesamtliste (wir gehen davon aus, dass kein Element doppelt vorkommt, um den Mengenbegriff bequem verwenden zu können). Der Rang eines Elements s in Z ist die Anzahl der Elemente z mit zs, also:

rank(s,Z):=|{zZ | zs}|

So hat das Minimum von Z zum Beispiel Rang 1 und das Maximum Rang 2n.

Wir fragen uns nun: was ist der Rang von ui, also einem Element, das in X auf einer ungeraden Position stand oder in Y. Das können wir nicht sicher sagen, zum Beispiel kann u2 Rang 2 haben, aber auch Rang 3, wenn zum Beispiel u1<v1<u2 gilt. Kann es Rang 4 haben? Das nächste Lemma beantwortet diese Frage:

Lemma 3.1.2 rank(ui){2i2,2i1}.

Beweis. Das Element ui ist in XoddYodd enthalten. Dort gibt es genau i Elemente, die ui sind. Schauen wir uns an, wo ui in X und Y liegt. Seien 2k1 und 2l1 die größten ungeraden Indizes mit x2k1ui und y2l1ui. Dann gilt

x1<x2<x3<<x2k1uiy1<y2<y3<<y2l1ui .

Die Mengen X und Y enthalten zusammen mindestens 2k1+2l1 Elemente, die ui sind, und somit gilt rank(ui,Z)2k+2l2. Davon gehören k zu Xodd und l zu Yodd, und somit gilt k+l=rank(ui,XoddYodd)=rank(ui,U)=i. Zusammen schließen wir, dass rank(ui,Z)2i2.

Folgende Elemente sind echt größer als ui:

ui<x2k+1<x2k+2<<xnui<y2l+1<y2l+2<<yn

Das sind insgesamt n2k+n2l=2n2i Elemente, die größer sind als ui. Betrachten wir noch x2k1 und y2l1. Eines davon ist ui selbst, und somit ist eines von x2k,y2k echt größer als ui. Es gibt also mindestens 2n2i+1 Elemente, die echt größer sind als ui, und somit ist rank(ui)2i1.

Lemma 3.1.3 rank(vi){2i,2i+1}.

Übungsaufgabe 3.1.1 Beweisen Sie das obige Lemma.

Für i=1 ergibt das erste Lemma rank(u1){0,1} und somit rank(u1)=1, da ein Rang von 0 unmöglich ist. Analog erhalten wir rank(vn)=n. Für i=1,,n1 wenden nun die beiden Lemmas auf ui+1 und vi an und sehen, dass

{rank(ui+1),rank(vi)}={2i,2i+1}

gilt. Wir müssen also nur noch ui+1 und vi vergleichen und können bestimmen, welche Elemente z2i und z2i+1 in der endgültigen sortierten Liste Z=[z1,,z2n] sind. Im Überblick erhalten wir folgende rekursive Konstruktion für merge:

Beobachtung 3.1.4 Das oben beschriebene Merge-Netzwerk hat Θ(nlogn) minmax-Gates und Tiefe Θ(logn).

Ein Sortiernetzwerk auf Merge-Netzwerken

Um nun ein Array [x1,x2,,xn] der Länge n zu sortieren, gehen wir wieder rekursiv vor. Wir nehmen an, dass n gerade ist, und teilen das Array in zwei Hälften L=[x1,,xn/2] und U=[xn/2,,xn]. Wir sortieren rekursiv und wenden dann merge auf die Ergebnisliste an.

Theorem 3.1.5 Das gerade beschriebene Sortiernetzwerk hat Tiefe Θ(log2n) und Θ(nlog2n) viele Gates.

Übungsaufgabe 3.1.2 Beweisen Sie das Theorem.