原理:算法
- 比较相邻的元素。若是第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作一样的工做,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对全部的元素重复以上的步骤,除了最后一个。
- 持续每次对愈来愈少的元素重复上面的步骤,直到没有任何一对数字须要比较
时间复杂度:数组
///冒泡函数代码实现
func bubbleSort(_ arr: inout [Double]) {
for i in 0 ..< arr.count {
for j in 0 ..< arr.count - i {
if j+1 < arr.count {
if arr[j] > arr[j+1] {
let temp = arr[j]
arr[j] = arr[j+1]
arr[j+1] = temp
}
}
}
}
}
复制代码
原理:bash
- 从第一个元素开始,该元素能够认为已经被排序
- 取出下一个元素,在已经排序的元素序列中从后向前扫描
- 若是该元素(已排序)大于新元素,将该元素移到下一位置
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
- 将新元素插入到下一位置中
- 重复步骤2~5
若是比较操做的代价比交换操做大的话,能够采用二分查找法来减小比较操做的数目。该算法能够认为是插入排序的一个变种,称为二分查找排序。数据结构
时间复杂度:app
///插入排序的实现
func insertSort(_ arr: inout [Double]) {
//从第1位开始做为要插入的数
for i in 1 ..< arr.count {
let temp = arr[i]
var j = i - 1
while (j >= 0 && temp < arr[j]) {
//与已排序的数逐一比较,大于temp时,该数移后
arr[j + 1] = arr[j]
j -= 1
}
if j != i - 1 {
//在相应的位置插入(由于上面j-1跳出while循环,因此这里是j+1)
arr[j + 1] = temp
}
}
}
复制代码
原理:函数
对比数组中前一个元素跟后一个元素的大小,若是后面的元素比前面的元素小则用一个变量k来记住他的位置,接着第二次比较,前面“后一个元素”现变成了“前一个元素”,继续跟他的“后一个元素”进行比较若是后面的元素比他要小则用变量k记住它在数组中的位置(下标),等到循环结束的时候,咱们应该找到了最小的那个数的下标了,而后进行判断,若是这个元素的下标不是第一个元素的下标,就让第一个元素跟他交换一下值,这样就找到整个数组中最小的数了。而后找到数组中第二小的数,让他跟数组中第二个元素交换一下值,以此类推ui
时间复杂度: ,不稳定spa
选择排序的交换操做介于 0 和 (n - 1) 次之间。选择排序的比较操做为 n (n - 1) / 2 次之间。选择排序的赋值操做介于 0 和 3 (n - 1) 次之间。 比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2。交换次数O(n),最好状况是,已经有序,交换0次;最坏状况交换n-1次,逆序交换n/2次。交换次数比冒泡排序少多了,因为交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。设计
///选择排序
func selectionSort(_ arr: inout [Double]) {
for i in 0 ..< arr.count-1 {
var min = i
//找出最小值的位置
for j in i+1 ..< arr.count {
if arr[min] > arr[j] {
min = j
}
}
//若是最小值的下标不是i,就交换
if min != i {
let temp = arr[i]
arr[i] = arr[min]
arr[min] = temp
}
}
}
复制代码
堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似彻底二叉树的结构,并同时知足堆积的性质:即子结点的键值或索引老是小于(或者大于)它的父节点。code
原理:
- 将无序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
- 将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
- 从新调整结构,使其知足堆定义,而后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
时间复杂度:,不稳定
/*
堆排序
*/
//调整一个根节点和左右节点的位置
func adjustHeap(arr:inout [Double],i: Int,length: Int) {
let temp = arr[i]
var tempNum = i
var left = 2 * i + 1
while left < length {
///若是右节点存在,且大于左节点,取右节点
if left+1 < length && arr[left + 1] > arr[left]{
left += 1
}
///若是父节点已经大于子节点
if temp >= arr[left] {
break
}
arr[tempNum] = arr[left]
tempNum = left
left = 2*left + 1
}
arr[tempNum] = temp
}
//互换数组元素
func swapArr(arr: inout [Double],index1: Int,index2:Int) {
let temp = arr[index1]
arr[index1] = arr[index2]
arr[index2] = temp
}
///堆排序
func heapSort(_ arr: inout [Double]) {
///建立初始化堆
var i = arr.count/2
while i >= 0 {
adjustHeap(arr: &arr, i: i, length: arr.count)
i -= 1
}
var j = arr.count - 1
while j > 0 {
swapArr(arr: &arr, index1: 0, index2: j)
adjustHeap(arr: &arr, i: 0, length: j)
j -= 1
}
}
复制代码
原理:
将无序的序列分红子序列,将子序列排序在合成有序的序列。
例如:初始状态:6,202,100,301,38,8,1
- 第一次归并后:{6,202},{100,301},{8,38},{1}
- 第二次归并后:{6,100,202,301},{1,8,38}
- 第三次归并后:{1,6,8,38,100,202,301}
时间复杂度:
///归并排序的实现
func mergeSort(_ arr: inout [Double]) {
var temp = Array<Double>(repeating:0, count: arr.count)
helperSort(arr: &arr, left: 0, right: arr.count-1,temp: &temp)
}
///分
func helperSort(arr: inout [Double], left: Int, right: Int, temp: inout [Double]) {
if left < right {
let mid = (left + right)/2
///递归分数组左边元素
helperSort(arr: &arr, left: left, right: mid,temp: &temp)
///递归分数组右边元素
helperSort(arr: &arr, left: mid+1, right: right,temp: &temp)
///递归合并子数组
merge(arr: &arr, left: left, right: right, mid: mid, temp: &temp)
}
}
///合
func merge(arr: inout [Double], left: Int, right: Int, mid: Int, temp: inout [Double]) {
var i = left //
var j = mid + 1
var t = 0 //临时数组下标
///把左边和右边的元素按顺序放进temp
while i <= mid && j <= right {
if arr[i] <= arr[j] {
temp[t] = arr[i]
t += 1
i += 1
}else {
temp[t] = arr[j]
t += 1
j += 1
}
}
///将左边剩余元素放进temp中
while i <= mid {
temp[t] = arr[i]
t += 1
i += 1
}
//将右边剩余元素放进temp中
while j <= right {
temp[t] = arr[j]
t += 1
j += 1
}
//将temp中的元素所有拷贝到原数组中
i = left
t = 0
while i <= right {
arr[i] = temp[t];
i += 1
t += 1
}
}
复制代码
原理:
已知数组:A[n]
- 设置两个变量i、j,排序开始的时候:i = 0,j = N-1
- 以第一个数组元素做为关键数据,赋值给key,即key = A[0]
- 从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]的值赋给A[i]
- 从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]的值赋给A[j] 5.重复第三、4步,直到i = j
时间复杂度:
///快速排序的实现
///大于基数的数放在右边,小于基数的数放在左边
func quicklySort(arr: inout [Double], left: Int, right: Int) {
if left >= right {
return
}
let num = arr[left] //取第一个数做为基数
var l = left
var r = right
while l < r {
//从右边遍历
while l < r && arr[r] >= num{
r -= 1
}
arr[l] = arr[r]
while l < r && arr[l] <= num{
l += 1
}
arr[r] = arr[l]
}
arr[l] = num
quicklySort(arr: &arr, left: left, right: l - 1)
quicklySort(arr: &arr, left: l + 1 , right: right)
}
复制代码
原理:
首先要排序的数都是整数
- 找出最大值max和最小值min
- 建立一个大小为max-min+1的数组Temp,每一个元素的值都为0
- 遍历数,找到Temp对应的下标的元素加1,即统计数出现的次数
- 经过遍历Temp,根据统计的每一个数的次数,相对应的排序
计数排序是一种非比较类型的算法,因此没有O(nlogn)的下限,是经过牺牲空间换时间的算法。
时间复杂度:
//计数排序的实现
func countSort(_ arr: inout [Int]) {
if arr.count <= 1 {
return
}
//找出最大值和最小值
var max = arr[0]
var min = arr[0]
for num in arr {
if num >= max {
max = num
}
if min >= num{
min = num
}
}
let len = max - min + 1
var temp = Array<Int>(repeatElement(0, count: len))
//统计每一个数出现的次数
for num in arr {
temp[num - min] = temp[num - min] + 1
}
print(temp)
var nextIndex = 0;
for i in 0 ..< temp.count {
var val = temp[i]
while val > 0 {
arr[nextIndex] = i + min;
nextIndex = nextIndex + 1
val = val - 1
}
}
}
复制代码
原理:
- 找出最大值max和最小值min
- 给定一个桶的数量,建立一个桶数组(二维数组),每一个桶的范围为(max-min+1)/桶的数量
- 遍历数,把数值添加到对应范围的桶中,若是桶中有其余数值,按要求排序
- 经过遍历桶数组,获得一个顺序的数组
时间复杂度:
///桶排序
///bucketCount是桶的大小
func bucketSort(_ arr: inout [Double], bucketCount:Int) {
if arr.count <= 1 || bucketCount <= 0 {
return
}
//找出最大值和最小值
var max = arr[0]
var min = arr[0]
for num in arr {
if num >= max {
max = num
}
if min >= num{
min = num
}
}
//每一个桶的数值范围
let space = (max - min + 1) / Double(bucketCount)
var buckets = Array<Array<Double>>(repeating: [Double](), count: bucketCount)
//将数值放到对应范围的桶中
for i in 0 ..< arr.count {
///数值对应的桶
let index = Int((arr[i] - min) / space)
//
if buckets[index].isEmpty {
buckets[index].append(arr[i])
}else {
///从小到大排序
for j in 0 ..< buckets[index].count {
if arr[i] > buckets[index][j] {
buckets[index].insert(arr[i], at: j + 1)
}
}
}
}
///排序全部的桶
var n = 0
var index = 0
while n < buckets.count {
let bucket = buckets[n]
if !bucket.isEmpty {
arr.insert(contentsOf: bucket, at: index)
index += bucket.count
}
n = n + 1
}
}
复制代码