快排

首先你需要知道,**原地算法 (in-place)**的定义:就是特指空间复杂度为 O(1) 的算法;即在算法运行时,输入数据会被输出覆盖。

你还要知道,分而治之 (divide and conquer),基于多项分支递归的算法范式。首先你需要确定何时函数将不再调用自己,再缩小问题规模使其符合前一步。

当数组中只有唯一或为空元素时,那它就是有序的,这就是函数停止调用自己的条件。

而其它的调用中,你都必须对数组进行切分,这才能满足上述条件。

func separateSort(a []int, start, end int) {
	if start >= end {
		return
	}
	pivot := partition(a, start, end)
	// fmt.Println("the pivot is:", a[pivot])
	separateSort(a, start, pivot-1)
	separateSort(a, pivot+1, end)
}

根据要求你得到了第一个函数,接受一个数组以及它的起始下标,当数组元素唯一时返回。

pivot 基准,或可称为分区点,由 partition 函数的返回值赋值;此时将数组 a 已分为三部分,分区点左右继续递归调用。

partition 函数首先对接受到的数组假设,设其末端为分区点;再将小于分区点的元素换到右边,大于分区点的元素换到右边;最后返回结果分区点。

func partition(a []int, start, end int) int {
	left, right := start, end
	pivot := end
	for left < right {
		if a[left] > a[pivot] {
			if a[right] < a[pivot] {
				a[left], a[right] = a[right], a[left]
			} else {
				right--
			}
		} else {
			left++
		}
	}
	if a[left] != a[pivot] {
		a[left], a[pivot] = a[pivot], a[left]
	}
	// fmt.Printf("array order is: %d --> ", a)
	return left
}

最后就是调用了,

func qsort(a []int) {
	separateSort(a, 0, len(a)-1)
}

func main() {
	a := []int{6, 2, 5, 9, 3, 7, 0, 1, 3, 4, 8}
	fmt.Println("Original: ", a)
	qsort(a)
	fmt.Println("Complete! ", a)
}

靠着代码的输出,你可以看看 pviot 的选择过程:

Original:  [6 2 5 9 3 7 0 1 3 4 8]
array order is: [6 2 5 4 3 7 0 1 3 8 9] --> the pivot is: 8
array order is: [1 2 0 3 3 7 5 6 4 8 9] --> the pivot is: 3
array order is: [0 2 1 3 3 7 5 6 4 8 9] --> the pivot is: 0
array order is: [0 1 2 3 3 7 5 6 4 8 9] --> the pivot is: 1
array order is: [0 1 2 3 3 4 5 6 7 8 9] --> the pivot is: 4
array order is: [0 1 2 3 3 4 5 6 7 8 9] --> the pivot is: 7
array order is: [0 1 2 3 3 4 5 6 7 8 9] --> the pivot is: 6
Complete!  [0 1 2 3 3 4 5 6 7 8 9]

具体代码执行过程,如下手绘图所示:
在这里插入图片描述
在图中依照时间顺序,从上至下可依次寻找相应的 pivot 值。你只需要着眼于一次能够正确完成,那么你只需要在正确地传递数组相应的边界条件即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值