04=排序算法(冒泡选择插入和快速排序)
Posted 伤心兮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了04=排序算法(冒泡选择插入和快速排序)相关的知识,希望对你有一定的参考价值。
一、排序算法
1.1 冒泡排序
-
每次循环都比较前后两个元素的大小,如果前者大于后者,则将两者进行交换。这样做会将每次循环中最大的元素替换到末尾,逐渐形成有序集合。将每次循环中的最大元素逐渐由队首转移到队尾的过程形似“冒泡”过程,故因此得名。
-
时间复杂度 最好O(n),平均O( n 2 n^2 n2),最坏O( n 2 n^2 n2)
import random
import time
def bubble(li):
'''
:param li: 需要进行排序的数组
:return: 排好序的数组
''' n = len(li)
while n:
for i in range(n - 1):
if li[i] >= li[i + 1]:
li[i], li[i + 1] = li[i + 1], li[i]
n -= 1
return li
def main():
begin = time.time()
li = list(range(10000))
random.shuffle(li) # 打乱
print(bubble(li))
end = time.time()
print(end - begin)
if __name__ == '__main__':
main()
- 但是上述代码情况时间复杂度始终是不变的。为O( n 2 n^2 n2)。最好的情况下(也就是数组已经排好序了)此时,时间复杂度为O(n)。
import random
import time
# 装饰器函数
def get_time(fn):
def inner(*args, **kwargs):
begin = time.time()
result = fn(*args, **kwargs)
end = time.time()
print("函数执行花费%f秒" % (end - begin))
return result
return inner
@get_time
def bubble(li):
'''
:param li: 需要进行排序的数组
:return: 排好序的数组
''' for i in range(len(li) - 1): # i表示第n趟
is_exchange = False
for j in range(len(li)-i-1): # len(li)-i-1表示无序区
if li[j] >= li[j + 1]:
li[j], li[j + 1] = li[j + 1], li[j]
is_exchange = True
if not is_exchange: # 如果第一趟没有进行交换。则说明列表为顺序排序
break
return li
def main():
li = list(range(10000))
bubble(li) # 函数执行花费0.001997秒
random.shuffle(li) # 打乱
bubble(li) # 函数执行花费28.990895秒
if __name__ == '__main__':
main()
1.2 选择排序
- 一次遍历最小的数,放到第一个位置。再一次遍历记录无序区中最小的数,继续放置。
- 其核心就是找到最小值对应的索引,然后与无序区的第0个元素交换位置。
import time
import random
# 装饰器函数
def get_time(fn):
def inner(*args, **kwargs):
begin = time.time()
result = fn(*args, **kwargs)
end = time.time()
print("函数执行花费%f秒" % (end - begin))
return result
return inner
@get_time
def select_sort(li):
for i in range(len(li)-1): # n-1躺
min_pos = i # 无序区最小值对应的索引,
for j in range(i+1,len(li)): # 无序区
if li[j] < li[min_pos]:
min_pos = j
li[i], li[min_pos] = li[min_pos], li[i] # 交换位置
return li
def main():
li = list(range(10000))
select_sort(li) # 函数执行花费7.453225秒
if __name__ == '__main__':
main()
1.3 插入排序
- 插入排序的精髓在于每次都会在先前排好序的子集合中插入下一个待排序的元素,每次都会判断待排序元素的上一个元素是否大于待排序元素,如果大于,则将元素右移,然后判断再上一个元素与待排序元素…以此类推。直到小于等于比较元素时就是找到了该元素的插入位置。
def insert_sort(li):
for i in range(1, len(li)): # i相对无序区的下标
tem = li[i]
j = i - 1
while j >= 0 and li[j] > tem: # 相对无序区的值小于于相对有序区的值
li[j+1] = li[j] # 则有序区的值后移
j -= 1 # 直到最后
# j的位置在循环结束时要么是-1,要么比tem小
li[j+1] = tem
return li
def main():
li = [6, 3, 1, 7, 8, 0, 2, 4, 9, 5]
print(insert_sort(li))
if __name__ == '__main__':
main()
1.4 快速排序
- 快速排序核心是找到一个中心枢纽(一般为第零个元素),使用双指针法,
- i从左往右,j从右往左。根据中心枢纽进行分区,先从左往右找到第1个比中心枢纽大的数字,从右往左找到找到第一个比中心枢纽小的数字。这两个数字进行交换。
- 然后i继续从左往右,找到下一个比中心枢纽大的数字,j继续从右往左找比中心枢纽小的数字。再将这两个数字继续宁交换
- 直到i和j相交,最后把中心枢纽放进i和j中间。对于中心枢纽左边和右边,使用递归调用,得到最终结果。
def quick_sort(li):
if len(li) < 2:
return li
tmp = li[0]
left = [v for v in li[1:] if v <= tmp]
right = [v for v in li[1:] if v > tmp]
left = quick_sort(left)
right = quick_sort(right)
return left + [tmp] + right
以上是关于04=排序算法(冒泡选择插入和快速排序)的主要内容,如果未能解决你的问题,请参考以下文章
插入排序(直接插入排序希尔排序);交换排序(冒泡排序快速排序);选择排序(简单选择排序堆排序);归并排序和基数排序;基于关键词比较的排序算法下界分析