一、插入排序
对含有 个元素的数组 进行 次遍历,第 次遍历将元素 插入到位置区间 中合适的位置上。
# !/usr/bin/python
# coding=utf-8
def insert_sort(a):
loop_num = len(a) - 1
if loop_num == -1:
return
for i in range(loop_num):
tmp = a[i + 1]
p = -1
for j in range(i, -1, -1):
if tmp >= a[j]:
break
a[j + 1] = a[j]
p = j
if p != -1:
a[p] = tmp
return a
def main():
# 测试用例
a = [34, 2, 14, 5, 6, 200, 122, 79]
insert_sort(a)
a = [2, 1]
insert_sort(a)
a = [1, 2]
insert_sort(a)
a = [1]
insert_sort(a)
a = []
insert_sort(a)
if __name__ == '__main__':
main()
最好情况: 有序,仅需n-1次比较,
最坏情况: 逆序,需n * (n-1) / 2次比较和交换
时间复杂度: O(n*n)
二、选择排序
对有 个元素的数组 进行 次遍历,第 次遍历顺序扫描子数组,并将其中最小的元素与 相交换。
# !/usr/bin/python
# coding=utf-8
def select_sort(a):
loop_num = len(a) - 1
if loop_num == -1:
print('empty array!')
return
for i in range(loop_num):
t = i
for j in range(i + 1, loop_num + 1):
if a[j] < a[t]: t = j
a[i], a[t] = a[t], a[i]
return a
def main():
# 测试用例
a = [34, 2, 14, 5, 6, 200, 122, 79]
select_sort(a)
a = [2, 1]
select_sort(a)
a = [1, 2]
select_sort(a)
a = [1]
select_sort(a)
a = []
select_sort(a)
if __name__ == '__main__':
main()
最好情况: 有序,需n-1次比较
最坏情况: 逆序,需n * (n-1) / 2次比较, 以及n - 1次交换
时间复杂度: O(n*n)
三、冒泡排序
对有 个元素的数组 进行 次遍历,第 次遍历将按顺序对子数组中所有毗邻元素对进行交换,交换原则是小元素排在大元素之前,最多执行 次交换,遍历结束后,成为子数组中的最大元素。
# !/usr/bin/python
# coding=utf-8
def bubble_sort(a):
loop_num = len(a) - 1
if loop_num == -1:
print('empty array!')
return
for i in range(loop_num):
for j in range(i, loop_num):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
return a
def main():
# 测试用例
a = [34, 2, 14, 5, 6, 200, 122, 79]
bubble_sort(a)
a = [2, 1]
bubble_sort(a)
a = [1, 2]
bubble_sort(a)
a = [1]
bubble_sort(a)
a = []
bubble_sort(a)
if __name__ == '__main__':
main()
最好情况: 有序,需n-1次比较
最坏情况: 逆序,需n * (n-1) / 2次比较, 以及n * (n-1) / 2次交换
时间复杂度: O(n*n)
四、插入排序和冒泡排序的优劣性比较
实质上,三种简单排序的性能与一个概念——逆序紧密相关。逆序定义为数组中 但 的序偶,数组中序偶中的数量即执行插入排序需要进行的交换次数。情况总是这样,因为交换两个不按原序排序的元素恰好消除一个逆序,而一个排过序的数组没有逆序。
一般来说,插入排序较冒泡排序性能更胜一筹,为什么那? 因为冒泡排序的交换次数和插入排序的移动次数都是由逆序对的数量决定的,但是冒泡排序的数据交换要比插入排序的数据移动要复杂,冒泡排序需要 3 个赋值操作,而插入排序只需要 1 个。所以,插入排序的实际运行时间要优于冒泡排序。