Go 有序数组分段随机排序

Go 对数组进行分阶段随机排序

起源

  1. 有一个值有序的数组
  2. 需要对相同值的区域进行随机排序

解决思路

  1. 随机排序可以考虑洗牌算法
  2. 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)
}

后续

  1. 可以考虑使用go语言自带的rand.Shuffle()方法
  2. 具体思路是
    2.1 确认段的起始位置nStart, nEnd
    2.2 把该位置赋值给一个新的slice,tempArr := arr[nStart:nEnd]
    2.3 调用rand.Shuffle方法处理
    2.4 调试

2022年是比较特殊的一年,口罩、俄乌等,大家加油,努力的活下去。最近接触了点Copilot,能干掉程序猿的也就是程序员😂,加油,做个不能晚点被 替代的人。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值