原理:算法
- 比較相鄰的元素。若是第一個比第二個大,就交換他們兩個。
- 對每一對相鄰元素作一樣的工做,從開始第一對到結尾的最後一對。在這一點,最後的元素應該會是最大的數。
- 針對全部的元素重複以上的步驟,除了最後一個。
- 持續每次對愈來愈少的元素重複上面的步驟,直到沒有任何一對數字須要比較
時間複雜度:數組
///冒泡函數代碼實現
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
}
}
複製代碼