You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Go中调用QuickSort会修改原切片?递归相关疑问

为什么Go语言中我的快速排序会修改原切片?

这完全是Go语言切片的预期行为,不是你的代码有问题——核心原因在于切片是引用类型,和你理解的“只有传递指针才会修改原数据”的认知有偏差,咱们一步步拆解:

切片的本质:带元数据的指针

Go语言里的切片并不是直接存储数据的容器,它其实是一个包含三个字段的轻量级结构体:

  • 指向底层数组的指针
  • 切片当前的长度(len)
  • 切片的容量(cap)

当你把切片作为参数传递给函数时,Go会拷贝这个结构体,但结构体里的指针还是指向原来的底层数组。这意味着:函数里对切片元素的任何修改,都会直接作用在原底层数组上,自然会影响到外部的原切片。

你的两个困惑点解析

1. 为什么原变量toSort被修改了?

你调用sorting.QuickSort(toSort)时,传递的是切片结构体的副本,但这个副本里的指针和toSort指向同一个底层数组。你的QuickSort函数里直接交换了sorted切片的元素(也就是修改底层数组的内容),所以原toSort自然会看到这些修改——因为它们共享同一个数据源。

2. 为什么递归子切片操作会直接更新原sorted切片?

当你执行sorted[:curLowIndx]或sorted[curLowIndx+1:]这种子切片操作时,生成的新切片依然指向原来的底层数组,只是调整了切片的长度和范围。递归调用QuickSort处理这些子切片时,修改的还是同一个底层数组的元素,所以这些变化会直接反映到原sorted切片上。这也是你不需要合并返回子切片的原因——所有排序操作都是在同一个底层数组上完成的。

如何避免修改原切片?

如果你希望排序后不影响原切片,可以在QuickSort函数开头先创建原切片的副本,后续操作都基于这个副本:

func QuickSort(input []int) []int {
    if len(input) <= 1 {
        return input
    }
    // 创建原切片的副本,使用新的底层数组
    sorted := make([]int, len(input))
    copy(sorted, input)
    // 后续逻辑不变...
    pivotIndx := len(sorted) - 1
    pivot := sorted[pivotIndx]
    curLowIndx := 0
    for indx, val := range sorted {
        if val < pivot {
            sorted[indx], sorted[curLowIndx] = sorted[curLowIndx], sorted[indx]
            curLowIndx++
        }
    }
    sorted[curLowIndx], sorted[pivotIndx] = sorted[pivotIndx], sorted[curLowIndx]
    QuickSort(sorted[:curLowIndx])
    QuickSort(sorted[curLowIndx+1:])
    return sorted
}

这样修改后,原toSort就不会被改变了。

内容的提问来源于stack exchange,提问作者user6547408

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 18:22:33