编程小白最近在学习算法,自己用python写了十大排序算法,发出来供大家参考。如有不足之处,欢迎批评讨论。
首先是两种交换排序:冒泡排序和快速排序。
def bubbleSort(nums: list) -> list:
"""
冒泡排序
1. **优化一**:通过记录最后一次交换的位置`lastChange`,减少了每次内层循环的比较次数。因为超过`lastChange`的部分在上一次遍历时已经排序好,无需再次比较。
2. **优化二**:设置`done`标志位来判断在一次外层循环中是否发生了任何交换。如果没有发生交换,说明整个数组已经排序完成,可以提前结束排序,避免不必要的遍历。
:param nums: 待排序序列
:return: 排序后序列
"""
l = len(nums)
lastChange = l - 1 # 优化一:记录最后一次交换的位置,作为内层循环的终点
for i in range(l - 1):
done = True # 优化二:判断一轮遍历中是否发生交换,若无则表示已排序好,终止遍历
for j in range(lastChange):
if nums[j] > nums[j + 1]:
nums[j], nums[j + 1] = nums[j + 1], nums[j]
done = False
lastChange = j
if done: break
return nums
def quickSort(nums: list, start=0, end=None) -> list:
"""
快速排序
### 改进建议:
1. **增加随机选择基准值**:这段代码中选择的基准值是区间起始位置的元素,这样可能导致在面对特定序列(如已排序序列)时效率降低。可以通过随机选择基准值来提高算法的平均性能。
2. **尾递归优化**:尽管Python的标准实现CPython不支持尾调用优化,但改写代码逻辑来减少递归深度依然有其好处。可考虑对较小的子数组先递归排序,避免过深的递归调用。
3. **优化比较和交换操作**:当前的实现中,即使`bigIndex`和`smallIndex`相遇,也会进行一次无意义的交换。可以改进以避免这种不必要的操作。
:param nums: 待排序序列
:param start:排序起始索引,默认为0
:param end:排序结束索引,默认为None
:return: 排序后序列(注意:原地排序,返回原来的列表对象)
"""
if end is None: end = len(nums) - 1 # 在首次调用时,设置end为列表最后一个元素的索引
if start >= end: return nums # 如果起始索引大于等于结束索引,则不需要排序,直接返回列表
# 初始化基准值为起始位置的元素,bigIndex指向起始位置,smallIndex指向结束位置
stdNum = nums[start]
bigIndex = start
smallIndex = end
# 开始循环,直到bigIndex与smallIndex相遇
while bigIndex != smallIndex:
# 从右向左找第一个小于等于基准值的元素
while nums[smallIndex] >= stdNum and bigIndex != smallIndex:
smallIndex -= 1
# 从左向右找第一个大于等于基准值的元素
while nums[bigIndex] < stdNum and bigIndex != smallIndex:
bigIndex += 1
nums[bigIndex], nums[smallIndex] = nums[smallIndex], nums[bigIndex] # 交换找到的两个元素的位置
nums[bigIndex] = stdNum # 将基准值放到最终位置
# 对基准值左右两边的列表递归进行快速排序
quickSort(nums, start, bigIndex - 1)
quickSort(nums, bigIndex + 1, end)
return nums
if __name__ == '__main__':
from random import choices
nums = list(choices(range(100), k=10))
print('Before sorting:', nums)
print('After bubbleSort sorting:', bubbleSort(nums))
print('After quickSort sorting:', quickSort(nums))
输出:
Before sorting: [52, 46, 73, 98, 79, 69, 51, 67, 78, 43]
After bubbleSort sorting: [43, 46, 51, 52, 67, 69, 73, 78, 79, 98]
After quickSort sorting: [43, 46, 51, 52, 67, 69, 73, 78, 79, 98]