算法思想
- 基于LSD方法的链式基数排序的基本思想
“多关键字排序”的思想实现“单关键字排序”。对数字型或字符型的单关键字,可以看作由多个数位或多个字符构成的多关键字,此时可以采用“分配-收集”的方法进行排序,这一过程称作基数排序法,其中每个数字或字符可能的取值个数称为基数。比如,扑克牌的花色基数为4,面值基数为13。在整理扑克牌时,既可以先按花色整理,也可以先按面值整理。按花色整理时,先按红、黑、方、花的顺序分成4摞(分配),再按此顺序再叠放在一起(收集),然后按面值的顺序分成13摞(分配),再按此顺序叠放在一起(收集),如此进行二次分配和收集即可将扑克牌排列有序。
基数排序实现步骤
* 判断数据在各位的大小,排列数据
* 根据上一步的结果,判断数据在十分位的大小,排列数据。如果数据在这个位置的余数相同,那么数据之间的顺序根据上一轮的排列顺序确定
* 依次类推,继续判断数据在百分位、千分位......上面的数据重新排序,直到所有的数据在某一分位上数据都为0
- 基数排序实现步骤实例
假设有欲排数据序列如下所示:
73 22 93 43 55 14 28 65 39 81
首先根据个位数的数值,在遍历数据时将它们各自分配到编号0至9的桶(个位数值与桶号一一对应)中。
分配结束后。接下来将所有桶中所盛数据按照桶号由小到大(桶中由顶至底)依次重新收集串起来,得到如下仍然无序的数据序列:
81 22 73 93 43 14 55 65 28 39
接着,再进行一次分配,这次根据十位数值来分配(原理同上)
分配结束后。接下来再将所有桶中所盛的数据(原理同上)依次重新收集串接起来,得到如下的数据序列:
14 22 28 39 43 55 65 73 81 93
观察可以看到,此时原无序数据序列已经排序完毕。如果排序的数据序列有三位数以上的数据,则重复进行以上的动作直至最高位数为止。
代码
#pragma mark --- 基数排序
/**
基数排序
*/
import UIKit
class ViewController: UIViewController {
var intArray:[Int] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
for _ in 0..<20 {
intArray.append(Int(arc4random()%30))
}
let tempArr = radixSort(&intArray)
for item in tempArr {
print(item)
}
}
func radixSort(_ array:inout [Int]) ->[Int] {
//待排数组的最大数值
let maxNumber = listMaxItem(array)
//最大数值的数字位数
let maxLength = numberLength(maxNumber)
for digit in 1...maxLength {
//创建空桶
var bucket:[[Int]] = createBucket()
// 入桶
for item in array {
//确定item 归属哪个桶 以digit位数为基数
let baseNumber = fetchBaseNumber(item, digit)
var mutArray = bucket[baseNumber]
mutArray.append(item)
bucket[baseNumber] = mutArray
}
var index = 0
//出桶
for i in 0..<bucket.count {
var arrayTemp = bucket[i]
//将桶的数据放回待排数组中
while arrayTemp.count != 0 {
let number = arrayTemp[0]
array[index] = number
arrayTemp.removeFirst()
index += 1
}
}
}
return array
}
//MARK:创建空桶
func createBucket() ->[[Int]] {
var bucket:[[Int]] = []
for _ in 0..<10 {
let tempArray:[Int] = []
bucket.append(tempArray)
}
return bucket
}
//MARK:数据最大值
func listMaxItem(_ array:[Int]) ->Int {
var maxNumber = array[0]
for ele in array {
if ele > maxNumber {
maxNumber = ele
}
}
return maxNumber
}
//MARK:数字的位数
func numberLength(_ number:Int) ->Int {
let numberStr = String(number)
return numberStr.count
}
func fetchBaseNumber(_ number:Int,_ digit:Int) ->Int {
let length = numberLength(number)
//digit为基数位数
if digit > 0 && digit <= length {
//number的位数确定
let string = String(number)
let strArr:[Character] = Array(string)
let str:Character = strArr[strArr.count - digit]
return Int.init(String(str))!
}
return 0
}
}
以上代码仅限数字排序,加入数字+字母的组合呢?
0~9:对应0~9,a~z:对应10~36
将以上代码修改为:
- 1.创建空桶为0~36
- 2.数据最大值改为最长字符串
- 3.数字的位数改为字符串的长度 按以上修改即可