Python常见的排序算法及其特点和实现代码
本文介绍了Python中常见的排序算法及其实现,包括冒泡排序(稳定,O(n²))、选择排序(不稳定,O(n²))、插入排序(稳定,O(n²)最好O(n))、希尔排序(不稳定,O(nlogn))、归并排序(稳定,O(nlogn))、快速排序(不稳定,平均O(nlogn))、堆排序(不稳定,O(nlogn))、计数排序(稳定,O(n+k))、桶排序(稳定,O(n+k))和基数排序(稳定,O(nk))。每种算法都给出了核心原理、时间复杂度和Python实现代码,并指出适用场景,如快速排序适合大数据量,计数排序适合范围固定的整数。
冒泡排序
- 原理:重复比较相邻元素,将较大的元素逐渐“冒泡”到数组末尾。
- 时间复杂度:平均和最坏情况均为O(n2)O(n2),稳定。
- 代码示例:
def bubblesort(arr):for i in range(1, len(arr)):for j in range(0, len(arr)-i):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]return arr
选择排序
- 原理:每次从未排序部分选择最小元素,与未排序部分的第一个元素交换。
- 时间复杂度:O(n2)O(n2),不稳定。
- 代码示例:
def selectionsort(arr):for i in range(len(arr)-1):minindex = ifor j in range(i+1, len(arr)):if arr[j] < arr[minindex]:minindex = jif i != minindex:arr[i], arr[minindex] = arr[minindex], arr[i]return arr
插入排序
- 原理:将元素逐个插入到已排序序列的合适位置。
- 时间复杂度:平均O(n2)O(n2),最好情况O(n)O(n),稳定。
- 代码示例:
def insertionsort(arr):for i in range(len(arr)):preindex = i-1current = arr[i]while preindex >= 0 and arr[preindex] > current:arr[preindex+1] = arr[preindex]preindex -= 1arr[preindex+1] = currentreturn arr
希尔排序
- 原理:基于插入排序的改进,通过分组插入减少数据移动次数。
- 时间复杂度:平均O(nlogn)O(nlogn),不稳定。
- 代码示例:
def shellsort(arr):import mathgap = 1while gap < len(arr)/3:gap = gap*3 + 1while gap > 0:for i in range(gap, len(arr)):temp = arr[i]j = i - gapwhile j >= 0 and arr[j] > temp:arr[j+gap] = arr[j]j -= gaparr[j+gap] = tempgap = math.floor(gap/3)return arr
归并排序
- 原理:采用分治法,将数组分成两半,分别排序后再合并。
- 时间复杂度:O(nlogn)O(nlogn),稳定。
- 代码示例:
def mergesort(arr):import mathif len(arr) < 2:return arrmiddle = math.floor(len(arr)/2)left, right = arr[0:middle], arr[middle:]return merge(mergesort(left), mergesort(right))def merge(left, right):result = []while left and right:if left[0] <= right[0]:result.append(left.pop(0))else:result.append(right.pop(0))while left:result.append(left.pop(0))while right:result.append(right.pop(0))return result
快速排序
- 原理:选择一个基准元素,将数组分为小于和大于基准的两部分,递归排序。
- 时间复杂度:平均O(nlogn)O(nlogn),最坏O(n2)O(n2),不稳定。
- 代码示例:
def quicksort(arr, left=None, right=None):left = 0 if not isinstance(left, (int, float)) else leftright = len(arr)-1 if not isinstance(right, (int, float)) else rightif left < right:partitionindex = partition(arr, left, right)quicksort(arr, left, partitionindex-1)quicksort(arr, partitionindex+1, right)return arrdef partition(arr, left, right):pivot = leftindex = pivot + 1i = indexwhile i <= right:if arr[i] < arr[pivot]:swap(arr, i, index)index += 1i += 1swap(arr, pivot, index-1)return index-1def swap(arr, i, j):arr[i], arr[j] = arr[j], arr[i]
堆排序
- 原理:利用堆结构,每次取出堆顶元素构建有序序列。
- 时间复杂度:O(nlogn)O(nlogn),不稳定。
- 代码示例:
def heapsort(arr):global arrlenarrlen = len(arr)buildmaxheap(arr)for i in range(len(arr)-1, 0, -1):swap(arr, 0, i)arrlen -= 1heapify(arr, 0)return arrdef buildmaxheap(arr):import mathfor i in range(math.floor(len(arr)/2), -1, -1):heapify(arr, i)def heapify(arr, i):left = 2*i + 1right = 2*i + 2largest = iif left < arrlen and arr[left] > arr[largest]:largest = leftif right < arrlen and arr[right] > arr[largest]:largest = rightif largest != i:swap(arr, i, largest)heapify(arr, largest)
计数排序
- 原理:统计元素出现次数,按顺序填充到结果数组。
- 时间复杂度:O(n+k)O(n+k),稳定。
- 代码示例:
def countingsort(arr, maxvalue):bucketlen = maxvalue + 1bucket = [0] * bucketlensortedindex = 0arrlen = len(arr)for i in range(arrlen):if not bucket[arr[i]]:bucket[arr[i]] = 0bucket[arr[i]] += 1for j in range(bucketlen):while bucket[j] > 0:arr[sortedindex] = jsortedindex += 1bucket[j] -= 1return arr
桶排序
- 原理:将数据分到不同桶中,对每个桶排序后合并。
- 时间复杂度:O(n+k)O(n+k),稳定。
- 代码示例:
def bucket_sort(s):min_num = min(s)max_num = max(s)bucket_range = (max_num - min_num) / len(s)count_list = [[] for _ in range(len(s)+1)]for i in s:count_list[int((i - min_num) // bucket_range)].append(i)s.clear()for i in count_list:for j in sorted(i):s.append(j)
基数排序
- 原理:按数字位数从低位到高位依次排序。
- 时间复杂度:O(nk)O(nk),稳定。
- 代码示例:
def radixsort(list):i = 0n = 1max_num = max(list)while max_num > 10**n:n += 1while i < n:bucket = {}for x in range(10):bucket.setdefault(x, [])for x in list:radix = int((x / (10**i)) % 10)bucket[radix].append(x)j = 0for k in range(10):if len(bucket[k]) != 0:for y in bucket[k]:list[j] = yj += 1i += 1return list
以上算法可根据数据特点和需求选择,如快速排序适合大数据量,计数排序适合范围固定的整数。