1. 排序算法的重要性
排序算法是指将一组无序数据按照一定的规则进行排列的过程,对于程序员来说,排列数据使得程序运行的更快,增加程序的执行效率,提高程序的质量,是非常重要的。因此,掌握排序算法是程序员必不可少的技能之一。
2. 排序的分类
2.1 按照数据结构划分
排序算法可以根据不同的数据结构进行分类,主要包括:
数组排序:对于一维、二维或多维数组进行排序。
链表排序:对于链表结构中的节点进行排序。
树形结构排序:对于二叉树、AVL树、堆排序树、B树、红黑树进行排序。
2.2 按照排序方式划分
排序算法还可以按照排序的方式进行分类,包括:
比较排序:通过比较关键字大小来进行排序,包括插入排序、希尔排序、归并排序、快速排序、堆排序、冒泡排序、选择排序等。
非比较排序:不通过比较关键字大小来进行排序,包括桶排序、计数排序、基数排序等。
3. 十大排序算法
下面介绍程序员必须掌握的十大排序算法:
3.1 冒泡排序
冒泡排序是一种简单的排序算法,它的原理是通过不断交换相邻元素的位置,将大的元素逐渐的往后移。
def bubble_sort(nums):
n = len(nums)
for i in range(n):
for j in range(n-i-1):
if nums[j] > nums[j+1]:
nums[j], nums[j+1] = nums[j+1], nums[j]
return nums
冒泡排序的时间复杂度是O(n2)。
3.2 选择排序
选择排序是一种简单的排序算法,它的原理是指定一个最小值,从数组中查找最小值并将其交换到数组的最前面。
def selection_sort(nums):
n = len(nums)
for i in range(n):
min_index = i
for j in range(i, n):
if nums[j] < nums[min_index]:
min_index = j
nums[i], nums[min_index] = nums[min_index], nums[i]
return nums
选择排序的时间复杂度是O(n2)。
3.3 插入排序
插入排序是一种简单的排序算法,它的原理是从数组的第二个元素开始,将当前元素插入到已排序好的数组中,保持已排序数组的有序性。
def insertion_sort(nums):
n = len(nums)
for i in range(1, n):
key = nums[i]
j = i - 1
while j >= 0 and nums[j] > key:
nums[j+1] = nums[j]
j -= 1
nums[j+1] = key
return nums
插入排序的时间复杂度是O(n2)。
3.4 希尔排序
希尔排序是一种基于插入排序的快速、高效的排序算法,它的原理是将数组进行分组,然后对每组中的元素进行插入排序。
def shell_sort(nums):
n = len(nums)
gap = n // 2
while gap > 0:
for i in range(gap, n):
temp = nums[i]
j = i
while j >= gap and nums[j-gap] > temp:
nums[j] = nums[j-gap]
j -= gap
nums[j] = temp
gap = gap // 2
return nums
希尔排序的时间复杂度的比较复杂,最好情况下是O(n),最坏情况下是O(n2)。
3.5 快速排序
快速排序是一种基于分治思想的排序算法,它的原理是指定一个基准元素,通过分区的方式,将数组分为两个子数组,然后分别对左右两边的子数组进行递归排序。
def quick_sort(nums):
if len(nums) <= 1:
return nums
pivot = nums[len(nums)//2] #选择基准值
left, right, mid = [], [], []
for num in nums:
if num < pivot:
left.append(num)
elif num > pivot:
right.append(num)
else:
mid.append(num)
return quick_sort(left) + mid + quick_sort(right)
快速排序的时间复杂度最好情况下是O(nlogn),最坏情况下是O(n2)。
3.6 归并排序
归并排序是一种基于分治思想的排序算法,它的原理是将数组分为两个子数组,然后递归地对两个子数组进行排序,并最终将两个排序好的子数组合并成一个有序数组。
def merge_sort(nums):
if len(nums) <= 1:
return nums
mid = len(nums)//2 #获取中间值
left, right = nums[:mid], nums[mid:]
return merge(merge_sort(left), merge_sort(right))
def merge(left, right):
result = []
i, j = 0, 0
while i < len(left) and j < len(right):
if left[i] < right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result += left[i:]
result += right[j:]
return result
归并排序的时间复杂度是O(nlogn)。
3.7 堆排序
堆排序是一种基于堆的排序算法,它的原理是将无序数组构建成一个二叉堆,并递归地将最大值移动到数组的末尾。
def heap_sort(nums):
n = len(nums)
for i in range(n//2 - 1, -1, -1):
heapify(nums, n, i)
for i in range(n-1, 0, -1):
nums[i], nums[0] = nums[0], nums[i]
heapify(nums, i, 0)
return nums
def heapify(nums, n, i):
largest = i
l = 2*i + 1
r = 2*i + 2
if l < n and nums[l] > nums[largest]:
largest = l
if r < n and nums[r] > nums[largest]:
largest = r
if largest != i:
nums[i], nums[largest] = nums[largest], nums[i]
heapify(nums, n, largest)
堆排序的时间复杂度是O(nlogn)。
3.8 计数排序
计数排序是一种比较简单的排序算法,它的原理是统计数组中每个元素出现的次数,并根据元素出现的次数将元素放入有序数组中。
def counting_sort(nums):
n = len(nums)
output, count = [0] * n, [0] * (max(nums)+1)
for num in nums:
count[num] += 1
for i in range(1, len(count)):
count[i] += count[i-1]
for i in range(n-1, -1, -1):
output[count[nums[i]]-1] = nums[i]
count[nums[i]] -= 1
return output
计数排序的时间复杂度是O(n+k),其中k是数组中最大元素的个数。
3.9 桶排序
桶排序是一种基于计数排序的排序算法,它的原理是将数组分成若干个桶,对桶内的元素进行排序,并按顺序将所有桶的元素排成一个有序数组。
def bucket_sort(nums):
n, k = len(nums), max(nums)
gap = (k+1) // n
buckets = [[] for _ in range(n)]
for num in nums:
i = min(num // gap, n-1)
buckets[i].append(num)
if len(buckets[i]) > 1:
j = len(buckets[i]) - 2
while j >= 0 and buckets[i][j] > num:
buckets[i][j+1] = buckets[i][j]
j -= 1
buckets[i][j+1] = num
return [num for bucket in buckets for num in bucket]
桶排序的时间复杂度是O(n+k),其中k是算法中桶的个数。
3.10 基数排序
基数排序是一种基于分治思想的排序算法,它的原理是首先按照个位数进行排序,然后按照十位、百位等高位进行排序。
def radix_sort(nums):
radix = 10
max_num = max(nums)
exp = 1
while max_num // exp > 0:
buckets = [[] for _ in range(radix)]
for num in nums:
buckets[num//exp % radix].append(num)
nums = [num for bucket in buckets for num in bucket]
exp *= 10
return nums
基数排序的时间复杂度是O(d(n+k)),其中d是数字位数,k是基数。
4. 总结
本文介绍了程序员必须掌握的十大排序算法,这些算法包括冒泡排序、选择排序、插入排序、希尔排序、快速排序、归并排序、堆排序、计数排序、桶排序、基数排序,对于程序员来说,排列数据使得程序运行的更快,增加程序的执行效率,提高程序的质量,是非常重要的,掌握排序算法是程序员必不可少的技能之一。