理论知识
「排序算法」对数据进行排序(从小到大,从大到小等)的过程中使用的算法,主要是为了能够节省空间,缩小耗时等目的。
「稳定性」判断条件为相同元素是否会更换位置。
冒泡排序
定义
重复元素列表,然后依次比较两个相邻的元素,如果顺序错误就交换位置,直到没有相邻元素需要交换。
代码
/**
* 冒泡排序
* 排序前:[2,5,8,4,1,7,9,3,6]
* 排序后:[1,2,3,4,5,6,7,8,9]
*/
fun bubbleSort(numArray: IntArray): IntArray {
for (index in 1 until numArray.size) {
var flag = true
for (i in 0 until numArray.size - index) {
if (numArray[i] > numArray[i + 1]) {
val temp = numArray[i]
numArray[i] = numArray[i + 1]
numArray[i + 1] = temp
flag = false
}
}
Log.e("bubbleSort===", numArray.contentToString())
if (flag) break
}
return numArray
}
//运行结果
bubbleSort===: [2, 5, 4, 1, 7, 8, 3, 6, 9]
bubbleSort===: [2, 4, 1, 5, 7, 3, 6, 8, 9]
bubbleSort===: [2, 1, 4, 5, 3, 6, 7, 8, 9]
bubbleSort===: [1, 2, 4, 3, 5, 6, 7, 8, 9]
bubbleSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]
bubbleSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]
推导过程
特性
| 时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|
| O(n^2) | O(1) | 稳定 |
选择排序
定义
不断从待排的元素列表中选出最小(或最大)的一个元素,放到已顺序排列(从小到大或者从大到小)的列表后面一位,直到全部元素都排列完成。
代码
/**
* 选择排序
* 排序前:[2,5,8,4,1,7,9,3,6]
* 排序后:[1,2,3,4,5,6,7,8,9]
*/
fun selectSort(numArray: IntArray): IntArray {
for (i in numArray.indices) {
var minIndex = i
var j = i + 1
while (j in numArray.indices) {
if (numArray[j] < numArray[minIndex]) {
minIndex = j
}
j++
}
if (i != minIndex) {
val temp = numArray[i]
numArray[i] = numArray[minIndex]
numArray[minIndex] = temp
}
Log.e("selectSort===", numArray.contentToString()+"==="+i)
}
return numArray
}
//运行结果
selectSort===: [1, 5, 8, 4, 2, 7, 9, 3, 6]===0
selectSort===: [1, 2, 8, 4, 5, 7, 9, 3, 6]===1
selectSort===: [1, 2, 3, 4, 5, 7, 9, 8, 6]===2
selectSort===: [1, 2, 3, 4, 5, 7, 9, 8, 6]===3
selectSort===: [1, 2, 3, 4, 5, 7, 9, 8, 6]===4
selectSort===: [1, 2, 3, 4, 5, 6, 9, 8, 7]===5
selectSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]===6
selectSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]===7
selectSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]===8
推导过程
特性
| 时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|
| O(n^2) | O(1) | 不稳定 |
插入排序
定义
将待排序元素插入到已排序的有序表中,从而得到一个新的有序表。
代码
/**
* 插入排序
* 排序前:[2,5,8,4,1,7,9,3,6]
* 排序后:[1,2,3,4,5,6,7,8,9]
*/
fun insertSort(numArray: IntArray): IntArray {
for (i in 1 until numArray.size) {
val tmp: Int = numArray[i]
var j = i
while (j > 0 && tmp < numArray[j - 1]) {
numArray[j] = numArray[j - 1]
j--
}
if (j != i) {
numArray[j] = tmp
}
Log.e("insertSort===", numArray.contentToString() + "===" + i)
}
return numArray
}
//运行结果
insertSort===: [2, 5, 8, 4, 1, 7, 9, 3, 6]===1
insertSort===: [2, 5, 8, 4, 1, 7, 9, 3, 6]===2
insertSort===: [2, 4, 5, 8, 1, 7, 9, 3, 6]===3
insertSort===: [1, 2, 4, 5, 8, 7, 9, 3, 6]===4
insertSort===: [1, 2, 4, 5, 7, 8, 9, 3, 6]===5
insertSort===: [1, 2, 4, 5, 7, 8, 9, 3, 6]===6
insertSort===: [1, 2, 3, 4, 5, 7, 8, 9, 6]===7
insertSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]===8
推导过程
特性
| 时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|
| O(n^2) | O(1) | 稳定 |
归并排序
定义
分治法的思维,将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。
代码
/**
* 归并排序
* 排序前:[2,5,8,4,1,7,9,3,6]
* 排序后:[1,2,3,4,5,6,7,8,9]
*/
fun mergeSort(numArray: IntArray, left: Int, right: Int): IntArray {
if (left == right) return intArrayOf(numArray[left])
val mid: Int = left + (right - left) / 2
//左有序数组
val leftArr = mergeSort(numArray, left, mid)
//右有序数组
val rightArr = mergeSort(numArray, mid + 1, right)
//新有序数组
val newNum = IntArray(leftArr.size + rightArr.size)
var m = 0
var i = 0
var j = 0
while (i < leftArr.size && j < rightArr.size) {
newNum[m++] = if (leftArr[i] <= rightArr[j]) leftArr[i++] else rightArr[j++]
}
while (i < leftArr.size) newNum[m++] = leftArr[i++]
while (j < rightArr.size) newNum[m++] = rightArr[j++]
Log.e("mergeSort===", newNum.contentToString())
return newNum
}
//运行结果
mergeSort===: [2, 5]
mergeSort===: [2, 5, 8]
mergeSort===: [1, 4]
mergeSort===: [1, 2, 4, 5, 8]
mergeSort===: [7, 9]
mergeSort===: [3, 6]
mergeSort===: [3, 6, 7, 9]
mergeSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]
推导过程
特性
| 时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|
| O(n*log n) | O(n) | 稳定 |
希尔排序
定义
又名缩小增量排序,把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。这里的增量可以理解成步长。
代码
/**
* 希尔排序
* 排序前:[2,5,8,4,1,7,9,3,6]
* 排序后:[1,2,3,4,5,6,7,8,9]
*/
fun shellSort(numArray: IntArray): IntArray {
var gap = numArray.size / 2
while (1 <= gap) {
for (i in gap until numArray.size) {
var j = i - gap
val tmp = numArray[i]
while (j >= 0 && tmp < numArray[j]) {
numArray[j + gap] = numArray[j]
j -= gap
}
numArray[j + gap] = tmp
}
gap /= 2
Log.e("shellSort===", numArray.contentToString() + "===" + gap)
}
return numArray
}
//运行结果
shellSort===: [1, 5, 8, 3, 2, 7, 9, 4, 6]===step:4
shellSort===: [1, 3, 2, 4, 6, 5, 8, 7, 9]===step:2
shellSort===: [1, 2, 3, 4, 5, 6, 7, 8, 9]===step:1
推导过程
特性
| 时间复杂度 | 空间复杂度 | 稳定性 |
|---|---|---|
| O(n*log n) | O(1) | 不稳定 |
项目 github 地址
具体写法在项目的 DifferentSort 文件中