我正在尝试在Swift中实现TimSort。 我已经提到了这两个链接:This和this 我已转换为Swift的代码是:
import UIKit
class ViewController: UIViewController {
var arr : [Int] = []
let run : Int = 5
override func viewDidLoad() {
super.viewDidLoad()
for _ in 0..<10 {
arr.append(Int(arc4random_uniform(100)))
}
timSort()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func insertionSort(_ array:[Int]) -> [Int] {
var a = array
for x in 1..<a.count {
var y = x
while y > 0 && a[y] < a[y - 1] {
a.swapAt(y - 1, y)
y -= 1
}
}
return a
}
func merge(leftPile: [Int], rightPile: [Int]) -> [Int] {
var leftIndex = 0
var rightIndex = 0
var orderedPile = [Int]()
while leftIndex < leftPile.count && rightIndex < rightPile.count {
if leftPile[leftIndex] < rightPile[rightIndex] {
orderedPile.append(leftPile[leftIndex])
leftIndex += 1
} else if leftPile[leftIndex] > rightPile[rightIndex] {
orderedPile.append(rightPile[rightIndex])
rightIndex += 1
} else {
orderedPile.append(leftPile[leftIndex])
leftIndex += 1
orderedPile.append(rightPile[rightIndex])
rightIndex += 1
}
}
while leftIndex < leftPile.count {
orderedPile.append(leftPile[leftIndex])
leftIndex += 1
}
while rightIndex < rightPile.count {
orderedPile.append(rightPile[rightIndex])
rightIndex += 1
}
return orderedPile
}
func timSort() {
print("Unsorted : \(arr)")
for i in stride(from: 0, to: arr.count, by: run) {
print("i : \(min((i + run),(arr.count)))")
arr.replaceSubrange(i..<min((i + run),(arr.count)), with: insertionSort(Array(arr[i..<min((i + run),(arr.count))])))
}
print("after insertion sort \(arr)")
var runCount = run
while runCount < arr.count{
for x in stride(from: 0, to: arr.count, by: 2 * runCount) {
print("x : \(x) runcount \(runCount) calc : \(x + 2 * runCount)")
arr.replaceSubrange(x..<min((x + 2 * runCount),(arr.count)), with: merge(leftPile: Array(arr[x..<(x + runCount)]), rightPile: Array(arr[(x + runCount)..<min((x + 2 * runCount),(arr.count))])))
}
runCount = runCount * 2
}
print("Sorted : \(arr)")
}
}
我面临的问题是,当我在两个链接中执行代码时,它都可以与任何运行值一起工作(例如run = 7
),但是在我的代码中却没有发生。
我的代码仅在run = 5
和arr.count = 10
时才能正常工作。在所有其他情况下,它在arr.replaceSubrange(x..<min((x + 2 * runCount),(arr.count)), with: merge(leftPile: Array(arr[x..<(x + runCount)]), rightPile: Array(arr[(x + runCount)..<min((x + 2 * runCount),(arr.count))])))
此行上崩溃。
我尝试了各种解决方法,但无法解决问题。 请有人帮我指出。
答案 0 :(得分:2)
您需要再进行min
条检查。在您上一个while
循环中,x + runCount
可能超过arr.count
,因此x + runCount
需要替换为min(x + runCount, arr.count)
。添加了min
检查后,代码现在可以在run
和arr.count
的各种大小下运行:
func timSort() {
print("Unsorted : \(arr)")
for i in stride(from: 0, to: arr.count, by: run) {
print("i : \(min((i + run),(arr.count)))")
arr.replaceSubrange(i..<min((i + run),(arr.count)), with: insertionSort(Array(arr[i..<min((i + run),(arr.count))])))
}
print("after insertion sort \(arr)")
var runCount = run
while runCount < arr.count{
for x in stride(from: 0, to: arr.count, by: 2 * runCount) {
print("x : \(x) runcount \(runCount) calc : \(x + 2 * runCount)")
arr.replaceSubrange(x..<min(x + 2 * runCount, arr.count), with: merge(leftPile: Array(arr[x..<min(x + runCount, arr.count)]), rightPile: Array(arr[min(x + runCount, arr.count)..<min(x + 2 * runCount, arr.count)])))
}
runCount = runCount * 2
}
print("Sorted : \(arr)")
}
答案 1 :(得分:0)
从Swift 5.0开始,“ sort()”方法使用timsort作为默认实现。您可以在Here
中找到更多相关信息