Algorithmen und Datenstrukturen 1-3. Seminar - Dominic Rose Bioinformatics Group, University of Leipzig Wintersemester 2009/10
Outline Spezielle Listen: Stacks, Queues Sortierverfahren 3. Übungsserie
Wiederholung: Stacks Synonyme: Stapel, Keller, LIFO-Liste,... Spezielle Liste, bei der alle Einfügungen und Löschungen nur an einem Ende, TOP genannt, vorgenommen werden.
Wiederholung: Stacks Stack-Operationen (ADT): 1. CREATE: Erzeugt den leeren Stack 2. INIT(S): Initialisiert S als leeren Stack 3. PUSH(S, x): Fügt das Element x als oberstes Element von S ein 4. POP(S): Löschen des Elementes, das als letztes in den Stack S eingefügt wurde 5. TOP(S): Abfragen des Elementes, das als letztes in den Stack S eingefügt wurde 6. EMPTY(S): Abfragen, ob der Stack S leer ist Alle Operationen benötigen nur konstante Kosten: O(1)
Anwendung: Wiederholung: Stacks Wohlgeformte Klammerausdrücke (Vorlesung) Tower-of-Hanoi Problem Gegeben: 3 Türme, n Scheiben Ziel: Alle Scheiben von Turm A nach Turm C versetzen Bedingung: Scheiben sind zu jedem Zeitpunkt der Größe nach geordnet, Größere darf nie auf Kleineren liegen.
Wiederholung: Queues Synonyme: FIFO-Schlange, Warteschlange Spezielle Liste, Elemente werden an einem Ende (hinten) eingefügt und am anderen Ende (vorne) entfernt.
Wiederholung: Queues Queue-Operationen (ADT): 1. CREATE: Erzeugt die leere Schlange 2. INIT (Q): Initialisiert Q als leere Schlange 3. ENQUEUE (Q, x): Fügt das Element x am Ende der Schlange Q ein 4. DEQUEUE (Q): Löschen des Elementes, das am längsten in der Schlange verweilt (erstes Element) 5. FRONT (Q): Abfragen des ersten Elementes in der Schlange 6. EMPTY (Q): Abfragen, ob die Schlange leer ist Beispiel: Q = [a, b, c] ENQUEUE(Q, d) Q = [a, b, c, d] DEQUEUE(Q) Q = [b, c, d]
Wiederholung: Sortieren
Selection-Sort - Algorithmus 1. Start: Unsortierte Teilliste (UT) ist die ganze Liste 2. WHILE( Liste UT enthält mehr als ein Element ): 3. Auswahl des kleinsten Elementes x in UT 4. Austausch von x mit dem ersten Element von UT 5. Reduziere UT um dieses Element ENDWHILE
Beispiel: [8, 2, 5, 3, 7, 1, 6, 4] Selection-Sort - Beispiel
Selection-Sort - Beispiel Beispiel: [8, 2, 5, 3, 7, 1, 6, 4] 1. 8, 2, 5, 3, 7, 1, 6, 4 SCHWARZ: Unsortierte Teilliste 2. 1, 2, 5, 3, 7, 8, 6, 4 ROT: Sortierte Teilliste 3. 1, 2, 5, 3, 7, 8, 6, 4 4. 1, 2, 3, 5, 7, 8, 6, 4 5. 1, 2, 3, 5, 7, 8, 6, 4 6. 1, 2, 3, 4, 7, 8, 6, 5 7. 1, 2, 3, 4, 5, 8, 6, 7 8. 1, 2, 3, 4, 5, 6, 8, 7 9. 1, 2, 3, 4, 5, 6, 7, 8 10. 1, 2, 3, 4, 5, 6, 7, 8
Bubble-Sort - Algorithmus Vertauschungen = true while( Vertauschungen ) Vertauschungen = false for i=1.. n-1 if ( A(i) > A(i+1) ) exchange A(i) and A(i+1); Vertauschungen = true
Beispiel: [55, 7, 78, 12, 42] Bubble-Sort - Beispiel
Beispiel: [55, 7, 78, 12, 42] Bubble-Sort - Beispiel
Insertion-Sort - Algorithmus Idee: i-tes Element, x, der Liste (1. Element der unsortierten Teilliste) wird an der richtigen Stelle der bereits sortierten Teilliste (1 bis i 1) eingefügt Elemente in sortierter Teilliste mit höherem Schlüsselwert als x werden verschoben Algorithmus: for(i=2.. n) temp = A[i]; j = i-1; //Fge A[i] in die sortierte Folge A[1.. i-1] while ( j>0 and A[j] > temp ) A[j+1] = A[j]; j--; A[j+1] = temp;
Insertion-Sort - Beispiel Beispiel: [5, 2, 4, 6, 1, 3]
Insertion-Sort - Beispiel Beispiel: [5, 2, 4, 6, 1, 3]
Shell-Sort - Algorithmus Weiterentwicklung von Insertion-Sort. Versucht Nachteil von IS auszugleichen, dass Elemente in der Sequenz oft über weite Strecken verschoben werden (u.u. ineffizient). Sortierung in mehreren Stufen von grob bis fein Vorsortierung reduziert Anzahl von Tauschvorgängen Realisierung über Hilfsmatrizen
Shell-Sort - Beispiel Beispiel: [2, 5, 3, 4, 3, 9, 3, 2, 5, 4, 1, 3], mittels 4-, 2-, 1-Folge.
Shell-Sort - Beispiel Beispiel: [2, 5, 3, 4, 3, 9, 3, 2, 5, 4, 1, 3], mittels 4-, 2-, 1-Folge. Vorgehen: Matrix erstellen, Spalten sortieren, Insertion-Sort
Quick-Sort - Idee Prinzip: Teile und Herrsche / Divide and Conquer Partitioniere zu sortierenden bereich in 2 Hälften, links nur Schlüssel < Pivot-ELement, rechts alles >= Pivot-Element. Sortiere Teilhälften in gleicher Weise
Quick-Sort - Pseudo-Code
Quick-Sort - Beispiel
Quick-Sort - Anmerkungen Bestimmung des Pivot-Elements Möglichst nahe am Median der sortierten Liste Ideal: Liste wird in zwei gleichlange Teillisten zerlegt Oft: Einfach linkes bzw. rechtes Element Übliches Verfahren zum Zerlegen der Liste: 2 Zeiger i und j, i beginnt von links, j von rechts Bis i > j (sich also i und j kreuzen) i solange erhöhen, bis Wert p gefunden j solange erniedrigen, bis Wert <p gefunden Falls i < j, L [i] und L [j] austauschen benötigt keinen zusätzlichen Speicherplatz Listengrenzen l und r werden beim Aufruf von Quicksort übergeben
Quick-Sort - Algorithmus Algorithmus qsort(a,l,r) sortiert A[l..r]: i=l; j=r // Initialisieren: if(r<=l) return // Fertig? piv = A[(l+r)/2] // Pivot-Element do // Schleife while(a[i]<piv) i++ // Links suchen while(a[j]>piv) j-- // Rechts suchen if(i<=j) exchange(a[i],a[j]) i++; j-- while (i<=j) // Schleifenende qsort(a,l,j) // Rekursiver Aufruf qsort(a,i,r)
Beispiel: [3, 2, 5, 6, 4] Quick-Sort - Beispiel i=l; j=r // Initialisieren: if(r<=l) return // Fertig? piv = A[(l+r)/2] // Pivot-Element do // Schleife while(a[i]<piv) i++ // Links suchen while(a[j]>piv) j-- // Rechts suchen if(i<=j) exchange(a[i],a[j]) i++; j-- while (i<=j) // Schleifenende qsort(a,l,j) // Rekursiver Aufruf qsort(a,i,r)
Heap-Sort - Idea
Heap-Sort - Idea
Heap-Sort - Idea
Heap-Sort - Beispiel In-place Realisierung, im Array: n 2n, 2n + 1 index 0 1 2 3 4 Beispiel 39 17 50 1 5 Heap-Eigenschaft 50 17 39 1 5 von A[0] bis A [n/2] herstellen tausche A [0] mit A [n] 5 17 39 1 50 Wiederherstellen der Heap-Eigenschaft, tauschen,...
Merge-Sort
Merge-Sort
Laufzeiten Einfache Verfahren Höhere Verfahren Einfügen Insertion-Sort O(n 2 ) Shell-Sort O(n 1.2 ) Auswählen Selection-Sort O(n 2 ) Heap-Sort O(nlog 2 (n)) Austauschen Bubble-Sort O(n 2 ) Quick-Sort O(nlog 2 (n))
3. Übungsserie 4 Aufgaben, insgesamt 35 Punkte A09 Stack-Sort, Pseudo-Code ergänzen, analysieren (12 Punkte) A10 Selection-/Insertion-/Bubble-Sort (9 Punkte) A11 Fragen zu Sortier-Algorithmen (5 Punkte) A12 Stacks, Queues, Pseudo-Code: WUSEL (9 Punkte)
Aufgabe 9 Beim Umzug eines Informatik-Instituts ist eines der Programme beschädigt worden. Glücklicherweise ist nur an einer Stelle (...) der Ausdruck für eine Bedingung verlorengangen: INIT(S), i=0 Solange (i<laenge(l)) { Solange ((nicht EMPTY(S)) und (...)) { Ausgabe(TOP(S)), POP(S) } PUSH(S,L[i]) i=i+1 } Solange (nicht EMPTY(S)) { Ausgabe(TOP(S), POP(S)) } Ende
Aufgabe 9 - Lösung (a) Welche Bedingung steht sinnvollerweise statt..., damit das Programm die Elemente aus der Eingabe möglichst gut in aufsteigender Reihenfolge sortiert ausgibt? Insbesondere soll das reparierte Programm bei Eingabe von (5,4,3,2,1) als Ausgabe (1,2,3,4,5) liefern. Auf (1,5,4,3,2,6) soll mit (1,2,3,4,5,6) geantwortet werden. Zeigen Sie, wie das reparierte Programm auf diesen zwei Beispielen arbeitet, indem Sie den Stapel direkt vor und direkt nach jedem PUSH explizit angeben. (6 Punkte)
Aufgabe 9 - Lösung (a) Welche Bedingung steht sinnvollerweise statt..., damit das Programm die Elemente aus der Eingabe möglichst gut in aufsteigender Reihenfolge sortiert ausgibt? Insbesondere soll das reparierte Programm bei Eingabe von (5,4,3,2,1) als Ausgabe (1,2,3,4,5) liefern. Auf (1,5,4,3,2,6) soll mit (1,2,3,4,5,6) geantwortet werden. Zeigen Sie, wie das reparierte Programm auf diesen zwei Beispielen arbeitet, indem Sie den Stapel direkt vor und direkt nach jedem PUSH explizit angeben. (6 Punkte) Bedingung? (1 Punkt) Eingabe (5,4,3,2,1)? (2 Punkt) Eingabe (1,5,4,3,2,6)? (3 Punkte)
Aufgabe 9 - Lösung INIT(S), i=0 Solange (i<laenge(l)) { Solange ((nicht EMPTY(S)) und (TOP(S)<=L[i])) { Ausgabe(TOP(S)), POP(S) } PUSH(S,L[i]) i=i+1 } Solange (nicht EMPTY(S)) { Ausgabe(TOP(S), POP(S)) } Ende
Aufgabe 9 - Lösung Eingabe (5,4,3,2,1)? Angabe des Stapels direkt vor und nach jedem PUSH?
Aufgabe 9 - Lösung Eingabe (5,4,3,2,1)? Angabe des Stapels direkt vor und nach jedem PUSH? i Ausgaben Push 0 [] [5] 1 [5] [5, 4] 2 [5, 4] [5, 4, 3] 3 [5, 4, 3] [5, 4, 3, 2] 4 [5, 4, 3, 2] [5, 4, 3, 2, 1] 5 1,..., 5
Aufgabe 9 - Lösung Eingabe (1,5,4,3,2,6)? Angabe des Stapels direkt vor und nach jedem PUSH?
Aufgabe 9 - Lösung Eingabe (1,5,4,3,2,6)? Angabe des Stapels direkt vor und nach jedem PUSH? i Ausgaben Push 0 [] [1] 1 1 [] [5] 2 [5] [5, 4] 3 [5, 4] [5, 4, 3] 4 [5, 4, 3] [5, 4, 3, 2] 5 2,..., 5 [] [6] 6 6
Aufgabe 9 - Lösung (b) Begründen Sie kurz, dass die Laufzeit des Programms in O(n) liegt, wobei die Problemgröße n = Laenge(L) ist. Wieso kann man bereits an dieser Abschätzung des Laufzeitverhaltens erkennen, dass es Eingabelisten gibt, die vom Programm nicht korrekt sortiert ausgegeben werden? (4 Punkte)
Aufgabe 9 - Lösung Da i in jeder Iteration um 1 erhöht wird werden n=laenge(l) Iterationen ausgeführt. Pro Iteration werden zumindest folgende Operationen ausgeführt: Test auf Listenende O(1) mindestens Test ob Stack leer und Schlüsselvergleich O(1) PUSH() O(1) i=i+1 O(1) Für jedes Element wird genau einmal PUSH aufgerufen. Spätestens am Ende der Schleife werde alle Elemente vom Stack entfernt. Also wird für jedes Element zusätzlich einmal AUSGABE(TOP(S)) und einmal POP(S) ausgerufen sowie die Schleifenabbruchtests ausgeführt. All diese Operationen sind in O(1). O(n) Sortieren auf der Basis von Schlüsselvergleichen benötigt mindestens Ω(n log n).
Aufgabe 9 - Lösung (c) Geben Sie eine möglichst kurze Liste an, die vom Programm nicht korrekt sortiert wird. (2 Punkte)
Aufgabe 9 - Lösung (c) Geben Sie eine möglichst kurze Liste an, die vom Programm nicht korrekt sortiert wird. (2 Punkte) (2 3 1)
Aufgabe 10 - Lösung Verwenden Sie Selection-Sort, Insertion-Sort und Bubble-Sort mit Abbruchkontrolle, um die folgende Liste zu sortieren: (1, 6, 3, 8, 4, 2, 9, 5). Geben Sie jeweils nach Beendigung der inneren Schleife die aktuelle Liste und die Anzahl der bis dahin stattgefundenen Schlüsselvergleiche an. (3x3 Punkte)
Selection Sort...nach Ende der inneren Schleife... for i=1... n-1 min = i for j=i+1 bis n if (A(j) < A(min)) min = j -->> exchange A(i) and A(min)
Aufgabe 10 - Lösung Gegeben: (1, 6, 3, 8, 4, 2, 9, 5) Selection Sort (ˆx: akt. Element; ˇy: bestimmtes Minimum): (ˆ1, ˇ 6, 3, 8, 4, 2, 9, 5) 7 7 (1, ˆ6, 3, 8, 4, ˇ2, 9, 5) 6 13 (1, 2, ˇˆ3, 8, 4, 6, 9, 5) 5 18 (1, 2, 3, ˆ8, ˇ4, 6, 9, 5) 4 22 (1, 2, 3, 4, ˆ8, 6, 9, ˇ5) 3 25 (1, 2, 3, 4, 5, ˇˆ6, 9, 8) 2 27 (1, 2, 3, 4, 5, 6, ˆ9, ˇ8) 1 28
Aufgabe 10 - Lösung Gegeben: (1, 6, 3, 8, 4, 2, 9, 5) Insertion Sort: (1, 6, 3, 8, 4, 2, 9, 5) 1 1 (1, 6, 6, 8, 4, 2, 9, 5) 2 3 (1, 3, 6, 8, 4, 2, 9, 5) 1 4 (1, 3, 6, 6, 8, 2, 9, 5) 3 7 (1, 3, 3, 4, 6, 8, 9, 5) 5 12 (1, 2, 3, 4, 6, 8, 9, 5) 1 13 (1, 2, 3, 4, 6, 6, 8, 9) 4 17
Aufgabe 10 - Lösung Gegeben: (1, 6, 3, 8, 4, 2, 9, 5) Bubble Sort: 1. (1, 3, 6, 4, 2, 8, 5, 9) 7 7 2. (1, 3, 4, 2, 6, 5, 8, 9) 6 13 3. (1, 3, 2, 4, 5, 6, 8, 9) 5 18 4. (1, 2, 3, 4, 5, 6, 8, 9) 4 22 5. (1, 2, 3, 4, 5, 6, 8, 9) 3 25
Aufgabe 11 - Lösung Welche der folgenden Aussagen treffen zu? Begründen Sie Ihre Aussage. (a) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n 2 ) ist. (b) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n) ist. (c) Es gibt Fälle, in denen die Laufzeit von Merge-Sort in O(n 2 ) ist. (d) Insertion-Sort kann in O(n) laufen. (e) Selection-Sort kann in O(n) laufen. (5 Punkte)
Aufgabe 11 - Lösung (a) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n 2 ) ist
Aufgabe 11 - Lösung (a) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n 2 ) ist Ja, z.b. eine vorsortierte Liste [1,2,3,4,5,6,7,8] und Pivotelement immer das erste Element.
Aufgabe 11 - Lösung (a) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n 2 ) ist Ja, z.b. eine vorsortierte Liste [1,2,3,4,5,6,7,8] und Pivotelement immer das erste Element. (b) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n) ist.
Aufgabe 11 - Lösung (a) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n 2 ) ist Ja, z.b. eine vorsortierte Liste [1,2,3,4,5,6,7,8] und Pivotelement immer das erste Element. (b) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n) ist. Nein. Untere Grenze für Quick-Sort ist O(nlogn).
Aufgabe 11 - Lösung (a) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n 2 ) ist Ja, z.b. eine vorsortierte Liste [1,2,3,4,5,6,7,8] und Pivotelement immer das erste Element. (b) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n) ist. Nein. Untere Grenze für Quick-Sort ist O(nlogn). (c) Es gibt Fälle, in denen die Laufzeit von MergeSort in O(n 2 ) ist.
Aufgabe 11 - Lösung (a) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n 2 ) ist Ja, z.b. eine vorsortierte Liste [1,2,3,4,5,6,7,8] und Pivotelement immer das erste Element. (b) Es gibt Fälle, in denen die Laufzeit von Quick-Sort in O(n) ist. Nein. Untere Grenze für Quick-Sort ist O(nlogn). (c) Es gibt Fälle, in denen die Laufzeit von MergeSort in O(n 2 ) ist. Nein. Merge-Sort ist stabil bezüglich der Laufzeit. Liegt also immer in O(nlogn).
Aufgabe 11 - Lösung (d) Insertion-Sort kann in O(n) laufen.
Aufgabe 11 - Lösung (d) Insertion-Sort kann in O(n) laufen. Ja, z.b. eine vorsortiertes Array [1,2,3,4,5,6,7,8]. Dann wird jedes Element nur einmal verglichen (nämlich mit dem letzten Element des bereits sortierten Teils des Arrays) und dahinter eingefügt. Insgesamt: lineare Laufzeit. (e) Selection-Sort kann in O(n) laufen.
Aufgabe 11 - Lösung (d) Insertion-Sort kann in O(n) laufen. Ja, z.b. eine vorsortiertes Array [1,2,3,4,5,6,7,8]. Dann wird jedes Element nur einmal verglichen (nämlich mit dem letzten Element des bereits sortierten Teils des Arrays) und dahinter eingefügt. Insgesamt: lineare Laufzeit. (e) Selection-Sort kann in O(n) laufen. Nein. Denn es muss in jedem Durchgang das Minimum gesucht werden. Dies hat auch bei einer z.b. vorsortierten Liste lineare Laufzeit (der Algorithmus berücksichtigt Vorsortierung nicht). Man braucht außerdem n Durchläufe, was zu einer (stabilen) Laufzeit in O(n 2 ) führt.
Aufgabe 12 Das Programm WUSEL simuliert folgenden Prozess. Studierende, die jeder einen mit ihrem Namen versehenen Zettel auf einen Stapel S gelegt haben, versuchen, ihren jeweiligen Zettel wiederzufinden. Dazu stellen sie sich in einer Schlange Q an. Die/der jeweils vorderste Studierende schaut nach, ob der oberste Zettel des Stapels ihrer/seiner ist. Falls ja, wird der Zettel vom Stapel genommen und der/die Studierende verl a st die Schlange. Ansonsten bleibt der Stapel unver andert, und die/der Studierende stellt sich hinten wieder an. Dies wird iteriert, bis entweder der Stapel oder die Schlange leer sind. Das Programm sieht so aus:
Aufgabe 12 WUSEL(stack S, queue Q) { Solange (nicht EMPTY(S) und nicht EMPTY(Q)): { Falls (TOP(S) == FRONT(Q)) POP(S) Sonst ENQUEUE(Q,FRONT(Q)) } DEQUEUE(Q) } ENDE
Aufgabe 12 - Lösung (a) Welche notwendige und hinreichende Bedingung müssen S and Q beim Aufruf von WUSEL erfüllen, damit das Programm terminiert, also der Befehl ENDE irgendwann erreicht wird? (2 Punkte)
Aufgabe 12 - Lösung (a) Welche notwendige und hinreichende Bedingung müssen S and Q beim Aufruf von WUSEL erfüllen, damit das Programm terminiert, also der Befehl ENDE irgendwann erreicht wird? (2 Punkte) Die Schlüsselmenge von S muss in der Schluesselmenge von Q enthalten sein oder umgekehrt (zusätzlich Spezialfälle berücksichtigen, um z.b. den Stack leer zu bekommen: Alle Aufgabenzettel, zu denen es keine Studenten gibt, müssen unten im Stack liegen, also unter den Aufgaben, zu denen es Studenten gibt).
Aufgabe 12 - Lösung (b) Betrachten Sie ab jetzt nur noch Instanzen, bei denen das Programm terminiert. Geben Sie eine exakte Schranke Θ(... ) für die Laufzeit im worst case von WUSEL als Funktion der Problemgröße n an. Hierbei sei n = S + Q die Summe der Zahlen der Elemente in S und Q bei Aufruf. Begründen Sie Ihre Antwort. (3 Punkte)
Aufgabe 12 - Lösung (b) Betrachten Sie ab jetzt nur noch Instanzen, bei denen das Programm terminiert. Geben Sie eine exakte Schranke Θ(... ) für die Laufzeit im worst case von WUSEL als Funktion der Problemgröße n an. Hierbei sei n = S + Q die Summe der Zahlen der Elemente in S und Q bei Aufruf. Begründen Sie Ihre Antwort. (3 Punkte) Θ(n 2 ), evtl weil T (n) c n(n 1)/2 + const
Aufgabe 12 - Lösung (c) Nun sei bei Aufruf Q = [1, 2, 3, 4, 5]. S enthalte dieselben Elemente wie Q. Geben Sie eine Startreihenfolge der Elemente in S an, so dass WUSEL (i) möglichst wenige und (ii) möglichst viele Schleifendurchläufe braucht. Geben Sie in beiden Fällen die Anzahl der Durchläufe an. (4 Punkte)
Aufgabe 12 - Lösung (c) Nun sei bei Aufruf Q = [1, 2, 3, 4, 5]. S enthalte dieselben Elemente wie Q. Geben Sie eine Startreihenfolge der Elemente in S an, so dass WUSEL (i) möglichst wenige und (ii) möglichst viele Schleifendurchläufe braucht. Geben Sie in beiden Fällen die Anzahl der Durchläufe an. (4 Punkte) (i) 5,4,3,2,1 5 Durchläufe S und Q vor Begin der i-ten Schleife i S Q 1 [1,2,3,4,5] [5,4,3,2,1] 2 [1,2,3,4] [4,3,2,1] 3 [1,2,3] [3,2,1] 4 [1,2] [2,1] 5 [1] [1]
Aufgabe 12 - Lösung (ii) 1,2,3,4,5 15 Durchläufe, S und Q vor Begin der i-ten Schleife: i S Q 1 [1,2,3,4,5] [1,2,3,4,5] 2 [1,2,3,4,5] [2,3,4,5,1] 3 [1,2,3,4,5] [3,4,5,1,2] 4 [1,2,3,4,5] [4,5,1,2,3] 5 [1,2,3,4,5] [5,1,2,3,4] 6 [1,2,3,4] [1,2,3,4] 7 [1,2,3,4] [2,3,4,1] 8 [1,2,3,4] [3,4,1,2] 9 [1,2,3,4] [4,1,2,3] 10 [1,2,3] [1,2,3] 11 [1,2,3] [2,3,1] 12 [1,2,3] [3,1,2] 13 [1,2] [1,2] 14 [1,2] [2,1] 15 [1] [1]