1. 冒泡排序
对相邻元素进行两两比较,若逆序则进行交换,每一趟冒泡都会将最小(最大)的元素“浮”到顶端(归位),所以对于n个元素的数组,最多只需n-1趟冒泡,便可达到完全有序。
def bubble_sort(arr):
if not arr or len(arr) < 2:
return arr
# 归位第n-i个元素
for i in range(len(arr)-1):
# 默认此轮没有进行元素交换
flag = True
for j in range(len(arr)-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
flag = False
if flag:
return arr
# return arr
若原数组有序,仅需比较n-1次(1趟);
若为倒序,需比较(n-1)+(n-2)+...+1=n(n-1)/2次,与交换次数相等。
测试
a = [4, 3, 9, -1, 7, 3]
print(bubble_sort(a))
# [-1, 3, 3, 4, 7, 9]
2. 简单选择排序
排序结果不稳定!!!
每一趟从待排序的数据中选择最小(最大)的一个元素作为首元素,直到所有元素排完为止。
这样无论数组原始排序如何,比较次数是不变的;
对于交换操作,在数组完全有序时,无需交换,在最差情况下(数组倒序),交换n-1次即可。
def selection_sort(arr):
if not arr or len(arr) < 2:
return arr
for i in range(len(arr)-1):
# 每一趟比较时,较小元素的下标
min = i
for j in range(i+1, len(a)):
if a[j] < a[min]:
min = j
if min != i:
a[i], a[min] = a[min], a[i]
return arr
测试
a = [4, 3, 9, -1, 7, 3]
print(selection_sort(a))
# [-1, 3, 3, 4, 7, 9]
3. 直接插入排序
排序结果稳定!!!
时间复杂度:O(n^2)
空间复杂度:O(1)
在最好的情况下时间复杂度为o(n),需要比较n-1次,此时无需交换元素。
直接插入排序 > (优于)简单选择排序 > 冒泡排序
def insert_sort(arr):
if not arr or len(arr) < 2:
return arr
for i in range(1, len(arr)):
for j in range(i-1, -1, -1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
return arr
插入排序是将一个新元素插入到有序区间内(每一步将一个待排序的记录插入到前面已经排好序的有序序列中);而选择排序是在未排序区间找到min或max,并交换到有序区间之后。
4. 二分查找(折半查找)
时间复杂度: o(logN)
对数据的要求:
1. 采用顺序存储结构
2. 按关键字大小有序排列
def binary_search(arr, key):
if not arr or len(arr) == 0:
return -1
low, high = 0, len(arr) - 1
while low <= high:
mid = (low+high)//2
if arr[mid] == key:
return mid
if arr[mid] < key:
low = mid + 1
else:
high = mid - 1
return -1
测试
a = [-1, 3, 4, 4, 6, 7]
print(binary_search(a, 4))
# 2