快速排序不同优化的版本

两种思路

  1. 填坑法
  2. 指针交换法

首先找最左边的值做基准值:p, 然后i指针代表最左边, j指针代表最右边
i指针每次向右移与p值比较,如果i < p则右移,否则停止
j指针每次向左移与p值比较,如果j > p则左移,否则停止
i,j指针都停止后再 i与j的值交换
再进行一次循环.直到i与j重合, 然p值填到i与j重合的位置.
此时的数组,以p为准,p的左边都是小于p的值,p的右边都大于p的值.
然后分别将p左边的数组排序与p右边的数组排序.
以i为基准, i 与 left 未重合则代表,数组left:i之间数组个数大于1.(数组只有一个元素则无需排序啦)

填坑法

//填空法(i,j指针必须j指针先开始)
//首先找最左边的值做基准值:p, 然后i指针代表最左边, j指针代表最右边
//i指针每次向右移与p值比较,如果i < p则右移,否则停止
//j指针每次向左移与p值比较,如果j > p则左移,否则停止
//i,j指针都停止后再 i与j的值交换
//再进行一次循环.直到i与j重合, 然p值填到i与j重合的位置.
//此时的数组,以p为准,p的左边都是小于p的值,p的右边都大于p的值.
//然后分别将p左边的数组排序与p右边的数组排序.
//以i为基准, i 与 left 未重合则代表,数组left:i之间数组个数大于1.(数组只有一个元素则无需排序啦)
func QSortFill(list []int, left, right int) {
	pivot := list[left]
	i, j := left, right
	for i < j {
		for i < j && list[j] > pivot {
			j--
		}
		list[i] = list[j]
		for i < j && list[i] < pivot {
			i++
		}
		list[j] = list[i]
	}
	list[i] = pivot
	if i-left > 1 {
		QSortFill(list, left, i-1)
	}
	if right-i > 1 {
		QSortFill(list, i+1, right)
	}
}
func TestQSortFill(t *testing.T) {
	list := []int{8, 2, 3, 5, 9, 1}
	fmt.Println("unsort:", list)
	QSortFill(list, 0, len(list)-1)
	fmt.Println("sorted:", list)
}

指针交换法

//指针交换法(i,j指针无轮哪个先走都可以)
//先找到一个基准值p, 然后i指针代表最左边, j指针代表最右边
//i指针每次向右移与p值比较,如果i < p则右移,否则停止
//j指针每次向左移与p值比较,如果j > p则左移,否则停止
//i,j指针都停止后再 i与j的值交换
//再进行一次循环.直到i与j重合, 然p值填到i与j重合的位置.
//此时的数组,以p为准,p的左边都是小于p的值,p的右边都大于p的值.
//然后分别将p左边的数组排序与p右边的数组排序.
//以i为基准, i 与 left 未重合则代表,数组left:i之间数组个数大于1.(数组只有一个元素则无需排序啦)
func QSortPoint(list []int, left, right int) {
	pivot := list[left]
	i, j := left, right
	for i < j {
		for i < j && list[j] > pivot {
			j--
		}
		for i < j && list[i] < pivot {
			i++
		}
		if i < j {
			list[i], list[j] = list[j], list[i]
		}
	}
	list[i] = pivot
	if i-left > 1 {
		QSortPoint(list, left, i-1)
	}
	if right-i > 1 {
		QSortPoint(list, i+1, right)
	}
}
func TestQSortPoint(t *testing.T) {
	list := []int{8, 3, 2, 1, 5, 11, 21, 55, 9}
	fmt.Println("QSortPoint排序前:", list)
	QSortPoint(list, 0, len(list)-1)
	fmt.Println("QSortPoint排序后:", list)
}

可以优化的部分

if i-left > 1 {
	QSortPoint(list, left, i-1)
}
if right-i > 1 {
	QSortPoint(list, i+1, right)
}

改成
//函数的第一行必须写上 left >= right 
if left >= right {
	return
}
//todo 
QSortPoint(list, left, i-1)
QSortPoint(list, i+1, right)

改良代码

//QSortPoint的改良版本. 只要left大于等于right就不再递归.方便记忆
func QSortPoint2(list []int, left, right int) {
	if left >= right {
		return
	}
	pivot := list[left]
	i, j := left, right
	for i < j {
		for i < j && list[j] > pivot {
			j--
		}
		for i < j && list[i] < pivot {
			i++
		}
		if i < j {
			list[i], list[j] = list[j], list[i]
		}
	}
	list[i] = pivot
	QSortPoint(list, left, i-1)
	QSortPoint(list, i+1, right)
}
func TestQSortPoint2(t *testing.T) {
	list := []int{8, 3, 2, 1, 5, 9}
	fmt.Println("TestQSortPoint2排序前:", list)
	QSortPoint2(list, 0, len(list)-1)
	fmt.Println("TestQSortPoint2排序后:", list)
}

参考

漫画说快排

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值