[Swift]八大排序算法(八):基数排序
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
?微信公眾號(hào):山青詠芝(shanqingyongzhi)
?博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/?)
?GitHub地址:https://github.com/strengthen/LeetCode
?原文地址:https://www.cnblogs.com/strengthen/p/9866566.html?
?如果鏈接不是山青詠芝的博客園地址,則可能是爬取作者的文章。
?原文已修改更新!強(qiáng)烈建議點(diǎn)擊原文地址閱讀!支持作者!支持原創(chuàng)!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
排序分為內(nèi)部排序和外部排序。
內(nèi)部排序:是指待排序列完全存放在內(nèi)存中所進(jìn)行的排序過(guò)程,適合不太大的元素序列。
外部排序:指的是大文件的排序,即待排序的記錄存儲(chǔ)在外存儲(chǔ)器上,待排序的文件無(wú)法一次裝入內(nèi)存,需要在內(nèi)存和外部存儲(chǔ)器之間進(jìn)行多次數(shù)據(jù)交換,以達(dá)到排序整個(gè)文件的目的。
當(dāng)N小于20的時(shí)候,插入排序具有最好的性能。
當(dāng)N大于20時(shí),快速排序具有最好的性能,盡管歸并排序(merge sort)和堆排序(heap sort)復(fù)雜度都為nlog2(n)。
基數(shù)排序
基數(shù)排序(Radix Sort)屬于“分配式排序”(distribution sort),又稱“桶子法”(bucket sort)或bin sort,顧名思義,它是透過(guò)鍵值的部份信息,將要排序的元素分配至某些“桶”中,藉以達(dá)到排序的作用。
基數(shù)排序法是屬于穩(wěn)定性的排序,其時(shí)間復(fù)雜度為O(nlog(r)m),其中r為所采取的基數(shù),而m為堆數(shù),在某些時(shí)候,基數(shù)排序法的效率高于其它的穩(wěn)定性排序法。
基本思想:
將整數(shù)按位數(shù)切割成不同的數(shù)字,然后按每個(gè)位數(shù)分別比較。
具體做法:
將所有待比較數(shù)值統(tǒng)一為同樣的數(shù)位長(zhǎng)度,數(shù)位較短的數(shù)前面補(bǔ)零。
然后,從最低位開(kāi)始,依次進(jìn)行一次排序。這樣從最低位排序一直到最高位排序完成以后, 數(shù)列就變成一個(gè)有序序列。
?ViewController.swift文件:運(yùn)行時(shí)間(3.3862s)
1 import UIKit 2 3 class ViewController: UIViewController { 4 //屬性1:用來(lái)存儲(chǔ)需要排序的數(shù)組 5 var result : Array<Int> = Array<Int>() 6 //屬性2:統(tǒng)計(jì)排序花費(fèi)的時(shí)間 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 //初始化一個(gè)整形數(shù)組 13 var array : Array<Int> = Array<Int>() 14 //將1至100的100個(gè)整數(shù),存入到該數(shù)組中 15 for i in 1...100 16 { 17 array.append(i) 18 } 19 //添加一個(gè)循環(huán)語(yǔ)句, 20 //用來(lái)生成一個(gè)由100個(gè)隨機(jī)整數(shù)組成的數(shù)組 21 for _ in 1...100 22 { 23 //首先根據(jù)數(shù)組的長(zhǎng)度, 24 //獲得一個(gè)1至100的隨機(jī)整數(shù) 25 let temp = Int(arc4random() % UInt32(array.count))+1 26 //根據(jù)隨機(jī)值從數(shù)組中獲得指定位置的整數(shù), 27 //并存儲(chǔ)在用來(lái)排序的數(shù)組中 28 let num = array[temp-1] 29 result.append(num) 30 //從原數(shù)組中移該隨機(jī)數(shù),以避免獲得重復(fù)的數(shù)字 31 array.remove(at: temp-1) 32 } 33 //添加一個(gè)循環(huán)語(yǔ)句, 34 //用來(lái)生成100個(gè)自定義視圖對(duì)象 35 for i in 1...100 36 { 37 //初始化自定義視圖對(duì)象 38 let num = result[i-1] 39 //并設(shè)置它的顯示區(qū)域。 40 //其中視圖的高度,是當(dāng)前數(shù)組中的數(shù)字的兩倍大小 41 let view = SortView(frame: CGRect(x: 10+i*3, y: 200, width: 2, height: num * 2)) 42 view.backgroundColor = .black 43 //設(shè)置視圖的標(biāo)識(shí)值 44 view.tag = i 45 //并將視圖添加到當(dāng)前視圖控制器的根視圖 46 self.view.addSubview(view) 47 } 48 //然后添加一個(gè)按鈕 49 //當(dāng)用戶點(diǎn)擊該按鈕時(shí)對(duì)數(shù)組進(jìn)行排序 50 let bt = UIButton(frame: CGRect(x: 10, y: 340, width: 300, height: 40)) 51 //設(shè)置背景按鈕的背景顏色為橙色 52 bt.backgroundColor = .orange 53 //設(shè)置按鈕在正常狀態(tài)下的標(biāo)題文字 54 bt.setTitle("Sort", for: .normal) 55 //給按鈕對(duì)象綁定點(diǎn)擊事件, 56 bt.addTarget(self, action: #selector(reOrderView), for: .touchUpInside) 57 //將按鈕添加到當(dāng)前視圖控制器的根視圖 58 self.view.addSubview(bt) 59 } 60 61 //添加一個(gè)方法,用來(lái)響應(yīng)按鈕的點(diǎn)擊事件 62 @objc func reOrderView() 63 { 64 //獲得當(dāng)前的日期和時(shí)間 65 date = Date() 66 //在一個(gè)全局隊(duì)列中,以異步的方式對(duì)數(shù)組進(jìn)行排序 67 //并實(shí)時(shí)調(diào)整和數(shù)組中的數(shù)值相對(duì)應(yīng)的視圖的位置 68 DispatchQueue.global().async 69 { 70 //調(diào)用實(shí)例方法,用來(lái)實(shí)現(xiàn)可視化的基數(shù)排序, 71 //該方法在下方的代碼中實(shí)現(xiàn) 72 self.radixSort(list: &self.result) 73 //獲得排序后的系統(tǒng)時(shí)間, 74 //并在控制臺(tái)輸出兩個(gè)時(shí)間的差值, 75 //從而獲得排序所花費(fèi)的大致時(shí)間。 76 //考慮線程休眠的影響,此數(shù)據(jù)僅做參考 77 let endDate = Date() 78 print(endDate.timeIntervalSince(self.date)) 79 } 80 } 81 82 //添加一個(gè)方法,用來(lái)實(shí)現(xiàn)具體的可視化的基數(shù)排序的功能 83 private func radixSort(list: inout Array<Int>) 84 { 85 //首先初始化一個(gè)二維數(shù)組,作為10個(gè)空桶 86 //每個(gè)空桶作為子數(shù)組, 87 //分別存儲(chǔ)位數(shù)為0至9的所有元素 88 var bucket: Array<Array<Int>> = [] 89 //通過(guò)一循環(huán)語(yǔ)句, 90 //往二維數(shù)組中添加10個(gè)空數(shù)組 91 for _ in 0..<10 92 { 93 bucket.append([]) 94 } 95 //接著來(lái)獲得數(shù)組中的所有元素的最大值, 96 //從而獲得位數(shù)最多的元素。 97 //例如數(shù)組中的最大值為1234 98 //那么它的位數(shù)為4,并且也是數(shù)組中所有元素最大的位數(shù)。 99 var maxNumber = list[0] 100 //通過(guò)循環(huán)語(yǔ)句,獲得數(shù)組中元素的最大值 101 for item in list 102 { 103 if maxNumber < item 104 { 105 maxNumber = item 106 } 107 } 108 //將該元素轉(zhuǎn)換為字符串, 109 //從而通過(guò)字符串的長(zhǎng)度, 110 //獲得該元素的位數(shù)。 111 let maxLength = "\(maxNumber)".count 112 //添加一個(gè)循環(huán)語(yǔ)句,循環(huán)區(qū)間為1到最大位數(shù)。 113 //該循環(huán)語(yǔ)句用來(lái)進(jìn)行基數(shù)排序 114 for digit in 1...maxLength 115 { 116 //通過(guò)一個(gè)實(shí)例方法,獲得指定位數(shù)的值,并添加到對(duì)應(yīng)的桶數(shù)組中。 117 //例如當(dāng)digit的值為1時(shí),表示獲得個(gè)位數(shù)的值, 118 //并存儲(chǔ)在對(duì)應(yīng)的桶(子數(shù)組)中 119 for item in list 120 { 121 let baseNumber = fetchBaseNumber(number: item, digit: digit) 122 bucket[baseNumber].append(item) 123 } 124 //到此完成了入桶操作,接著進(jìn)行出桶操作。 125 //即將所有桶中的數(shù)據(jù)全部取出,并依次放在數(shù)組中。 126 //首先初始化一個(gè)整形變量,作為索引值。 127 var index = 0 128 //添加一個(gè)循環(huán)語(yǔ)句,對(duì)十個(gè)桶進(jìn)行遍歷 129 for i in 0..<bucket.count 130 { 131 //添加另一個(gè)循環(huán)語(yǔ)句,進(jìn)行出桶的操作, 132 //直到桶的數(shù)據(jù)為空。 133 while !bucket[i].isEmpty 134 { 135 //將桶中的第一個(gè)元素刪除 136 //并將返回的被刪除的元素, 137 //存入數(shù)組中指定的索引位置。 138 list[index] = bucket[i].remove(at: 0) 139 //接著同步更新界面中對(duì)應(yīng)的視圖對(duì)象的高度 140 self.udpateView(j: index, height: list[index]) 141 index += 1 142 } 143 } 144 } 145 } 146 147 //添加一個(gè)方法,用來(lái)獲得指定位數(shù)的值, 148 //例如獲取某個(gè)數(shù)字的個(gè)位、十位、千位等的值 149 func fetchBaseNumber(number: Int, digit: Int) -> Int 150 { 151 //在此將數(shù)字轉(zhuǎn)換為字符串的方式 152 //來(lái)獲得指定位數(shù)的值 153 if digit > 0 && digit <= "\(number)".count 154 { 155 //初始化一個(gè)整形數(shù)組,用來(lái)存儲(chǔ)數(shù)字的每個(gè)位數(shù)的值 156 var numbersArray: Array<Int> = [] 157 //通過(guò)一個(gè)循環(huán)語(yǔ)句,將數(shù)字的每個(gè)位數(shù), 158 //添加到整形數(shù)組中 159 for char in "\(number)".characters 160 { 161 numbersArray.append(Int("\(char)")!) 162 } 163 //最后根據(jù)位數(shù),獲取并返回?cái)?shù)組中的值 164 return numbersArray[numbersArray.count - digit] 165 } 166 //采用0作為默認(rèn)值 167 return 0 168 } 169 170 //添加一個(gè)方法,用來(lái)更新視圖的高度 171 func udpateView(j: Int, height: Int) 172 { 173 //由于需要對(duì)界面元素進(jìn)行調(diào)整, 174 //所以需要切換至主線程 175 weak var weak_self = self 176 DispatchQueue.main.async 177 { 178 //根據(jù)標(biāo)識(shí)值, 179 //獲得和需要交換順序的數(shù)組元素相對(duì)應(yīng)的視圖對(duì)象 180 //并設(shè)置它的新的高度 181 let view = weak_self?.view.viewWithTag(j+1) 182 view?.frame.size.height = CGFloat(height*2) 183 } 184 //使線程休眠0.01秒, 185 //以方便觀察排序的視覺(jué)效果 186 Thread.sleep(forTimeInterval: 0.01) 187 } 188 189 override func didReceiveMemoryWarning() { 190 super.didReceiveMemoryWarning() 191 // Dispose of any resources that can be recreated. 192 } 193 }SortView.swift文件
1 import UIKit 2 3 class SortView: UIView { 4 //首先重寫(xiě)父類的初始化方法 5 override init(frame: CGRect) 6 { 7 //設(shè)置自定義視圖對(duì)象的顯示區(qū)域 8 super.init(frame: frame) 9 self.frame = frame 10 } 11 12 //添加一個(gè)必須實(shí)現(xiàn)的初始化方法 13 required init?(coder aDecoder: NSCoder) { 14 fatalError("init(coder:) has not been implemented") 15 } 16 17 //重寫(xiě)父類的重新布局子視圖方法 18 //將在此視圖中對(duì)視圖進(jìn)行外觀設(shè)置 19 override func layoutSubviews() 20 { 21 //首先獲得自定義視圖在界面中對(duì)Y軸坐標(biāo) 22 let y: CGFloat = 300 - frame.height 23 //然后重新設(shè)置自定義視圖的位置 24 self.frame = frame 25 self.frame.origin.y = y 26 //根據(jù)自定義視圖的高度,計(jì)算一個(gè)權(quán)重?cái)?shù)值 27 //用于生成不同的背景顏色 28 let weight = frame.height / 200 29 //生成不同y色相的顏色對(duì)象,從而給自定義視圖設(shè)置不同的背景顏色 30 //然后打開(kāi)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 }?
轉(zhuǎn)載于:https://www.cnblogs.com/strengthen/p/9866566.html
總結(jié)
以上是生活随笔為你收集整理的[Swift]八大排序算法(八):基数排序的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 汇编常用指令
- 下一篇: 使用花生壳做内网穿透