经过之前的学习,Go语言中的数据结构除了集合 Map和 字符串 之外,都已经深入学习了,接下来,进入我们的算法部分。
一、为什么需要排序
当我们拥有很多数据的同时,我想要查找数据群中某一个指定的数据,如果我们直接查找,因为数据是乱序的,所以效率会很慢很慢。
如果我们把这些大数据群,排好序之后,再使用时间复杂度低的查找算法,就能快速又精准的找到所需数据。因此我们需要排序来为查找打下坚实的基础。
二、什么是选择排序
首先,大部分情况下,我们会把数据群,例如数组,分为有序部分和无序部分,那么排序排的就是无序的部分。
其次,选择排序,就是从数据群中选择(说是选择,其实本质还是比较)出一个最大或最小(下面默认是最小的,因为我喜欢)的数据,放在数据群的第一位,然后这个第一位就变成了有序部分,因为它是最小的。
接着,我们再比较其他无序部分,在这些无序部分再比较出最小的,放在无序部分的第一位。
周而复始,直到无序部分只剩下一个数据的时候,那么该数据则一定是最大的。
三、代码实现
在看了上面的内容后,我们可以发现有这么几点是需要我们实现的:
- 在获取第一个最小值后,我们如何标识它是有序 / 无序的,然后从下一个无序部分开始重新比较
- 是否有一些特殊情况需要我们判断,例如传入的内容是否为空,等等
话不多说,看看代码:
package sort
import (
"log"
"testing"
)
func TestSelectionSort(t *testing.T) {
arr := []int{7, 2, 4, 1, 1, 5, -1}
log.Println(arr)
selectionSort(arr)
log.Println(arr)
}
// selectionSort
// 把整个数组都看作是无序状态,然后从数组中选择一个最小的
// 和i交换位置,交换了位置后,0 —— i 则视为有序部分
func selectionSort(arr []int) {
if arr == nil || len(arr) < 2 {
return
}
n := len(arr)
for i := 0; i < n-1; i++ {
minIndex := i
for j := i + 1; j < n; j++ {
if arr[j] < arr[minIndex] {
minIndex = j
}
}
// 已经拿出最小的存储在minIndex
swap(arr, i, minIndex)
}
}
// swap 交换位置
func swap(arr []int, i, minIndex int) {
arr[i], arr[minIndex] = arr[minIndex], arr[i]
}
可以看到,我们用 minIndex 作为标识,而 i 的总数 控制着我们的循环次数,当我们不断选择之后,i 会逐步 +1 ,导致 minIndex 会不断向后移动,这就分割开了我们有序部分和无序部分。
minIndex 一开始是 i ,当我们找到比他那个位置的数字还小的数字时,就会让 minIndex = 该比他还小的数字的位置,直到对比完一轮,此时 minIndex 一定是 整个数组中最小的数字的位置 。
然后我们执行交换,这样数组的第一位就是整个数组中最小的数字了。