原文链接
在实际应用中常常用到排序算法,这篇文来总结一下常用的。上面是原文链接,文章里介绍很详细,还有动图示例,形象易懂。
重复的内容不再赘述,看原文就好,这里写一写我常用到的。
冒泡排序
这个记的最深刻,也是最常用的,因为一遇到排序问题,首先想到的就是冒泡。原理很简单,一句话总结就是,每次将未排序部分的极值移动到尾端。如果是升序排列,那么每次寻找的就是最大值,反之则是最小值。这个过程,就像是在冒泡。
1 | val arr = intArrayOf(3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48) |
选择排序
这个和冒泡排序很像,第一次从所有元素中找到极值放到第一位,第二次从剩下的元素中找到极值放到第二位,以此类推。
1 | // 选择排序 |
快速排序
- 这是个有趣的排序算法,使用递归
- 选择一个基准值,一般选左端,或者右端
- 目标是把比基准值小的放到左边,大的放到右边
- 如果选择左端则从右端指针开始判断,反之从左端指针开始
- 这里假设选择左端为基准值,所以从右端指针开始扫描
- 用临时变量存储基准值,此时可认为左指针指向的位置是空
- 如果右指针比基准值小,则将右指针的值填充到左指针,此时认为右指针位置是空
- 此时用左指针扫描
- 遇到比基准值大的时候,将左指针的值填充到右指针,此时认为左指针位置为空
- 此时用右指针扫描
- 直到两个指针相遇,将临时变量的基准值填充到任一指针
- 然后将基准值左右两部分,分别递归
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34fun quick(low: Int,high: Int, array: IntArray) {
if (low >= high) return
var left = low
var right = high
val temp = array[left]
var reverse = true
while (left < right) {
if (reverse) {
// 从右指针扫描
// 当值比基准值小时,右指针的值填充到左指针,此时认为右指针为空
if (array[right] < temp) {
array[left] = array[right]
reverse = !reverse // 掉头
} else {
right-- // 右指针左移动
}
} else {
// 从左指针扫描
// 当值比基准值大时,左指针填充到右指针,此时认为左指针为空
if (array[left] > temp) {
array[right] = array[left]
reverse = !reverse // 调用
} else {
left++ // 左指针右移动
}
}
}
// 一趟结束后,指针相遇,把基准值放到指针所在位置
// 此时左侧都比基准值小,右侧都比基准值大
array[left] = temp
// 分别递归左侧和右侧
quick(low, left - 1, array)
quick(left + 1, high, array)
}
插入排序
- 将序列分为两部分,左侧是已经排好顺序的,右侧是未排的
- 每次从未排序列中取一个数字,将其插入到已排好部分
- 循环至排序完成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17fun insert(array: IntArray) {
var border = 0 // 左侧已排序部分的边界
while (border < array.size - 1) {
// 每次取右侧未排序部分的第一个数字,将其插入到左侧的目标位置
for (i in border downTo 0) {
if (array[i + 1] < array[i]) {
// 异或操作交换值,不用额外的临时变量
array[i] = array[i] xor array[i + 1]
array[i + 1] = array[i] xor array[i + 1]
array[i] = array[i] xor array[i + 1]
} else {
break
}
}
border++
}
}
https://github.com/oynix/SortAlgorithmSample