# bubble sort
# 冒泡排序(交换排序)
"""
- 基本思想是 通过与相邻元素的比较和交换,把较小的元素交换到最前面。
- 时间复杂度 O(n^2), 空间复杂度 O(1)
"""
def bubble_sort(seq):
n = len(seq)
for i in range(n-1, -1, -1):
for j in range(i):
if seq[i] < seq[j]:
seq[i], seq[j] = seq[j], seq[i]
print(seq)
# select sort(选择排序)
"""
- 基本思想 每次选出待排序序列中最小的元素与排好序的最后一个元素做比较
- 时间复杂度 O(n^2), 空间复杂度 O(1)
"""
def select_sort(seq):
for i in range(len(seq)):
min_idx = i
for j in range(i+1, len(seq)):
if seq[j] < seq[min_idx]:
min_idx = j
if i != min_idx:
seq[min_idx], seq[i] = seq[i], seq[min_idx]
print(seq)
# insert sort
"""
- 基本思想 每次从将待排序序列中的一个元素插入到有序序列中
- 时间复杂度 O(n^2), 空间复杂度 O(1)
"""
# 写法1
def insert_sort(seq):
n = len(seq)
for i in range(1, n):
if seq[i] < seq[i-1]:
temp = seq[i]
index = i # 待插入的下标
for j in range(i-1, -1, -1):
if seq[j] > temp:
seq[j + 1] = seq[j]
index = j
else:
break
seq[index] = temp
print(seq)
# 写法2
def insert(seq):
n = len(seq)
for i in range(1, n):
j = i - 1
tmp = seq[i]
while tmp < seq[j] and j>=0:
seq[j+1] = seq[j]
j -= 1
seq[j+1] = tmp
return seq
# quick sort
"""
- 基本思想 选择一个基准元素,将其余元素中比它大的放到右边,比它小的放到左边
- 时间复杂度 O(nlogn), 空间复杂度 O(nlogn)
"""
def quick_sort(seq):
return qsort(seq, 0, len(seq)-1)
def qsort(seq, left, right):
if left >= right:
return seq
x = seq[left]
i, j = left+1, right
while i < j:
while j>i and seq[j]>=x:
j -=1
while i<j and seq[i]<=x:
i += 1
seq[i], seq[j] = seq[j], seq[i]
seq[i], seq[left] = x, seq[i]
qsort(seq, left, i-1)
qsort(seq, j+1, right)
return seq
# merge sort
"""
- 基本思想: 归并排序采用的是分治思想,将待排序序列划分为2个序列,再对每个子序列进行划分,直到每个子序列只有一个元素为止,最后对子序列进行排序,排序后两两归并并,最后得到一个有序序列。
- 时间复杂度: o(nlogn), 空间复杂度o(n)
- 划分数据+合并且排序
"""
def merge_sort(seq):
if len(seq) <= 1:
return seq
mid = len(seq)//2
# 将列表分为两个部分,并且分别返回排好序的列表
left = merge_sort(seq[:mid])
right = merge_sort(seq[mid:])
return merge(left, right)
def merge(left, right):
# 合并两个排好序的列表,产生一个已排好序的列表
result = []
i = j = 0 # 为两个列表中的指针,便于两两对比
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result += left[i:]
result += right[j:]
return result
# heap sort
"""
- 基本思想:
- 时间复杂度
"""
def heap_sort(seq):
n = len(seq)
first = int(n/2-1) # 最后一个非叶子结点
for i in range(first, -1, -1): # 构造一个大根堆
max_heapify(seq, i, n-1)
for j in range(n-1, 0, -1):
seq[j], seq[0] = seq[0], seq[j]
max_heapify(seq, 0, j-1)
return seq
#
#
# #最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
# #start为当前需要调整最大堆的位置,end为调整边界
def max_heapify(seq, start, end):
root = start
while 1:
child = 2*root + 1
if child > end:
break
if child+1 <= end and seq[child] < seq[child+1]:
child += 1
if seq[root] < seq[child]:
seq[root], seq[child] = seq[child], seq[root]
root = child
else:
break
def find_topk(seq, k):
def build_min_heap(heap_array):
for i in range(len(heap_array)//2-1, -1, -1):
heapify(heap_array, i, len(heap_array)-1)
def heapify(array, start, end):
root = start # 假设最初的点是较小者
while True:
child = root*2 + 1 # 左孩子结点
if child > end:
break
if child + 1 <= end and array[child] > array[child+1]: # 先找到两个子结点中的较小者
child = child + 1
if array[root] > array[child]: # 再将较小者与父结点比较,找到较小者,交换
array[child], array[root] = array[root], array[child]
root = child
else:
break
heap_array = []
for i in range(k):
heap_array.append(seq[i])
build_min_heap(heap_array)
for i in range(k, len(seq)):
if seq[i] > heap_array[0]:
heap_array[0] = seq[i]
heapify(heap_array, 0, k-1)
return heap_array
def quickselect(seq, k):
if len(seq)<k:
return seq
pivort = seq[-1]
right = [pivort] + [x for x in seq[:-1] if x >= pivort]
rlen = len(right)
if rlen == k:
return right
if rlen> k:
return quickselect(right, k)
else:
left = [x for x in seq[:-1] if x < pivort]
return quickselect(left, k-rlen) + right
if __name__=='__main__':
seq = [3, 1, 2, 5, 2, 3, 9, 7, 11, -1]
# bubble_sort(seq)
# select_sort(seq)
# insert_sort(seq)
# s = quick_sort(seq)
s1 = heap_sort(seq)
print(s1)
s2 = find_topk(seq, 5)
print(s2)
s3 = merge_sort(seq)
print(s3)
s4 = quickselect(seq, 5)