python的十大算法_Python实现十大排序算法

本文中实现的排序算法均按照从小到大的顺序,待排序的数取一般整数。

选择排序

从前到后逐渐有序,每次遍历都会把无序部分的最小值往前“提”

def select(nums: List[int]) -> List[int]:

n = len(nums)

for i in range(n - 1):

k = i

for j in range(i + 1, n):

if nums[j] < nums[k]:

k = j

if k > i:

nums[i], nums[k] = nums[k], nums[i]

return nums

复制代码

冒泡排序

从后到前逐渐有序,每次遍历都会把无序部分的最大值向后“顶”。

def bubble(nums: List[int]) -> List[int]:

n = len(nums)

for i in range(n - 1):

for j in range(1, n - i):

if nums[j] < nums[j - 1]:

nums[j], nums[j - 1] = nums[j - 1], nums[j]

return nums

复制代码

插入排序

从前到后逐渐有序,将每次遍历到的值"插"入前方的有序部分。

def insert(nums: List[int]) -> List[int]:

for i in range(1, len(nums)):

for j in reversed(range(i)):

if nums[j] > nums[j + 1]:

nums[j], nums[j + 1] = nums[j + 1], nums[j]

return nums

复制代码

归并排序

自顶向下递归,自底向上有序。两两比较,组组归并。

def merge(nums: List[int]) -> List[int]:

def _merge(nums1: List[int], nums2: List[int]):

i, j, res = 0, 0, []

while i < len(nums1) and j < len(nums2):

if nums1[i] < nums2[j]:

res.append(nums1[i])

i += 1

else:

res.append(nums2[j])

j += 1

while i < len(nums1):

res.append(nums1[i])

i += 1

while j < len(nums2):

res.append(nums2[j])

j += 1

return res

if len(nums) <= 1:

return nums

mid = (len(nums) - 1) // 2

return _merge(merge(nums[:mid + 1]), merge(nums[mid + 1:]))

复制代码

希尔排序

跳跃分组结合插入排序,通过逐渐降低数组的无序性提高插入排序的效率。

def shell(nums: List[int]) -> List[int]:

def _sort(array: List[int], index: int, step: int, size: int):

current = index + step

while current < size:

if array[current] < array[current - step]:

front = current - step

while front >= 0 and array[front] > array[front + step]:

array[front], array[front + step] = array[front + step], array[front]

front -= step

current += step

n, k = len(nums), len(nums) // 2

while k > 0:

for i in range(k):

_sort(nums, i, k, n)

k //= 2

return nums

复制代码

快速排序

选取基准左数第一,左小右大移动边界。

小则移动大则交换,基准居中左右递归。

def quick(nums: List[int]) -> List[int]:

def _quick(array: List[int], start: int, close: int):

if start >= close:

return

bound = start + 1

for index in range(bound, close + 1):

if array[index] < array[start]:

array[index], array[bound] = array[bound], array[index]

bound += 1

base = bound - 1

array[start], array[base] = array[base], array[start]

_quick(array, start, base - 1)

_quick(array, base + 1, close)

_quick(nums, 0, len(nums) - 1)

return nums

复制代码

堆排序

形如第K大的数之类的问题,快排优于堆排。

形如前K大的数之类的问题,选择堆排更佳。

如果K不大于3,上述问题不过O(N)复杂度。

def heap(nums: List[int]) -> List[int]:

def heapify(array: List[int], index: int, size: int):

i_max = index

il, ir = 2 * index + 1, 2 * index + 2

if il < size and array[il] > array[i_max]:

i_max = il

if ir < size and array[ir] > array[i_max]:

i_max = ir

if index != i_max:

array[index], array[i_max] = array[i_max], array[index]

heapify(array, i_max, size)

n = len(nums)

for i in reversed(range(n // 2)):

heapify(nums, i, n)

for k in reversed(range(1, n)):

nums[0], nums[k] = nums[k], nums[0]

heapify(nums, 0, k)

return nums

复制代码

桶排序

有序的桶保证了重建后的数组是有序的数组,每次向桶中插入一个值需要保证桶中的数有序。

def bucket(nums: List[int]) -> List[int]:

# 以下实现只适用于0~99范围的整数

buckets = [list() for _ in range(10)]

for num in nums:

_bucket = buckets[num // 10]

_bucket.append(num)

n = len(_bucket)

for i in reversed(range(1, n)):

if _bucket[i] < _bucket[i - 1]:

_bucket[i], _bucket[i - 1] = _bucket[i - 1], _bucket[i]

res = []

for _bucket in buckets:

res.extend(_bucket)

return res

复制代码

计数排序

计数排序是一个统计和重现的过程,适用于待排序数取值范围非常有限的场景,例如十分制比赛中选手的排名。

def count(nums: List[int]) -> List[int]:

counter = [0 for _ in range(10)]

for num in nums:

counter[num] += 1

res = []

for num, _count in enumerate(counter):

for _ in range(_count):

res.append(num)

return res

复制代码

基数排序

将所有数先按个位排序,再按十位排序,再按百位排序......每次排序都是一次桶的分发和收集。

def radix(nums: List[int], figure: int) -> List[int]:

# figure表示待排序数的最大位数

# 如[1, 10, 100], figure取3

buckets = [list() for _ in range(10)]

dev, mod = 1, 10

for i in range(figure):

for x in nums:

k = (x % mod) // dev

buckets[k].append(x)

nums.clear()

for bucket in buckets:

for x in bucket:

nums.append(x)

bucket.clear()

dev *= 10

mod *= 10

return nums

复制代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值