Skip to content

Commit 404c896

Browse files
committed
Add quicksort
1 parent e1198f8 commit 404c896

File tree

8 files changed

+889
-1
lines changed

8 files changed

+889
-1
lines changed

Quicksort/Images/Example.graffle

3.68 KB
Binary file not shown.

Quicksort/Images/Example.png

47.1 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
//: Playground - noun: a place where people can play
2+
3+
import Foundation
4+
5+
6+
// *** Simple but inefficient version of quicksort ***
7+
8+
func quicksort<T: Comparable>(a: [T]) -> [T] {
9+
if a.count <= 1 {
10+
return a
11+
} else {
12+
let pivot = a[a.count/2]
13+
let less = a.filter { $0 < pivot }
14+
let equal = a.filter { $0 == pivot }
15+
let greater = a.filter { $0 > pivot }
16+
17+
// Uncomment this following line to see in detail what the
18+
// pivot is in each step and how the subarrays are partitioned.
19+
//print(pivot, less, equal, greater)
20+
21+
return quicksort(less) + equal + quicksort(greater)
22+
}
23+
}
24+
25+
let list1 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ]
26+
quicksort(list1)
27+
28+
29+
30+
// *** Using Lomuto partitioning ***
31+
32+
/*
33+
Lomuto's partitioning algorithm.
34+
35+
The return value is the index of the pivot element in the new array. The left
36+
partition is [low...p-1]; the right partition is [p+1...high], where p is the
37+
return value.
38+
*/
39+
func partitionLomuto<T: Comparable>(inout a: [T], low: Int, high: Int) -> Int {
40+
let pivot = a[high]
41+
42+
var i = low
43+
for j in low..<high {
44+
if a[j] <= pivot {
45+
(a[i], a[j]) = (a[j], a[i])
46+
i += 1
47+
}
48+
}
49+
50+
(a[i], a[high]) = (a[high], a[i])
51+
return i
52+
}
53+
54+
var list2 = [ 10, 0, 3, 9, 2, 14, 26, 27, 1, 5, 8, -1, 8 ]
55+
partitionLomuto(&list2, low: 0, high: list2.count - 1)
56+
list2
57+
58+
func quicksortLomuto<T: Comparable>(inout a: [T], low: Int, high: Int) {
59+
if low < high {
60+
let p = partitionLomuto(&a, low: low, high: high)
61+
quicksortLomuto(&a, low: low, high: p - 1)
62+
quicksortLomuto(&a, low: p + 1, high: high)
63+
}
64+
}
65+
66+
quicksortLomuto(&list2, low: 0, high: list2.count - 1)
67+
68+
69+
70+
// *** Hoare partitioning ***
71+
72+
/*
73+
Hoare's partitioning scheme.
74+
75+
The return value is NOT necessarily the index of the pivot element in the
76+
new array. Instead, the array is partitioned into [low...p] and [p+1...high],
77+
where p is the return value. The pivot value is placed somewhere inside one
78+
of the two partitions, but the algorithm doesn't tell you which one or where.
79+
*/
80+
func partitionHoare<T: Comparable>(inout a: [T], low: Int, high: Int) -> Int {
81+
let pivot = a[low]
82+
var i = low - 1
83+
var j = high + 1
84+
85+
while true {
86+
repeat { j -= 1 } while a[j] > pivot
87+
repeat { i += 1 } while a[i] < pivot
88+
89+
if i < j {
90+
swap(&a[i], &a[j])
91+
} else {
92+
return j
93+
}
94+
}
95+
}
96+
97+
var list3 = [ 8, 0, 3, 9, 2, 14, 10, 27, 1, 5, 8, -1, 26 ]
98+
partitionHoare(&list3, low: 0, high: list3.count - 1)
99+
list3
100+
101+
func quicksortHoare<T: Comparable>(inout a: [T], low: Int, high: Int) {
102+
if low < high {
103+
let p = partitionHoare(&a, low: low, high: high)
104+
quicksortHoare(&a, low: low, high: p)
105+
quicksortHoare(&a, low: p + 1, high: high)
106+
}
107+
}
108+
109+
quicksortHoare(&list3, low: 0, high: list3.count - 1)
110+
111+
112+
113+
// *** Randomized sorting ***
114+
115+
/* Returns a random integer in the range min...max, inclusive. */
116+
public func random(min min: Int, max: Int) -> Int {
117+
assert(min < max)
118+
return min + Int(arc4random_uniform(UInt32(max - min + 1)))
119+
}
120+
121+
func quicksortRandom<T: Comparable>(inout a: [T], low: Int, high: Int) {
122+
if low < high {
123+
let pivotIndex = random(min: low, max: high)
124+
(a[pivotIndex], a[high]) = (a[high], a[pivotIndex])
125+
126+
let p = partitionLomuto(&a, low: low, high: high)
127+
quicksortRandom(&a, low: low, high: p - 1)
128+
quicksortRandom(&a, low: p + 1, high: high)
129+
}
130+
}
131+
132+
var list4 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ]
133+
quicksortRandom(&list4, low: 0, high: list4.count - 1)
134+
list4
135+
136+
137+
138+
// *** Dutch national flag partioning ***
139+
140+
/*
141+
Swift's swap() doesn't like it if the items you're trying to swap refer to
142+
the same memory location. This little wrapper simply ignores such swaps.
143+
*/
144+
public func swap<T>(inout a: [T], _ i: Int, _ j: Int) {
145+
if i != j {
146+
swap(&a[i], &a[j])
147+
}
148+
}
149+
150+
/*
151+
Dutch national flag partitioning.
152+
Returns a tuple with the start and end index of the middle area.
153+
*/
154+
func partitionDutchFlag<T: Comparable>(inout a: [T], low: Int, high: Int, pivotIndex: Int) -> (Int, Int) {
155+
let pivot = a[pivotIndex]
156+
157+
var smaller = low
158+
var equal = low
159+
var larger = high
160+
161+
while equal <= larger {
162+
if a[equal] < pivot {
163+
swap(&a, smaller, equal)
164+
smaller += 1
165+
equal += 1
166+
} else if a[equal] == pivot {
167+
equal += 1
168+
} else {
169+
swap(&a, equal, larger)
170+
larger -= 1
171+
}
172+
}
173+
return (smaller, larger)
174+
}
175+
176+
var list5 = [ 10, 0, 3, 9, 2, 14, 8, 27, 1, 5, 8, -1, 26 ]
177+
partitionDutchFlag(&list5, low: 0, high: list5.count - 1, pivotIndex: 10)
178+
list5
179+
180+
func quicksortDutchFlag<T: Comparable>(inout a: [T], low: Int, high: Int) {
181+
if low < high {
182+
let pivotIndex = random(min: low, max: high)
183+
let (p, q) = partitionDutchFlag(&a, low: low, high: high, pivotIndex: pivotIndex)
184+
quicksortDutchFlag(&a, low: low, high: p - 1)
185+
quicksortDutchFlag(&a, low: q + 1, high: high)
186+
}
187+
}
188+
189+
quicksortDutchFlag(&list5, low: 0, high: list5.count - 1)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2+
<playground version='5.0' target-platform='osx'>
3+
<timeline fileName='timeline.xctimeline'/>
4+
</playground>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Timeline
3+
version = "3.0">
4+
<TimelineItems>
5+
</TimelineItems>
6+
</Timeline>

0 commit comments

Comments
 (0)