Go 对数组进行分阶段随机排序
起源
- 有一个值有序的数组
- 需要对相同值的区域进行随机排序
解决思路
- 随机排序可以考虑洗牌算法
- go自带的rand.Perm()方法,可以返回一个乱序的唯一数的int数组
代码
主要文件:arrrandom.go
package arrrange
type Value struct {
Index int
Value int
}
// MessSortArr 把有序的数组,按照关键数值分段进行打乱处理
func MessSortArr(arr []*Value) {
// 如果数组长度小于等于1,则不需要进行打乱处理
if len(arr) <= 1 {
return
}
// 最终的顺序
finalIndex := make([]int, len(arr))
// **这一步很重要**
// 如果没有排序的地方,则按照之前的排序处理
for i := 0; i < len(finalIndex); i++ {
finalIndex[i] = i
}
nStartIndex := 0 // 分段的起始位置
bChangeIndex := false // 是否变更了排序标识
bNeedMess := false // 是否需要打乱处理
// 设置随机数种子
rand.Seed(time.Now().UnixNano())
// 依次处理每一个段
for i := 1; i < len(arr); i++ {
if arr[i].Value != arr[i-1].Value {
bNeedMess = true
} else if i == len(arr)-1 {
// **注意这个地方,用来处理最后一段信息**
// **如果最后一段只有一个数据,则上面就会退出,否则就会进入这里处理**
bNeedMess = true
i++
}
// 判断是否需要打乱处理
if bNeedMess {
// 更新打乱标识
bNeedMess = false
// 判断段的长度是否大于1,如果大于1,则需要打乱处理
if i-nStartIndex > 1 {
// 记录变更了排序标识
bChangeIndex = true
// 获取对应的乱序数组
arrMessIndex := rand.Perm(i - nStartIndex)
// 更新该段的顺序
for ii := 0; ii < len(arrMessIndex); ii++ {
finalIndex[nStartIndex+ii] = arrMessIndex[ii] + nStartIndex
}
}
// 更新段起始位置
nStartIndex = i
}
}
// 如果变更了排序标识,则需要更新数组信息
if bChangeIndex {
// 创建新的数组,记录最终顺序信息
newArr := make([]*Value, len(arr))
for i := 0; i < len(finalIndex); i++ {
newArr[i] = arr[finalIndex[i]]
}
// 修改原始数组信息
copy(arr, newArr)
}
}
测试用例
package arrrange
func TestArrRange(t *testing.T) {
// arr := []int{1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5}
arr := make([]*Value, 0)
nIndex := 0
for i := 0; i < 1; i++ {
v1 := Value{i + nIndex, 1}
arr = append(arr, &v1)
}
nIndex += 1
for i := 0; i < 2; i++ {
v2 := Value{i + nIndex, 2}
arr = append(arr, &v2)
}
nIndex += 2
for i := 0; i < 3; i++ {
v3 := Value{i + nIndex, 3}
arr = append(arr, &v3)
}
nIndex += 3
for i := 0; i < 4; i++ {
v4 := Value{i + nIndex, 4}
arr = append(arr, &v4)
}
nIndex += 4
for i := 0; i < 2; i++ {
v5 := Value{i + nIndex, 5}
arr = append(arr, &v5)
}
nIndex += 2
MessSortArr(arr)
t.Log(arr)
}
后续
- 可以考虑使用go语言自带的rand.Shuffle()方法
- 具体思路是
2.1 确认段的起始位置nStart, nEnd
2.2 把该位置赋值给一个新的slice,tempArr := arr[nStart:nEnd]
2.3 调用rand.Shuffle方法处理
2.4 调试
2022年是比较特殊的一年,口罩、俄乌等,大家加油,努力的活下去。最近接触了点Copilot,能干掉程序猿的也就是程序员😂,加油,做个不能晚点被 替代的人。