1. 程式人生 > >[Swift]八大排序算法(五):插入排序

[Swift]八大排序算法(五):插入排序

統計 back alpha during item ... src float 文字

排序分為內部排序和外部排序。

內部排序:是指待排序列完全存放在內存中所進行的排序過程,適合不太大的元素序列。

外部排序:指的是大文件的排序,即待排序的記錄存儲在外存儲器上,待排序的文件無法一次裝入內存,需要在內存和外部存儲器之間進行多次數據交換,以達到排序整個文件的目的。

技術分享圖片

技術分享圖片

當N小於20的時候,插入排序具有最好的性能。

當N大於20時,快速排序具有最好的性能,盡管歸並(merge sort)和堆排序(heap sort)復雜度都為nlog2(n)。


插入排序

插入算法把要排序的數組分成兩部分:

第一部分包含了這個數組的所有元素,但將最後一個元素除外(讓數組多一個空間才有插入的位置),

第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成後,再將這個最後元素插入到已排好序的第一部分中。

插入排序的基本思想是:

每步將一個待排序的記錄,按其關鍵碼值的大小插入前面已經排序的文件中適當位置上,直到全部插入完為止。

(關鍵碼是數據元素中某個數據項的值,用它可以標示一個數據元素。通常會用記錄來標示數據元素,一個記錄可以有若幹數據項組成。)


ViewController.swift文件:運行時間(24.0695s)

  1 import UIKit
  2 
  3 class ViewController: UIViewController {
  4
//屬性1:用來存儲需要排序的數組 5 var result : Array<Int> = Array<Int>() 6 //屬性2:統計排序花費的時間 7 var date : Date! 8 9 override func viewDidLoad() { 10 super.viewDidLoad() 11 // Do any additional setup after loading the view, typically from a nib. 12 //
初始化一個整形數組 13 var array : Array<Int> = Array<Int>() 14 //將1至100的100個整數,存入到該數組中 15 for i in 1...100 16 { 17 array.append(i) 18 } 19 //添加一個循環語句, 20 //用來生成一個由100個隨機整數組成的數組 21 for _ in 1...100 22 { 23 //首先根據數組的長度, 24 //獲得一個1至100的隨機整數 25 let temp = Int(arc4random() % UInt32(array.count))+1 26 //根據隨機值從數組中獲得指定位置的整數, 27 //並存儲在用來排序的數組中 28 let num = array[temp-1] 29 result.append(num) 30 //從原數組中移該隨機數,以避免獲得重復的數字 31 array.remove(at: temp-1) 32 } 33 //添加一個循環語句, 34 //用來生成100個自定義視圖對象 35 for i in 1...100 36 { 37 //初始化自定義視圖對象 38 let num = result[i-1] 39 //並設置它的顯示區域。 40 //其中視圖的高度,是當前數組中的數字的兩倍大小 41 let view = SortView(frame: CGRect(x: 10+i*3, y: 200, width: 2, height: num * 2)) 42 view.backgroundColor = .black 43 //設置視圖的標識值 44 view.tag = i 45 //並將視圖添加到當前視圖控制器的根視圖 46 self.view.addSubview(view) 47 } 48 //然後添加一個按鈕 49 //當用戶點擊該按鈕時對數組進行排序 50 let bt = UIButton(frame: CGRect(x: 10, y: 340, width: 300, height: 40)) 51 //設置背景按鈕的背景顏色為橙色 52 bt.backgroundColor = .orange 53 //設置按鈕在正常狀態下的標題文字 54 bt.setTitle("Sort", for: .normal) 55 //給按鈕對象綁定點擊事件, 56 bt.addTarget(self, action: #selector(reOrderView), for: .touchUpInside) 57 //將按鈕添加到當前視圖控制器的根視圖 58 self.view.addSubview(bt) 59 } 60 61 //添加一個方法,用來響應按鈕的點擊事件 62 @objc func reOrderView() 63 { 64 //獲得當前的日期和時間 65 date = Date() 66 //在一個全局隊列中,以異步的方式對數組進行排序 67 //並實時調整和數組中的數值相對應的視圖的位置 68 DispatchQueue.global().async 69 { 70 //調用實例方法,用來進行可視化的插入排序。 71 //該方法在下方的代碼中實現 72 self.sort(items: self.result) 73 //獲得排序後的系統時間, 74 //並在控制臺輸出兩個時間的差值, 75 //從而獲得排序所花費的大致時間。 76 //考慮線程休眠的影響,此數據僅做參考 77 let endDate = Date() 78 print(endDate.timeIntervalSince(self.date)) 79 } 80 } 81 82 //添加一個方法,用來實現具體的可視化的插入排序的功能 83 func sort(items: Array<Int>) 84 { 85 //獲得進行排序的數組 86 var list = items 87 //首先將數組中的第一個元素,看成是已經完成排序的數組。 88 //然後從第二個元素開始,通過循環語句, 89 //將未排序的元素, 90 //由後向前完成排序的數組進行比較和插入 91 for i in 1..<list.count 92 { 93 var j = i 94 while j > 0 95 { 96 //將待排序的元素, 97 //由後向前,和每個已經完成排序的元素進行比較, 98 //當該元素小於已經完成排序的元素時, 99 //將該元素插入到找到的元素的前方, 100 //否則退出循環 101 if list[j] < list[j - 1] 102 { 103 //由於需要對界面元素進行調整, 104 //所以需要切換至主線程 105 weak var weak_self = self 106 DispatchQueue.main.async 107 { 108 //根據標識值, 109 //獲得和需要交換順序的數組元素相對應的視圖對象 110 let view1 = weak_self?.view.viewWithTag(j+1) 111 let view2 = weak_self?.view.viewWithTag(j) 112 //獲得兩個視圖對象的水平坐標X的值 113 let posX1 = view1?.frame.origin.x 114 let posX2 = view2?.frame.origin.x 115 //然後交換兩個視圖對象的水平坐標的值 116 //從而實現兩個視圖對象的位置的交 117 view1?.frame.origin.x = posX2! 118 view2?.frame.origin.x = posX1! 119 //記得更換兩個視圖對象的標識值 120 view1?.tag = j 121 view2?.tag = j+1 122 //交換數組中的兩個元素的位置 123 let temp = list[j] 124 list[j] = list[j-1] 125 list[j-1] = temp 126 //將第二個循環語句的索引值減1,實現從後往前的遍歷和比較 127 j = j - 1 128 } 129 //使線程休眠0.01秒, 130 //以方便觀察排序的視覺效果 131 Thread.sleep(forTimeInterval: 0.01) 132 } 133 else 134 { 135 //否則退出循環 136 break 137 } 138 } 139 } 140 } 141 142 override func didReceiveMemoryWarning() { 143 super.didReceiveMemoryWarning() 144 // Dispose of any resources that can be recreated. 145 } 146 }

SortView.swift文件

 1 import UIKit
 2 
 3 class SortView: UIView {
 4     //首先重寫父類的初始化方法
 5     override init(frame: CGRect)
 6     {
 7         //設置自定義視圖對象的顯示區域
 8         super.init(frame: frame)
 9         self.frame = frame
10     }
11 
12     //添加一個必須實現的初始化方法
13     required init?(coder aDecoder: NSCoder) {
14         fatalError("init(coder:) has not been implemented")
15     }
16     
17     //重寫父類的重新布局子視圖方法
18     //將在此視圖中對視圖進行外觀設置
19     override func layoutSubviews()
20     {
21         //首先獲得自定義視圖在界面中對Y軸坐標
22         let y: CGFloat = 300 - frame.height
23         //然後重新設置自定義視圖的位置
24         self.frame = frame
25         self.frame.origin.y = y
26         //根據自定義視圖的高度,計算一個權重數值
27         //用於生成不同的背景顏色
28         let weight = frame.height / 200
29         //生成不同y色相的顏色對象,從而給自定義視圖設置不同的背景顏色
30         //然後打開ViewController.swift文件
31         let color = UIColor(hue: weight, saturation: 1, brightness: 1, alpha: 1)
32         self.backgroundColor = color
33     }
34     /*
35     // Only override draw() if you perform custom drawing.
36     // An empty implementation adversely affects performance during animation.
37     override func draw(_ rect: CGRect) {
38         // Drawing code
39     }
40     */
41 }

[Swift]八大排序算法(五):插入排序