数据结构 - 快速排序

快速排序算法

快速排序是一种基于划分和迭代的排序算法。

主要原理:在每一次迭代时,都把向量分城左,中,右(left, mid, right)三部分,其中左边部分全部都小于中间值,而右边部分全部大于等于中间值。这样,将整个向量分解成一个类似二叉树的结构,从而达到排序的目的。


而这种方法减小计算量的关键技术是,在选定mid指针所指的值之后,要用最快的方法将小于mid值和大于mid值的数分开。

基本思路:在当前循环下,将mid值与向量队尾/队头的值进行交换。将left中左起第一个大于mid的数字,与right中右起第一个小于mid的数字进行互换。当一遍遍历完成之后,left和right会和,而所指数值正好是第一个大于/小于mid值的数字。然后,将放置于队尾/队头的mid元素与之进行互换,就完成了第一次迭代。然后将left子列调用原函数,再将right子列调用原函数.


快速排序的效率:

空间复杂度:快速排序是递归算法,每一层的调用数据用栈来存放,所以递归调用层数与二叉树高度类似。理想情况下,递归生成一个满二叉树,设数列长度为n,设二叉树高度为h,则有

n / (2 ^ h) = 1.     即有 h = log2(n)      即空间复杂度最小为O(log2(n))

最坏情况下,二叉树为单链,则栈长度为n,空间复杂度为O(n)


时间复杂度:设T(n)为对长度为n的待排序列进行排序的时间。则理想情况下,每次划分都生成两个等长子列。即有:

T(n) <= c * n + 2 * T(n / 2)   其中c * n为每次划分所需的n次比较的时间。 T(n / 2)为对子列排序所需时间。继续推导:

T(n) <= c * n + 2 * T(n / 2)

       <= 2 * c * n + 2 * (c * n / 2 + 2* T(n / 4)) = 2 * c * n + 4 * T(n / 4)    ......  递归次数即二叉树高度h

       <= log2(n) * c * n + n(T(1) = O(n*log2(n))

所以非理想情况下 h 不是 log2(n) 而是 n, 即时间复杂度为 O(n^2)


class Solution:
	def quick_sort(self, nums):
		lens = len(nums)
		if lens <= 1:
			return(nums)
			
		mid = lens // 2
		nums[-1], nums[mid] = nums[mid], nums[-1]
		mid = -1
		right = lens - 1
		left = 0
		print(left, mid)
		while right > left:
			while nums[left] <= nums[mid] and right > left:
				left = left + 1
			
			while nums[right] > nums[mid] and right > left:
				right = right - 1
				
			nums[right], nums[left] = nums[left], nums[right] 
			
		
		nums[right], nums[mid] = nums[mid], nums[right]
		mid = right
		
		#print(nums)
		
		nums[:mid] = self.quick_sort(nums[:mid])
		nums[mid + 1:] = self.quick_sort(nums[mid + 1:])
		
		print(nums)
		return(nums)
		
		
if __name__ == "__main__":
	sol = Solution()
	res = sol.quick_sort([9,7,5,3,2,7,5,4,23,9,56,67,23,11])
	
		

优化:

1.上述算法中,mid = len // 2 一步可以省略,因为支点只是要放到队首或队尾等待比较的点,与其在数列中的初始位置并无关系,所以可以找任意一个点作为支点。

基于这点,算法可改如下:

def quick_sort2(self, nums):
		lens = len(nums)
		if lens <= 1:
			return(nums)
		
		mid = -1
		right = lens - 1
		left = 0
		while right > left:
			while nums[left] <= nums[mid] and right > left:
				left = left + 1
				
			while nums[right] > nums[mid] and right > left:
				right = right - 1
				
			nums[right], nums[left] = nums[left], nums[right]
			
		nums[right], nums[mid] = nums[mid], nums[right]
		mid = right
		
		nums[:mid] = self.quick_sort(nums[:mid])
		nums[mid + 1:] = self.quick_sort(nums[mid + 1:])
		
		print(nums)
		return(nums)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值