diff --git a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift index 35de987..effb19e 100644 --- a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift +++ b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort Functional.xcplaygroundpage/Contents.swift @@ -7,27 +7,37 @@ This is a rather inefficient but neat solution. Pick a pivot and remove it from */ func swiftyQuickSort(var array: [T], _ isOrderedBefore: (T, T) -> Bool) -> [T] { - guard array.count > 1 else { - return array - } - + guard array.count > 1 else { return array + } + + let pivot = array.removeLast() + let lowers = array.filter { + isOrderedBefore($0, pivot) + } + let greaters = array.filter { + isOrderedBefore(pivot, $0) + } + let pivotsCount = array.count - lowers.count - greaters.count + 1 + let pivots = [T](count: pivotsCount, repeatedValue: pivot) + + return swiftyQuickSort(lowers, isOrderedBefore) + pivots + swiftyQuickSort(greaters, isOrderedBefore) } -//let array1 = [1] -//assert(swiftyQuickSort(array1, <) == [1]) -// -//let array2 = [Int]() -//assert(swiftyQuickSort(array2, <) == []) -// -//let array3 = ["c", "d", "b", "a"] -//assert(swiftyQuickSort(array3, <) == ["a", "b", "c", "d"]) -// -//let array4 = [3, 0, 2, 1, 2, -1] -//assert(swiftyQuickSort(array4, <) == [-1, 0, 1, 2, 2, 3]) -// -//let array6 = [5, 1, 2, 3] -//assert(swiftyQuickSort(array6, >) == [5, 3, 2, 1]) +let array1 = [1] +assert(swiftyQuickSort(array1, <) == [1]) + +let array2 = [Int]() +assert(swiftyQuickSort(array2, <) == []) + +let array3 = ["c", "d", "b", "a"] +assert(swiftyQuickSort(array3, <) == ["a", "b", "c", "d"]) + +let array4 = [3, 0, 2, 1, 2, -1] +assert(swiftyQuickSort(array4, <) == [-1, 0, 1, 2, 2, 3]) + +let array6 = [5, 1, 2, 3] +assert(swiftyQuickSort(array6, >) == [5, 3, 2, 1]) /*: [Table of Contents](Table%20of%20Contents) | [Previous](@previous) | [Next](@next) */ diff --git a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift index 8b456f5..3ab5803 100644 --- a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift +++ b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/Contents.swift @@ -9,28 +9,37 @@ Implement [Lomuto's partition algorithm]( https://en.wikipedia.org/wiki/Quicksor */ func lomutoPartition(inout array: [T], low: Int, high: Int, @noescape _ isOrderedBefore: (T, T) -> Bool) -> Int { - let pivot = array[high] - - // ... - - return 0 + let pivot = array[high] + var i = low + for j in low..(inout array: [T], low: Int, high: Int, @noescape _ isOrderedBefore: (T, T) -> Bool) -> Int { - let pivot = array[low] - - // ... - - return 0 + if low == high { + return low + } + + let pivot = array[low] + var i = low - 1 + var j = high + 1 + + while true { + repeat { + j -= 1 + } while isOrderedBefore(pivot, array[j]) + + repeat { + i += 1 + } while isOrderedBefore(array[i], pivot) + + if i < j { + swap(&array[i], &array[j]) + } else { + return j + } + } } -//var hoareArray1 = [2, 5, 4] -//assert(hoarePartition(&hoareArray1, low: 0, high: hoareArray1.count-1, <) == 0) -//assert(hoareArray1 == [2, 5, 4]) -// -//var hoareArray2 = [5, 6, 0, 2, 1, 7, 3] -//assert(hoarePartition(&hoareArray2, low: 0, high: hoareArray2.count-1, <) == 4) -//assert(hoareArray2 == [1, 3, 0, 2, 5, 7, 6]) -// -//var hoareArray3 = [1, 1, 1, 0] -//assert(hoarePartition(&hoareArray3, low: 0, high: hoareArray3.count-1, <) == 1) -//assert(hoareArray3 == [0, 1, 1, 1]) +var hoareArray1 = [2, 5, 4] +assert(hoarePartition(&hoareArray1, low: 0, high: hoareArray1.count-1, <) == 0) +assert(hoareArray1 == [2, 5, 4]) + +var hoareArray2 = [5, 6, 0, 2, 1, 7, 3] +assert(hoarePartition(&hoareArray2, low: 0, high: hoareArray2.count-1, <) == 3) +assert(hoareArray2 == [3, 1, 0, 2, 6, 7, 5]) + +var hoareArray3 = [1, 1, 1, 0] +assert(hoarePartition(&hoareArray3, low: 0, high: hoareArray3.count-1, <) == 1) +assert(hoareArray3 == [0, 1, 1, 1]) /*: @@ -69,33 +96,36 @@ By using your `hoarePartition`, implement an in-place quicksort. */ func quickSort(inout array: [T], low: Int, high: Int, @noescape _ isOrderedBefore: (T, T) -> Bool) { - - // ... + guard low < high else { return } + + let p = hoarePartition(&array, low: low, high: high, isOrderedBefore) + quickSort(&array, low: low, high: p, isOrderedBefore) + quickSort(&array, low: p+1, high: high, isOrderedBefore) } -//var array1 = [1] -//quickSort(&array1, low: 0, high: array1.count - 1, <) -//assert(array1 == [1]) -// -//var array2 = [Int]() -//quickSort(&array2, low: 0, high: array2.count - 1, <) -//assert(array2 == []) -// -//var array3 = [1, 2, 3] -//quickSort(&array3, low: 0, high: array3.count - 1, <) -//assert(array3 == [1, 2, 3]) -// -//var array4 = [3, 0, 2, 1, 2, -1] -//quickSort(&array4, low: 0, high: array4.count - 1, <) -//assert(array4 == [-1, 0, 1, 2, 2, 3]) -// -//var array5 = [1, 2, 3] -//quickSort(&array5, low: 0, high: array5.count - 1, >) -//assert(array5 == [3, 2, 1]) -// -//var array6 = [5, 1, 2] -//quickSort(&array6, low: 0, high: array6.count - 1, <) -//assert(array6 == [1, 2, 5]) +var array1 = [1] +quickSort(&array1, low: 0, high: array1.count - 1, <) +assert(array1 == [1]) + +var array2 = [Int]() +quickSort(&array2, low: 0, high: array2.count - 1, <) +assert(array2 == []) + +var array3 = [1, 2, 3] +quickSort(&array3, low: 0, high: array3.count - 1, <) +assert(array3 == [1, 2, 3]) + +var array4 = [3, 0, 2, 1, 2, -1] +quickSort(&array4, low: 0, high: array4.count - 1, <) +assert(array4 == [-1, 0, 1, 2, 2, 3]) + +var array5 = [1, 2, 3] +quickSort(&array5, low: 0, high: array5.count - 1, >) +assert(array5 == [3, 2, 1]) + +var array6 = [5, 1, 2] +quickSort(&array6, low: 0, high: array6.count - 1, <) +assert(array6 == [1, 2, 5]) /*: @@ -113,30 +143,45 @@ When the algorithm is running, there are 4 groups of elements. We need 3 indices */ func dutchFlagPartition(inout array: [T], pivotIndex: Int, low: Int, high: Int) -> (Int, Int) { - let pivot = array[pivotIndex] - - var smaller = 0 - var equal = 0 - var larger = high - - // ... - - return (smaller, larger) + let pivot = array[pivotIndex] + + var smaller = 0 + var equal = 0 + var larger = high + + while equal <= larger { + if array[equal] < pivot { + if smaller != equal { + swap(&array[smaller], &array[equal]) + } + smaller += 1 + equal += 1 + } else if array[equal] > pivot { + if equal != larger { + swap(&array[equal], &array[larger]) + } + larger -= 1 + } else { + equal += 1 + } + } + + return (smaller, larger) } -//var dutcharray = [5, 1, 2, 2, 4, 5] -//let lowAndHigh = dutchFlagPartition(&dutcharray, pivotIndex: 2, low: 0, high: dutcharray.count - 1) -//assert(lowAndHigh.0 == 1) -//assert(lowAndHigh.1 == 2) -//assert(dutcharray == [1 ,2 ,2, 4, 5, 5]) -// -// -//var dutcharray2 = [5, 10, 5, 5, 2, 5] -//let lowAndHigh2 = dutchFlagPartition(&dutcharray2, pivotIndex: 0, low: 0, high: dutcharray2.count - 1) -//assert(lowAndHigh2.0 == 1) -//assert(lowAndHigh2.1 == 4) -//assert(dutcharray2 == [2, 5, 5, 5, 5, 10]) -// +var dutcharray = [5, 1, 2, 2, 4, 5] +let lowAndHigh = dutchFlagPartition(&dutcharray, pivotIndex: 2, low: 0, high: dutcharray.count - 1) +assert(lowAndHigh.0 == 1) +assert(lowAndHigh.1 == 2) +assert(dutcharray == [1 ,2 ,2, 4, 5, 5]) + + +var dutcharray2 = [5, 10, 5, 5, 2, 5] +let lowAndHigh2 = dutchFlagPartition(&dutcharray2, pivotIndex: 0, low: 0, high: dutcharray2.count - 1) +assert(lowAndHigh2.0 == 1) +assert(lowAndHigh2.1 == 4) +assert(dutcharray2 == [2, 5, 5, 5, 5, 10]) + /*: ### 1.5. Reading Swift Source Code diff --git a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline index ad588fc..a5d100f 100644 --- a/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline +++ b/Assignments/Sorting/QuickSort.playground/Pages/Quicksort In-place.xcplaygroundpage/timeline.xctimeline @@ -3,44 +3,44 @@ version = "3.0"> diff --git a/Assignments/Sorting/QuickSort.playground/Pages/Table of Contents.xcplaygroundpage/Contents.swift b/Assignments/Sorting/QuickSort.playground/Pages/Table of Contents.xcplaygroundpage/Contents.swift index 1584e23..1392fb8 100644 --- a/Assignments/Sorting/QuickSort.playground/Pages/Table of Contents.xcplaygroundpage/Contents.swift +++ b/Assignments/Sorting/QuickSort.playground/Pages/Table of Contents.xcplaygroundpage/Contents.swift @@ -9,3 +9,4 @@ **** [Start](@next) */ +