1、概述
插入排序是简单直观且稳定的排序算法。
插入排序的基本操作是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数+1的有序数据,适用于少量数据的排序。
插入排序主要是将排序数组分成两部分,第一部分是包含这个数组的左右元素,但最后一个元素除外(数组有多余的空间才可插入),第二部分是需要插入的元素,在第一部分排序完成后,再将这个待插入放入元素插入到已排好序的第一部分中。
插入的过程其实是不断交换和比较的过程。
2、算法原理
基本思想:每步将一个待排序的记录,岸其关键码值的大小插入前面已经排好序的数列的适当位置中,知道全部插入为止
步骤:
1)从第一个元素开始,该元素可以认为已经被排序
2)取出下一个元素,在已经排序的元素序列中从后往前扫描
3)如果该元素(已排序)大于新元素,将该元素移到下一个位置
4)重复3,直到找到已排序的元素小于或等于新元素的位置
5)将新元素插入到该位置
6)重复2)~5)
3、举例
整理一个无序数组 [8, 3, 5, 4, 6]
1)取出第一个数字8,得到数组[8],无序数组为[3, 5, 4, 6]
2)取出第二个数字3,插入新数组,3<8,得到[3, 8],无序数组为[5, 4, 6]
3)取出第三个数字5,插入新数组,5<8且5>3,得到[3, 5 ,8],无序数组为[4, 6]
4)取出第四个数字4,插入新数组,4<8、4<5、4>3,得到[3, 4, 5, 8],无序数组为[6]
5)最后取出数字6,插入新数组,6>5、6<8,得到[3, 4, 5, 6, 8],排序完成
4、算法实现
1)新建数组,符合条件的插入来实现插入排序
func insertSort(_ array : [Int])->[Int]{
var list = array
//建立一个空数组,符合条件的插入,没插入的尾后添加
var newList = [list[0]]
//记录循环的次数
var count = 0
for i in 1..<list.count {
// var max : Int? = nil //从大到小排序
var min : Int? = nil//从小到大排序
count = i
for j in 0..<newList.count {
// if list[i] > newList[j] {
// max = i
if list[i] < newList[j] {
min = i
newList.insert(list[i], at: j)
break
}
}
// if max == nil {
// newList.append(list[i])
// }
if min == nil {
newList.append(list[i])
}
}
print(newList)
print("count: ",count)
return newList
}
2)通过交换数组数据实现插入排序
func insertSort1(_ array : [Int])->[Int]{
var list = array
//记录循环次数
var count = 0
for i in 1..<list.count {
//从i往前找,符合条件交换
var y = i
count = i
//从大到小排序
// while y>0 && list[y]>list[y-1]{
// list.swapAt(y, y-1)
// y -= 1
// }
//从小到大排序
while y>0 && list[y]<list[y-1]{
list.swapAt(y, y-1)
y -= 1
}
}
print(list)
print("count: ",count)
return list
}
3)通过移动数组数据实现插入排序
func insertSort2(_ array : [Int])->[Int]{
var list = array
var count = 0
for i in 1..<list.count {
count = i
//从i往前找,符合条件移动
var y = i
let tmp = list[y]
//从大到小排序
// while y>0 && tmp>list[y-1]{
// list[y] = list[y-1]
// y -= 1
// }
//从小到大排序
while y>0 && tmp<list[y-1]{
list[y] = list[y-1]
y -= 1
}
list[y] = tmp
}
print(list)
print("count: ",count)
return list
}
4)插入排序实现通用化
func insertSort3<T>(_ array : [T], _ isOrderedBefore:(T, T)->Bool)->[T]{
var list = array
var count = 0
for i in 1..<list.count {
count = i
//从i往前找,符合条件移动
var y = i
let tmp = list[y]
//从大到小排序
// while y>0 && tmp>list[y-1]{
// list[y] = list[y-1]
// y -= 1
// }
//从小到大排序
while y>0 && isOrderedBefore(tmp, list[y-1]){
list[y] = list[y-1]
y -= 1
}
list[y] = tmp
}
print(list)
print("count: ",count)
return list
}
5)调用
let array3 = [8, 3, 5, 4, 6]
SortSummary.insertSort(array3)
SortSummary.insertSort1(array3)
SortSummary.insertSort2(array3)
SortSummary.insertSort3(array3, <)
//insertSort3(array3){$0<$1}等同于insertSort3(array3, <)
SortSummary.insertSort3(array3){$0<$1}
SortSummary.insertSort3(array3, >)
运行结果:
1)新建数组
[3, 4, 5, 6, 8]
count: 4
2)交换
[3, 4, 5, 6, 8]
count: 4
3)移动
[3, 4, 5, 6, 8]
count: 4
4)通用方法
//从小到大排列
[3, 4, 5, 6, 8]
count: 4
[3, 4, 5, 6, 8]
count: 4
//从大到小排列
[8, 6, 5, 4, 3]
count: 4
5、时间复杂度
1)最好的情况下,完全没有任何数据移动,即O(n)
2)最坏的情况下(平均性能表现),比较的次数为(n+2)*(n+1)/2,移动的次数最大值(n+4)*(n-1)/2, 即O(n^2)
3)平均时间复杂度为 O(n^2)
注:排序的具体实现代码在 SortSummary.swift 文件里 调用是在 ViewController.swift