排序算法和数据结构中的六种算法思想和应用
2023-12-31 01:06:15
从基础到精通,从掌握到实现,排序算法无疑是每个程序员必备的技能。作为一名资深程序员,我在多年的编程实践中总结了6种最常见的排序算法,并将其封装成了一套全面的算法体系。
本文将逐一介绍这6种排序算法的思想、时间复杂度、空间复杂度和稳定性,并提供每种算法的实现代码。通过阅读本文,你将对排序算法有更深入的了解,以便在实际编程中根据具体问题选择合适的算法。
1. 选择排序
选择排序的思想非常简单,它从待排序的数组中选择最小的元素,然后将其与第一个元素交换,依次类推,直到数组中的所有元素都被排序好。
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:不稳定
def selection_sort(arr):
for i in range(len(arr) - 1):
min_index = i
for j in range(i + 1, len(arr)):
if arr[j] < arr[min_index]:
min_index = j
arr[i], arr[min_index] = arr[min_index], arr[i]
2. 冒泡排序
冒泡排序的思想也非常简单,它不断地比较相邻的两个元素,如果前一个元素大于后一个元素,则将它们交换,依次类推,直到数组中的所有元素都被排序好。
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定
def bubble_sort(arr):
for i in range(len(arr) - 1):
for j in range(len(arr) - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
3. 插入排序
插入排序的思想是将一个元素插入到已经排序好的数组中,使其保持有序。具体来说,从待排序的数组中选择一个元素,然后将其与已经排序好的数组中的元素逐一比较,找到合适的位置将该元素插入到数组中。
时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:稳定
def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j >= 0 and key < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
4. 希尔排序
希尔排序是插入排序的一种改进算法,它通过将数组分割成多个子数组,然后分别对每个子数组进行插入排序,最后将子数组合并成一个有序的数组。
时间复杂度:O(nlogn)
空间复杂度:O(1)
稳定性:不稳定
def shell_sort(arr):
gap = len(arr) // 2
while gap > 0:
for i in range(gap, len(arr)):
key = arr[i]
j = i
while j >= gap and key < arr[j - gap]:
arr[j] = arr[j - gap]
j -= gap
arr[j] = key
gap //= 2
5. 快速排序
快速排序是一种分治算法,它通过将数组分割成两个子数组,然后分别对两个子数组进行排序,最后将两个子数组合并成一个有序的数组。
时间复杂度:O(nlogn)
空间复杂度:O(logn)
稳定性:不稳定
def quick_sort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return quick_sort(left) + middle + quick_sort(right)
6. 归并排序
归并排序也是一种分治算法,它通过将数组分割成两个子数组,然后分别对两个子数组进行排序,最后将两个子数组合并成一个有序的数组。
时间复杂度:O(nlogn)
空间复杂度:O(n)
稳定性:稳定
def merge_sort(arr):
if len(arr) <= 1:
return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(left, right):
merged = []
left_index = 0
right_index = 0
while left_index < len(left) and right_index < len(right):
if left[left_index] <= right[right_index]:
merged.append(left[left_index])
left_index += 1
else:
merged.append(right[right_index])
right_index += 1
merged.extend(left[left_index:])
merged.extend(right[right_index:])
return merged