6. Сортировка
O(N²): пузырьковая сортировка, сортировка выбором, сортировка вставками
O(NlogN): быстрая сортировка, сортировка слиянием, сортировка кучей
6. 1. Пузырьковая сортировка — O(N²)
Сравнивает первую цифру массива со значением следующей цифры, и если предыдущее значение больше, позиция цифры меняется. Повторите длину массива, чтобы сравнить индексы сзади.
func boubbleSort (_ data:[Int],_ n:Int) -> [Int]{
var data = data
for i in 0...n-2 {
let last = n-i
for j in 0...last-1 {
if data[j] > data[j+1] {
let temp = data[j]
data[j] = data[j+1]
data[j+1] = temp
}
}
}
return data
}
boubbleSort([7,5,4,2,3,9], 5)
6. 2. Сортировка вставками — O(N²)
Если значение в самом конце массива меньше, чем значение предыдущей цифры на месте, поменяйте местами два значения. Если измененное значение меньше предыдущего, поменяйте местами два значения. Если обмен не производится, повторите со значением в конце массива.
func insertionSort (_ data:[Int],_ n:Int) -> [Int]{
var data = data
var end = n-1
for i in (0...n-1).reversed() {
for j in (0...end).reversed() {
if data[i] < data[j] {
let temp = data[i]
data[i] = data[j]
data[j] = temp
}
}
end -= 1
}
return data
}
insertionSort([7,5,4,2,3,9], 6)
6. 3. Сортировка выбором — O(N²)
Найдите наибольшее значение в массиве и замените его значением в конце массива. Затем повторите с массивом, кроме последнего.
func selectionSort (_ data:[Int],_ n:Int) -> [Int]{
var data = data
var end = n-1
for i in 0...end {
var largestIndex = 0
for j in 0...end {
if data[j] > data[largestIndex] {
largestIndex = j
}
}
let temp = data[largestIndex]
data[largestIndex] = data [n-1-i]
data[n-1-i] = temp
end -= 1
}
return data
}
selectionSort([7,5,4,2,3,9], 6)
6. 4. Быстрая сортировка — O(NlogN)
Быстрая сортировка – лучший метод сортировки среди нескольких методов сортировки.
(Используются методы рекурсии, разделения и квантизации.)
- Определить опорное значение из текущих данных D Предположим, что это самое левое значение в текущем диапазоне данных.
- После определения опорного значения его следует разделить на две независимые части с центром в нем. (D1), которое меньше опорного значения слева от опорного значения, и только значения больше опорного значения справа от опорного значения (D2). Это позволяет частям D1 и D2 быть независимыми друг от друга, сводя общую проблему к двум независимым проблемам.
- Если вы разделите на D1 и D2, вы можете рекурсивно обработать два вышеуказанных шага.
- Если вы больше не можете уменьшить размер данных, возвращаются текущие значения.
var data = [5,2,7,4,1,10,6,3,8,9]
func quickSort(_ left: Int,_ right: Int){
if (left < right){
var pivot = partition(left, right)
quickSort(left, pivot-1)
quickSort(pivot+1, right)
}
}
func partition(_ left: Int,_ right: Int) -> Int {
var i = left
for j in (left + 1)...(right + 1) {
if data[j] < data[left] {
i += 1
(data[i], data[j]) = (data[j], data[i])
}
}
(data[i], data[left]) = (data[left], data[i])
return i
}
quickSort(0,9)
6. 5. Сортировка слиянием — O(NlogN)
- Разделить: разделяет массив, в котором хранятся данные, пополам.
- Conquer: упорядочить каждый массив циклически
- Слияние: объединение двух массивов
Базовая сортировка слиянием начинается с двух отсортированных данных A, B и массива C для слияния двух данных. Переменные i, j и count используются для отображения текущего расположения данных сравнения массива A, B и C, а начальное значение устанавливается в исходное положение каждой переменной.
func merge(left:[Int],right:[Int]) -> [Int] {
var mergedList = [Int]()
var left = left
var right = right
while left.count > 0 && right.count > 0 {
if left.first! < right.first! {
mergedList.append(left.removeFirst())
} else {
mergedList.append(right.removeFirst())
}
}
return mergedList + left + right
}
func mergeSort(list:[Int]) -> [Int] {
guard list.count > 1 else {
return list
}
let leftList = Array(list[0..<list.count/2])
let rightList = Array(list[list.count/2..<list.count])
return merge(left: mergeSort(list:leftList), right: mergeSort(list:rightList))
}
print(mergeSort(list:[5,2,7,4,1,10,6,3,8,9]))