文章目录
- 插入排序
- 选择排序
- 快速排序
- 堆排序
一、插入排序
插入排序的基本策略是,将待排序记录分为有序区和无序区,每次将无序区的第一个记录插入到有序区中的适当位置,使有序区保持有序,重复操作直至排序完成。
时间复杂度为 O(n^2)
空间复杂度为 O(1)
def insect_sort(lst):
for i in range(1, len(lst)):
t = lst[i]
j = i - 1
while j >= 0 and lst[j] > t: # 从右往左比较待插入数字和有序区数字,已排好的数字大于未排数字t,则将大于t的数字右移
lst[j + 1] = lst[j]
j = j - 1
lst[j + 1] = t # 跳出循环后,由于循环最后执行了j-1,所以+1
return lst
二、选择排序
选择排序的基本思想是:每一趟从待排序记录中选出关键字最小或最大的记录,并顺序存放在已排好序的记录序列的最后或前面,直至记录排序完成为止。选择排序的特点是记录移动排序的次数较少。
时间复杂度为 O(n^2)
def selection_sort(lst):
for i in range(1, len(lst)):
small = lst[i] # small 记录无序区的第一个数字
for j in range(i + 1, len(lst)): # 遍历无序区,找到其中的最小值
if lst[j] < small:
small = lst(j)
lst[i], small = small, lst[i] # 交换
return lst
三、快速排序
快速排序是对冒泡排序的改进,其基本思想是:通过一趟排序将记录序列分成两个子序列,然后分别对这两个子序列进行排序,以达到整个序列有序。快速排序是不稳定的。
时间复杂度:最好 O(n lb n),最坏O(n^2)
空间复杂度:最好O(lb n),最坏O(n)
def quick_sort(lst, left, right):
b = lst[0] # 以序列第一个数字为基准
l = left
r = right
if l >= r:
return 0 # 序列大小为1或空
while r != l:
while r > l and lst[r] >= b: # 从右往左依次遍历,直到找到比基准数小的数字
r -= 1
while r > l and lst[l] < b: # 从左往右依次遍历,直到找到比基准数大的数字
l += 1
lst[r], lst[l] = lst[l], lst[r] # 交换这两个数字
quick_sort(lst, left, l - 1) # 递归处理左序列
quick_sort(lst, l + 1, right) # 递归处理右序列
return lst
四、堆排序
1.递归建立大根堆。
大根堆是指每个父节点大于它的左右子节点。
def max_heapify(heap, heap_size, root):
left = 2 * root + 1
right = left + 1
larger = root
if left < heap_size and heap[larger] < heap[left]:
larger = left
if right < heap_size and heap[larger] < heap[right]:
larger = right
if larger != root:
heap[root], heap[larger] = heap[larger], heap[root]
max_heapify(heap, heap_size, larger)
从下往上建立大根堆
def build_heap(heap):
heap_size = len(heap)
for i in range((heap_size - 2) // 2, -1, -1):
max_heapify(heap, heap_size, i)
print(heap)
交换每次排序之后的最大值(根节点)和最后一个数字,然后heap的大小减1,重新构建大根堆,直至排序完成。
def heap_sort(heap):
build_heap(heap)
for i in range(len(heap) - 1, -1, -1):
heap[0], heap[i] = heap[i], heap[0]
max_heapify(heap, i, 0)
return heap
时间复杂度O(lb n)
空间复杂度O(1)