蓝桥杯中涉及的排序算法笔者计划用两期博客进行归纳。本博客包括:冒泡排序、选择排序和快速排序。每一个算法都在给出概念解释的同时,给出了示例代码,以供低年级师弟师妹们学习和练习。
前序知识:
(1)Python基础语法
(2)Python基础算法
一、冒泡排序
1. 原理:
冒泡排序是一种简单的排序算法,它通过重复遍历待排序的数列,比较相邻元素并交换位置,将较大的元素逐渐“冒泡”到数列的末尾。
2. 基本流程:
- 从数列的第一个元素开始,依次比较相邻的两个元素。
- 如果第一个元素大于第二个元素,就交换这两个元素。
- 遍历完一次后,最大的元素已经被“冒泡”到了数列的最后一个位置。
- 然后,忽略已经排好序的部分,对剩余的部分重复上述过程。
- 每次遍历后,未排序的部分越来越少,直到所有元素都排好序。
3. 实时演示:
4. 性能分析:
(1)时间复杂度:
- 时间复杂度较高,效率较低,不适用于大规模数据。
- 最好情况:O(n)(当数组已经有序时,冒泡排序会进行一趟扫描即可退出)
- 最坏情况:O(n^2)(当数组完全倒序时)
- 平均情况:O(n^2)
(2)空间复杂度:
- O(1),因为它是原地排序,不需要额外的存储空间。
5. 代码(包含上述实时演示):
# 冒泡排序
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display, clear_output
def bubble_sort_jupyter(arr):
fig, ax = plt.subplots(figsize=(8,4))
n = len(arr)
for i in range(n):
for j in range(n-i-1):
#------------------------------这一部分仅仅用于实时可视化--------------------------------
# 创建颜色数组
colors = ['skyblue']*n
colors[j] = 'red'
colors[j+1] = 'lime'
# 更新图表
ax.clear()
ax.bar(range(n), arr, color=colors)
ax.set_title(f'冒泡排序 | 轮数: {i*n+j} | 当前比较: {arr[j]} vs {arr[j+1]}')
# 显示并清除输出
clear_output(wait=True)
display(fig)
plt.close(fig) # 防止内存泄漏
#------------------------------以上代码仅仅用于实时可视化--------------------------------
#------------------------------以下代码是实际的冒泡排序逻辑------------------------------
# 比较交换逻辑
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
plt.pause(0.5) # 暂停以更新显示
return arr
# 使用示例
arr = np.random.randint(1, 100, 10)
result = bubble_sort_jupyter(arr.copy())
print("原始数组:", arr)
print("排序后数组:", result)
二、选择排序
1. 原理:
选择排序是一种简单的排序算法。它每次从未排序的部分选择最小(或最大)元素,将其与未排序部分的第一个元素交换位置,逐步将数据分成已排序和未排序两部分,直到整个数组有序。
2. 基本流程:
- 从未排序部分选择最小的元素。 将该元素与未排序部分的第一个元素交换。
- 将已排序部分的边界向右移动一位。
- 重复以上过程,直到所有元素都排好序。
3. 实时演示:
4. 性能分析:
(1)时间复杂度:
- 时间复杂度较高,尤其是对大规模数据。
- 最好情况:O(n^2)
- 最坏情况:O(n^2)
- 平均情况:O(n^2)
(2)空间复杂度:
- O(1),同样是原地排序。
5. 代码(包含上述实时演示):
# 选择排序
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import display, clear_output
def selection_sort_jupyter(arr):
fig, ax = plt.subplots(figsize=(8,4))
n = len(arr)
for i in range(n):
min_idx = i
ax.clear()
colors = ['skyblue']*n
colors[i] = 'red'
for j in range(i+1, n):
#------------------------------这一部分仅仅用于实时可视化--------------------------------
# 更新比较颜色
colors[j] = 'lime'
ax.bar(range(n), arr, color=colors)
ax.set_title(f'选择排序 | 扫描中... 当前最小值: {arr[min_idx]}')
clear_output(wait=True)
display(fig)
plt.close(fig)
colors[j] = 'skyblue' # 恢复颜色
#------------------------------以上代码仅仅用于实时可视化--------------------------------
#------------------------------以下代码是实际的快速排序逻辑------------------------------
if arr[j] < arr[min_idx]:
min_idx = j
plt.pause(0.5) # 暂停以更新显示
# 显示最终交换
colors[i], colors[min_idx] = 'red', 'lime'
ax.bar(range(n), arr, color=colors)
ax.set_title('将最小值调换到头部!')
clear_output(wait=True)
display(fig)
plt.close(fig)
arr[i], arr[min_idx] = arr[min_idx], arr[i]
plt.pause(0.5) # 暂停以更新显示
return arr
# 使用示例
arr = np.random.randint(1, 100, 10)
result = selection_sort_jupyter(arr.copy())
print("原始数组:", arr)
print("排序后数组:", result)
三、快速排序
1. 原理:
快速排序是一种“分治法”策略的排序算法。它通过一个枢轴(pivot)将数组分为两个子数组,其中一个子数组的元素都比枢轴小,另一个子数组的元素都比枢轴大。然后递归地对这两个子数组进行快速排序,最终整个数组排好序。
2. 基本流程:
- 选择一个元素作为枢轴,通常选择第一个元素、最后一个元素或中间元素。
- 将数组分成两个子数组:一个包含比枢轴小的元素,另一个包含比枢轴大的元素。
- 对这两个子数组分别递归执行快速排序。
- 当子数组的大小为1或0时,递归结束。
3. 实时演示:
4. 性能分析:
(1)时间复杂度:
- 快速,尤其对于大规模数据,平均情况下时间复杂度较低。
- 最好情况:O(n log n),当枢轴总是能平衡分割数组时。
- 最坏情况:退化为O(n^2),当选择的枢轴总是数组的最大或最小元素时(比如已经排序好的数组)。
- 平均情况:O(n log n)。
(2)空间复杂度:
- O(log n),因为递归过程中栈的深度是O(log n)。
5. 代码(包含递归演示):
import numpy as np
def quick_sort(arr, depth=0):
# 如果数组长度小于等于1,直接返回数组(已经排好序)
if len(arr) <= 1:
return arr
else:
# 选择基准元素,通常选择中间元素
pivot = arr[len(arr) // 2]
# 使用numpy的布尔索引来划分出比基准小、比基准大的两个子数组
left = arr[arr < pivot]
middle = arr[arr == pivot]
right = arr[arr > pivot]
# 打印当前递归的深度和数组的状态
print(f"{' ' * depth}[{' '.join(map(str, arr))}] -> [{ ' '.join(map(str, left)) }] [{ ' '.join(map(str, middle)) }] [{ ' '.join(map(str, right)) }]")
# 递归对左边和右边进行排序
return np.concatenate([quick_sort(left, depth + 1), middle, quick_sort(right, depth + 1)])
# 使用示例
arr = np.random.randint(1, 100, 10)
print("原始数组:", arr)
result = quick_sort(arr.copy())
print("排序后数组:", result)