在数据结构中,排序算法是一块重头戏,今天主要来总结一下如何用python语言来实现几大主要的排序算法的实现
1.冒泡排序(Bubble Sort) :就像班主任给本班学生排队一样,每次从一列的开头那个同学往下比较,看下前一个同学和后一个同学的高矮次序,如果第一个同学最高,那他自然会排到最后面去。冒泡排序要做的就是执行多次的遍历,每次找出一个最大值放到最后,类似冒泡。最后排序完成(最大无绝对性,要看个人的实现方法)
程序运作思想:
- 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
def buddle_sort(mlist): """从大到小冒泡排序的实现""" n = len(mlist) # 总共要遍历的次数 为n-1次 for j in range(0, n-1): # 每次遍历要比较的次数 当第一次时 i的最大值就为n-1 以后每次减少1 for i in range(0, n-1-j): if mlist[i] < mlist[i+1]: mlist[i], mlist[i+1] = mlist[i+1], mlist[i] if __name__ == "__main__": mlist = [9, 8, 7, 4, 2, 34] buddle_sort(mlist) print(mlist)
===============================================================
2.选择排序(selection sort):首先在未排序列表中找出最大值,存放到排序序列的起始位置,然后再从未排序序列中找出最大值,将其放在已排序队列的末尾。选择排序每次移动一个元素,他们当中至少有一个要被移动到最终位置
def selection_sort(mlist):
"""从大到小选择排序的实现"""
n = len(mlist)
# 我们只需要确定n-1次位置的值就可以排序成功
for j in range(0, n-1):
# 每一次内循环都可以确定max_index 索引位置的值
# 第一次执行的时候,我们要确定0 索引位置的值
max_index = j
for i in range(j+1, n):
if mlist[max_index] < mlist[i]:
max_index = i
# 内循环结束后,我们知道了未排序队列的最大值的索引,还要对其进行交换
mlist[max_index], mlist[j] = mlist[j], mlist[max_index]
if __name__ == "__main__":
mlist = [9, 8, 7, 4, 2, 34, 99, 13]
selection_sort(mlist)
print(mlist)
运行结果:
================================================================================
3.插入排序(insertion sort):通过构建有序序列,对于未排序序列,从中一次取出数据插入已排序序列中。
def insert_sort(mlist):
"""插入排序"""
n = len(mlist)
# 默认索引0位置的数据为已排序序列
# 要从未排序序列取出的元素的次数
for j in range(1, n):
i = j
while i > 0:
if mlist[i] > mlist[i-1]:
mlist[i], mlist[i-1] = mlist[i-1], mlist[i]
i -= 1
else:
# 如果取出的数据比已排序序列的最后一个元素小,则比前面的都小,可以放在最后一位,退出循环
break
if __name__ == "__main__":
mlist = [54, 2, 7, 4, 2, 34]
insert_sort(mlist)
print(mlist)
运行结果:==========================================================================
4.快速排序(quick sort):将要数列里面的数据分割成独立的两部分,其中一部分的所有数据都要比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,通过递归将整个数据变为有序序列
- 从数列中挑出一个元素,称为"基准"(pivot),
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
运行结果:def quick_sort(mlist, start, end): """快速排序算法""" # 递归推出的条件 当上层函数low就为mid_value的位置时 递归传进来的start>end if start >= end: return # 定义中间值 mid_value = mlist[start] # low索引位置的数据 = mid_value low = start high = end # 我们一定要确保low 不能大于high while low < high: while low < high and mlist[high] > mid_value: high -= 1 mlist[low] = mlist[high] # 这里我们将和mid_value相等的值都放在比它小的序列,而且我们必须加入这个条件,不然 # 因为我们没有处理第一个数据程序将进入无限递归 # 在这里我们不能将这个循环放在上面循环之前,由于我们加入了条件mlist[low] <= mid_value # low索引可以向前移动,如果位置上的值大于mid_value,交换的时候会造成high序列数据丢失 while low < high and mlist[low] < mid_value: low += 1 mlist[high] = mlist[low] mlist[low] = mid_value # 执行递归操作,再对两个序列执行快速排序,每次都是将其中间值放入正确位置 # 直到要执行快速排序的序列里面的元素为 1 quick_sort(mlist, start, low-1) quick_sort(mlist, low+1, end) if __name__ == "__main__": mlist = [123, 322, 37, 4, 2, 34] quick_sort(mlist, 0, len(mlist)-1) print(mlist)
========================================================================
5.希尔排序(shell sort):从数列中按一定步长取出几列数列,分别对着几列数据进行排序,再减少步长进行排序,直到步长为1,此时变为插入排序
def shell_sort(alist):
"""希尔排序"""
n = len(alist)
# 取步长
gap = n // 2
while gap >= 1:
# 希尔算法,与普通插入算法之间的区别就是步长 ,
for j in range(gap, n):
i = j
while i > 0:
if alist[i] < alist[i - gap]:
alist[i], alist[i - 1] = alist[i - gap], alist[i]
i -= gap
else:
break
gap //= 2
if __name__ == "__main__":
mlist = [54,1,34, 2, 7, 4, 2, 34]
shell_sort(mlist)
print(mlist)
运行结果:
==========================================================================
6.归并排序:归并排序的思想就是先递归分解数组,再合并数组。将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。
def merge_sort(mlist):
"""归并排序算法"""
n = len(mlist)
# 按数列总长度的一半分割数组
# 当分割的数列只有一个元素时结束递归
if n <= 1:
return mlist
mid = n // 2
# 左边数列
left = merge_sort(mlist[:mid])
# 右边数列
right = merge_sort(mlist[mid:])
# 以下操作 先让两个序列变为有序,再将其合并为一个整体返回
left_pointer, right_pointer = 0, 0
result = []
# 当左右两个序列指针没有指向结尾执行以下操作
while left_pointer < len(left) and right_pointer < len(right):
if left[left_pointer] < right[right_pointer]:
result.append(left[left_pointer])
left_pointer += 1
else:
result.append(right[right_pointer])
right_pointer += 1
# 排序结束 将两个序列中没有添加进result数列的元素加入
result += right[right_pointer:]
result += left[left_pointer:]
return result
if __name__ == "__main__":
mlist = [123, 322, 37, 4, 2, 34, 234, 234, 341, 33, 33]
new_list = merge_sort(mlist)
print(new_list)
运行结果: