冒泡排序
冒泡排序是一种基本的排序算法,其基本思想是将相邻的元素进行比较和交换,从而逐步将最大的元素“冒泡”到最后面。其算法流程如下:
从数组的第一个元素开始,对相邻的两个元素进行比较,如果前一个元素比后一个元素大,则交换它们的位置,否则不交换。
继续比较数组中后面相邻的两个元素,重复上述操作,直到最后一个元素。
重复上述操作,每次循环将最大的元素“冒泡”到数组的最后面,直到所有元素都被排序。
冒泡排序的时间复杂度为 O(n^2),空间复杂度为 O(1)。在排序过程中,相邻元素的比较和交换操作是基本操作,因此其稳定性较好,适合于小规模数据的排序。
以下是冒泡排序的示例代码(使用 Python 语言实现):
def bubble_sort(arr):
n = len(arr)
for i in range(n):
for j in range(n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
选择排序
选择排序是一种简单的排序算法,其基本思想是从待排序的序列中选出最小(或最大)的元素,将其放到序列的起始位置,然后再从剩余的元素中选出最小(或最大)的元素,放到已排序序列的末尾。依次类推,直到所有元素都被排序。
其算法流程如下:
从序列中找到最小(或最大)的元素,将其放到序列的起始位置。
从剩余的元素中继续寻找最小(或最大)的元素,放到已排序序列的末尾。
重复上述操作,直到所有元素都被排序。
选择排序的时间复杂度为 O(n^2),空间复杂度为 O(1)。由于每次只需找出最小(或最大)的元素,因此它的交换次数相对于其他排序算法较少,但是其比较次数是不变的,因此其效率相对较低。
以下是选择排序的示例代码(使用 Python 语言实现):
def selection_sort(arr):
n = len(arr)
for i in range(n-1):
min_index = i
for j in range(i+1, n):
if arr[j] < arr[min_index]:
min_index = j
arr[i], arr[min_index] = arr[min_index], arr[i]
return arr
插入排序
插入排序是一种简单的排序算法,其基本思想是将待排序的元素插入到已排序序列中的正确位置,从而得到一个新的、更大的有序序列。它的工作方式类似于整理扑克牌的过程。
其算法流程如下:
将待排序的序列看成一个有序序列和一个无序序列,初始时有序序列只有一个元素。
从无序序列中取出第一个元素,将其插入到有序序列中的正确位置,使得有序序列仍然有序。
继续取出无序序列中的下一个元素,将其插入到有序序列中的正确位置,使得有序序列仍然有序。
重复上述操作,直到所有元素都被排序。
插入排序的时间复杂度为 O(n^2),空间复杂度为 O(1)。由于每次只需将一个元素插入到有序序列中,因此其交换次数相对于冒泡排序和选择排序较少,但是其比较次数仍然很高。
以下是插入排序的示例代码(使用 Python 语言实现):
def insertion_sort(arr):
n = len(arr)
for i in range(1, n):
key = arr[i]
j = i - 1
while j >= 0 and arr[j] > key:
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
return arr
快速排序
快速排序是一种高效的排序算法,它采用了分治法的思想,将待排序的序列分成两个子序列,一个子序列的元素都比另一个子序列小(或大),然后再对子序列进行递归排序,直到整个序列有序。
其算法流程如下:
从序列中选择一个元素作为基准元素(pivot)。
将序列中所有小于基准元素的元素放到基准元素的左侧,所有大于基准元素的元素放到右侧。
对基准元素左右两侧的子序列递归进行排序。
重复上述操作,直到整个序列有序。
快速排序的时间复杂度为 O(nlogn),空间复杂度为 O(logn)。由于快速排序采用了分治法的思想,因此它的效率相对较高。但是在某些情况下,它的效率可能会变得很低,例如当序列已经有序或者近乎有序时,每次划分都只能将一个元素划分到一侧,此时快速排序的效率会退化为 O(n^2)。
以下是快速排序的示例代码(使用 Python 语言实现):
def quick_sort(arr, left, right):
if left >= right:
return
pivot = partition(arr, left, right)
quick_sort(arr, left, pivot-1)
quick_sort(arr, pivot+1, right)
def partition(arr, left, right):
pivot = arr[left]
while left < right:
while left < right and arr[right] >= pivot:
right -= 1
arr[left] = arr[right]
while left < right and arr[left] <= pivot:
left += 1
arr[right] = arr[left]
arr[left] = pivot
return left
# 在这段代码中,quick_sort 函数用于对序列进行排序,partition 函数用于将序列分成两个子序列。快速排序采用了递归的方式实现,首先选择序列的第一个元素作为基准元素 pivot,然后使用 partition 函数将序列划分为两个子序列。在 partition 函数中,使用两个指针 left 和 right 分别从序列的左右两端开始扫描,不断将元素交换,直到 left 和 right 指针相遇,此时将基准元素放到 left 指针的位置,然后返回 left 指针的位置,作为下一次划分的基准元素位置。最终返回排序后的数组。
归并排序
归并排序是一种采用分治策略的排序算法,它的基本思想是将待排序的序列划分成若干个子序列,对每个子序列进行排序,然后将已排序的子序列合并成一个有序的序列。
具体实现过程如下:
将待排序序列平均分成两部分,分别对这两部分进行归并排序。
将两个已排序的子序列合并成一个有序的序列,这个过程称为归并。
递归执行步骤 1 和步骤 2,直到序列中只剩下一个元素,此时序列已经有序。
在归并排序中,最重要的是归并操作。归并操作的实现方法有多种,其中一种比较常用的是使用两个指针分别指向两个有序子序列的起始位置,比较指针所指的元素大小,将较小的元素复制到新的序列中,直到其中一个子序列复制完毕,再将另一个子序列中剩余的元素复制到新的序列中。
归并排序的时间复杂度为 O(nlogn),它比较稳定,不会出现最坏情况,但是其空间复杂度为 O(n),需要额外的空间来存储排序后的序列。
以下是归并排序的示例代码(使用 Python 语言实现):
def merge_sort(arr):
if len(arr) > 1:
mid = len(arr) // 2
left_half = arr[:mid]
right_half = arr[mid:]
merge_sort(left_half)
merge_sort(right_half)
i = j = k = 0
while i < len(left_half) and j < len(right_half):
if left_half[i] < right_half[j]:
arr[k] = left_half[i]
i += 1
else:
arr[k] = right_half[j]
j += 1
k += 1
while i < len(left_half):
arr[k] = left_half[i]
i += 1
k += 1
while j < len(right_half):
arr[k] = right_half[j]
j += 1
k += 1
# 在这段代码中,merge_sort 函数采用递归的方式将待排序序列划分成若干个子序列,并对每个子序列进行排序。merge 函数实现了归并操作,将两个已排序的子序列合并成一个有序的序列。在实现 merge 函数时,我们采用了两个指针 i 和 j 分别指向两个子序列的起始位置,比较指针所指的元素大小,将较小的元素复制到新的序列中,直到其中一个子序列复制完毕,再将另一个子序列中剩余的元素复制到新的序列
shell 排序
Shell 排序,也称为希尔排序,是插入排序的一种改进算法。它采用分组的思想,先将待排序序列按照一定的间隔分成若干个子序列,对子序列进行插入排序,然后缩小间隔,再次对子序列进行插入排序,直到间隔为 1 时完成排序。
具体算法流程如下:
选择一个增量序列,常用的增量序列为 Shell 提出的增量序列:n/2,n/4,n/8 ... 1。
按照增量序列将待排序序列分成若干个子序列,对每个子序列进行插入排序。
缩小增量序列,再次按照增量序列将子序列分组进行插入排序。
重复步骤 3,直到增量为 1 时完成排序。
Shell 排序的时间复杂度取决于增量序列的选择,通常情况下时间复杂度为 O(n^2),但是在某些增量序列的选择下,时间复杂度可以达到 O(nlogn)。Shell 排序比插入排序的效率要高,但是其实现比较复杂,需要选择适当的增量序列。
以下是 Shell 排序的示例代码(使用 Python 语言实现):
def shell_sort(arr):
n = len(arr)
gap = n // 2
while gap > 0:
for i in range(gap, n):
temp = arr[i]
j = i
while j >= gap and arr[j-gap] > temp:
arr[j] = arr[j-gap]
j -= gap
arr[j] = temp
gap //= 2
# 在这段代码中,gap 表示增量序列的长度,初始值为序列长度的一半,每次循环缩小增量序列,直到增量序列为 1。在每个增量序列下,按照插入排序的方式对每个子序列进行排序。