使用Python实现常见的几种排序算法
使用Python实现各种常见的排序算法
文章共介绍六种排序算法
- 冒泡排序
- 选择排序
- 插入排序
- 快速排序
- 希尔排序
- 归并排序
import sys
sys.setrecursionlimit(100000) #设置递归深度
class sort(object):
"""
该类中包含一些常见的排序算法,默认为升序排序
"""
def __init__(self,list):
self.list = list
def bubble_sort(self):
"""
冒泡排序,原理是依次比较相邻的两个元素的值,如果前面的大于后面的,就进行交换。每一轮会有一个最大的元素被选出放在最后。
n个元素经过n-1次排序即可完成排序。最优时间复杂度o(n),最坏时间复杂度o(n2),稳定排序算法。
:return: 返回排序后的列表
"""
for j in range(len(self.list)-1, 0, -1):
# j从8到0,不包含0,每次减一,包使排序的次数为8次。
for i in range(j):
# 每一轮i从0到j进行变化,不包含j
if self.list[i] > self.list[i+1]:
self.list[i], self.list[i+1] = self.list[i+1], self.list[i]
print("经过冒泡排序后的列表顺序为:" + str(self.list))
return self.list
def select_sort(self,newlist):
"""
选择排序,原理是每次从未排序序列中挑选出最小的元素放在序列开始,每轮会有一个元素被排好序。
n个元素进行n-1轮排序,最好最坏时间复杂度都是o(n2),不稳定
:return:返回排好序的列表
"""
print("原始列表顺序为:"+str(list))
n = len(newlist)
# 需要n-1次排序
for i in range(n-1):
# 记录最小值的位置
min_index = i
# 选出最小的值,交换下标
for j in range(i+1, n):
if newlist[j] < newlist[min_index]:
min_index = j
# 每一轮确定了最小的下标后,就更换值
if min_index != i:
newlist[i], newlist[min_index] = newlist[min_index], newlist[i]
print("经过选择排序后的列表顺序为:"+str(newlist))
return newlist
def insert_sort(self,newlist):
"""
插入排序,原理是构建一个已排列的序列,对于未排序的数据,在已排序序列中从后先前扫描,找到合适的位置插入。
n个元素需要n-1轮的排序,最优时间复杂度o(n),最坏时间复杂度o(n2),稳定
:param newlist:传入的未排序的列表
:return:返回已经排列好的列表
"""
print("原始列表顺序为:" + str(list))
# n个元素需要n-1轮的排序
for i in range(1,len(newlist)):
for j in range(i, 0, -1):
if newlist[j] < newlist[j-1]:
newlist[j], newlist[j-1] = newlist[j-1], newlist[j]
print("经过插入排序后的列表顺序为:" + str(newlist))
return newlist
def quick_sort(self, newlist, start, end):
"""
快速排序,原理是通过一趟排序要将排序的数据分割为独立的两部分,其中一部分的数据要比另一部分要小,
然后再按照这种方法对这两部分数据分别进行快速排序,不断递归。具体:从序列中挑选出一个数作为基准,重新排列数列
,所有比基准元素小的摆在基准前面,所有元素比基准大的摆在基准后面.在对其余两个前后序列进行相同操作.
最优时间复杂度o(nlogn),最差时间复杂度o(n2),空间复杂度o(logn),不稳定
:param newlist:无序列表
:return:返回已经排好序的列表
"""
if start < end:
i = start
j = end
pivot = newlist[start]
while i < j :
while newlist[j] >= pivot and i < j:
j -= 1
newlist[i], newlist[j] = newlist[j], newlist[i]
while newlist[i] <= pivot and i < j:
i += 1
newlist[i], newlist[j] = newlist[j], newlist[i]
self.quick_sort(newlist, start, i - 1)
self.quick_sort(newlist, i+1, end)
return newlist
def shell_sort(self, newlist):
"""
希尔排序,原理是将数据从大步长分割进行插入排序,慢慢减小步长进行排序,最终步长缩减为1.
最坏时间复杂度o(n2),不稳定
:param newlist:无序列表
:return:返回有序列表
"""
print("原始列表顺序为:" + str(list))
n = len(newlist)
# 初始步长
gap = n//2
while gap > 0 :
for i in range(gap, n):
j = i
# 插入排序
while j >= gap and newlist[j-gap] > newlist[j]:
newlist[j-gap] , newlist[j] = newlist[j], newlist[j-gap]
j -= gap
gap = gap//2
print("经过希尔排序后的列表顺序为:" + str(newlist))
return newlist
def merge_sort(self, newlist):
"""
归并排序的思想就是分治,先递归分解数组,在合并数组.具体:将数组分解到最小之后,比较两个数组最前面的数,谁小就取谁,
取了后相应的指针就往后移一位,然后再比较,直至有一个数组为空,再把不为空的数组直接复制过去。
最优和最坏时间复杂度为o(nlogn),稳定
:param newlist:无序列表
:return:返回有序列表
"""
if len(newlist) <= 1 :
return newlist
num = len(newlist)//2
left = self.merge_sort(newlist[:num])
right = self.merge_sort(newlist[num:])
return self.merge(left,right)
def merge(self, left, right):
"""
用于合并merge_sort拆分后的两个列表
:param left: 传入到merge_sort中的前num个数字组成的列表
:param right: 传入到merge_sort中的n-num个数字组成的列表
:return: 返回合并的结果
"""
l,r = 0,0
result = []
while l < len(left) and r < len(right):
if left[l] < right[r]:
result.append(left[l])
l += 1
else:
result.append(right[r])
r += 1
result += left[l:]
result += right[r:]
return result
if __name__ == "__main__":
list = [23,15,65,49,98,52,0,12,-16]
print("原始列表顺序为:"+str(list))
sort = sort(list)
sort.bubble_sort()
list = [23, 15, 65, 49, 98, 52, 0, 12, -16]
sort.select_sort(list)
list = [23, 15, 65, 49, 98, 52, 0, 12, -16]
sort.insert_sort(list)
list = [23, 15, 65, 49, 98, 52, 0, 12, -16]
print("原始列表顺序为:" + str(list))
print("经过快速排序的列表顺序为:"+str(sort.quick_sort(list, 0, len(list)-1)))
list = [23, 15, 65, 49, 98, 52, 0, 12, -16]
sort.shell_sort(list)
list = [23, 15, 65, 49, 98, 52, 0, 12, -16]
print("原始列表顺序为:" + str(list))
print("经过归并排序的列表顺序为:" + str(sort.merge_sort(list)))