【译文】快速排序

快速排序

难易程度 : 中等

类似归并排序,快速排序是一种分治算法。快速排序挑选一个元素作为基数,然后围绕选定的基数分割给定的数组。快速排序有很多版本,这些版本以不同的方式挑选基数。

  1. 总是挑选第一个元素作为基数
  2. 总是挑选最后一个元素作为基数(下面有实现的案例)
  3. 挑选任意元素作为基数
  4. 挑选中位数作为基数

快速排序的关键步骤是分区。分区的目标是给定数组和基数x,把x放到有序数组中正确的位置,然后把所有比x小的数放到x前面,再把所有比x大的数放在x之后。所有这些操作完成的时间应该是线性的。

快速排序递归函数伪代码

/* --> Starting index, high --> Ending index */
quickSort(arr[], low, high)
{
	if (low < high)
	{
		/* pi is partitioning index, arr[pi] is now at right place */
		pi = partition(arr, low, high);
		
		quickSort(arr, low, pi - 1); // Before pi
		quickSort(arr, high, pi + 1); // After pi
	}
}

在这里插入图片描述

分区算法

有很多种方法实现分区,下面的伪代码采用算法导论中的方法。逻辑很简单,从数组最左侧元素开始,记录小于等于基数的元素索引为i。遍历数组,如果发现更小的元素,则将当前元素与arr[i]交换位置。如否则忽略当前元素。

/* low --> Starting index, high --> Ending index */
quickSort(arr[], low, high)
{
	if (low < high)
	{
		/* pi is partitioning index, arr[pi] is now at right palce */
		pi = partition(arr, low, high);

		quickSort(arr, low, pi - 1);   // Before pi
		quickSort(arr, high, pi + 1);  // After pi	
	}
}

分区伪代码

/* This function takes last element as pivot, places 
   the pivot element at its correct position in sorted
    array, and places all smaller (smaller than pivot)
    to left of pivot and all greater elements to right 
    of pivot */
partition (arr[], low, high)
{
	// pivot (Element to be places at right position)
	pivot = arr[high];

	i = (low - 1)  // Index of smaller element and indicates the
				   // right position of pivot found so far
	
	for (j = low; j <= high - 1; j++)
	{
		// If current element is smaller than the pivot
		if (arr[j] < pivot)
		{
			i++;    // increment index of smaller element
			swap arr[i] and arr[j]
		}
	}
	swap (arr[i + 1] and arr[high])
	return (i + 1)
}

分区函数说明

arr[] = {10, 80, 30, 90, 40, 50, 70}
Indexes:  0   1   2   3   4   5   6

low = 0, high = 6, pivot = arr[h] = 70
Initialize index of smaller element, i = -1

Traverse elements from j = low to high-1
j = 0: Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j])
i = 0
arr[] = {10, 80, 30, 90, 40, 50, 70} // No change as i and j
                                     // are same

j = 1: Since arr[j] > pivot, do nothing
// No change in i and arr[]

j = 2: Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j])
i = 1
arr[] = {10, 30, 80, 90, 40, 50, 70} // We swap 80 and 30

j = 3: Since arr[j] > pivot, do nothing
// No change in i and arr[]

j = 4: Since arr[j] <= pivot, do i++ and swap(arr[i], arr[j])
i = 2
arr[] = {10, 30, 40, 90, 80, 50, 70} // 80 and 40 Swapped
j = 5: Since arr[i] <= pivot, do i++ and swap arr[i] with arr[j]
i = 3
arr[] = {10, 30, 40, 50, 80, 90, 70} // 90 and 50 Swapped

We come out of loop because j is now equal to high-1.
Finally we place pivot at correct position by swapping
arr[i+1] and arr[high] (or pivot)
arr[] = {10, 30, 40. 50, 70, 90, 80} // 80 and 70 Swapped

Now 70 is at its correct place. All elements smaller than 
70 are before it and all elements greater than 70 are after
it.

推荐:在理解改解决方案之前,先尝试练习一下

代码实现

# Python3 implementation of QuickSort

# This Function handles sorting part of quick sort
# start and end points to first and last element of
# an array respectively
def partion(start, end, array):
	
	# Initializing pivot's index to start
	pivot_index = start
	pivot = array[pivot_index]
	
	# This loop runs till start pointer crosses
	# end pointer, and when it does we swap the 
	# pivot with element on end pointer
	while start < end:
		
		# Increment the start pointer till it finds an
		# element greater than pivot
		while start < len(array) and array[start] <= pivot:
			start += 1
		
		# Decrement the end pointer till it finds an 
		# element less than pivot
		while array[end] > pivot:
			end -= 1

		# If start and end have not crossed each other,
		# swap the numbers on start and end
		if(start < end):
			array[start], array[end] = array[end], array[start]
		
	# Swap pivot element with element on end pointer.
	# This puts pivot on its correct sorted place.
	array[end], array[pivot_index] = array[pivot_index], array[end]
	
	# Returning end pointer to divide the array into 2
	return end

# The main function that implements QuickSort
def quick_sort(start, end, array):
	
	if (start < end):
		
		# p is partitioning index, array[p]
		# is at right place
		p = partition(start, end, array)

		# Sort elements before partion
		# and after partition
		quick_sort(start, p - 1, array)
		quick_sort(p + 1, end, array)

# Driver code
array = [10, 7, 8, 9, 1, 5]
quick_sort(0, len(array) - 1, array)

print(f'Sorted array: {array}')

# This code is contributed by Adnan Aliakbar

输出结果

Sorted array:
1 5 7 8 9 10

简洁版代码

#User function Template for python3

class Solution:
    #Function to sort a list using quick sort algorithm.
    def quickSort(self,arr,low,high):
        # code here
        if (low < high):
            p = self.partition(arr, low, high)
            self.quickSort(arr, low, p-1)
            self.quickSort(arr, p+1, high)
    
    def partition(self,arr,low,high):
        # code here
        pivot_index = low
        pivot = arr[pivot_index]
        while low < high:
            while low < len(arr) and arr[low] <= pivot:
                low += 1
        
            while arr[high] > pivot:
                high -= 1
            
            if (low < high):
                arr[low], arr[high] = arr[high], arr[low]
        
        arr[high], arr[pivot_index] = arr[pivot_index], arr[high]
        
        return high
        
        
    

#{ 
#  Driver Code Starts
#Initial Template for Python 3

# if __name__ == "__main__":
#     t=int(input())  # provide array length
#     for i in range(t):
#         n=int(input())  # provide sort length, less or equal than array length
#         arr=list(map(int,input().split()))  # provide array, seprated with space
#         Solution().quickSort(arr,0,n-1)
#         for i in range(n):
#             print(arr[i],end=" ")
#         print()

# simple version
if __name__ == '__main__':
    arr = [4, 1, 3, 9, 7]
    n = 5
    Solution().quickSort(arr, 0, n-1)
    print(arr)

# } Driver Code Ends

快速排序分析

快速排序时间复杂度一般来说可以记作如下:

T(n) = T(k) + T(n-k-1) + θ(n)
前两项是两个递归调用,最后一个是分区过程。k是比基数小的所有元素。
快速排序时间复杂度取决于输入数据和分区策略。

参考

https://www.geeksforgeeks.org/quick-sort/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值