一个合格的算法工程师应该具有熟练写各种排序算法的本领
1,快速排序(n*logn)
分治法,主要是它的划分过程,即选取一个值将list中不大于该数的放在该数左边,不小于该数的放在该数右边,然后分别对左右两个区间递归划分。
def sortmy(arr, low, high):
if low < high:
n = partition(arr, low, high)
sortmy(arr, low, n - 1)
sortmy(arr, n+1, high)
def partition(arr, low, high):
key = arr[low]
while low < high:
while low < high and arr[high] >= key:
high -= 1
arr[low] = arr[high]
while low < high and arr[low] <= key:
low += 1
arr[high] = arr[low]
arr[low] = key
return low
arr = list(map(int, input().split()))
sortmy(arr, 0, len(arr) - 1)
print(arr)
2, 冒泡排序(n^2)
每次循环将最大的值放在数组最后
def sortmy(arr, n):
while n:
for i in range(n-1):
if arr[i] > arr[i+1]:
arr[i], arr[i+1] = arr[i+1], arr[i]
n -= 1
arr = list(map(int, input().split()))
sortmy(arr, len(arr))
print(arr)
3,堆排序(n*logn)
先构建大根堆(没有排好序),然后将堆顶位置的值(即最大值)与最后一个值交换,然后再将更新后的大根堆进行重新构建,最后会得到一个排好序的数组。具体参考堆的构建及堆排序(C++)
def sortmy(arr, n):
for i in range(int(n / 2 - 1), -1, -1):
heapAdjust(arr, i, n - 1)
while n - 1:
arr[0], arr[n - 1] = arr[n - 1], arr[0]
n -= 1
heapAdjust(arr, 0, n - 1)
def heapAdjust(arr, low, high):
"""
构建大根堆
:param arr:
:param low:
:param high:
:return:
"""
rc = arr[low] # 头节点
i = low * 2 + 1 # 左孩子
while i <= high:
if i < high: # 不是最后一个节点
if arr[i] < arr[i + 1]: # 左孩子比右孩子小
i += 1
if rc > arr[i]: # 头节点大于孩子节点就不操作
break
arr[low] = arr[i] # 否则将较大的孩子节点赋值给头节点
low = i # 开始将这个较大节点作为新头节点继续遍历
i = 2 * i + 1
arr[low] = rc # 循环执行完毕需要将一开始的头节点赋值给循环中的新头节点
arr = list(map(int, input().split()))
sortmy(arr, len(arr))
print(arr)
4、归并排序
分而治之,核心是将两个有序数组组合成一个有序数组,即下面的归并过程代码
import copy
import random
def merge(arr, start, mid, end):
"""
归并过程
:param arr:
:param start:
:param end:
:return:
"""
res = copy.deepcopy(arr)
Mid = mid
for idx in range(start, end + 1):
if start > Mid: # 左分支已遍历完
arr[idx] = res[mid + 1]
mid += 1
elif mid == end: # 右分支已遍历完
arr[idx] = res[start]
start += 1
elif res[start] <= res[mid + 1]: # 左分支的值小于右分支
arr[idx] = res[start]
start += 1
else:
arr[idx] = res[mid + 1] # 左分支的值大于右分支
mid += 1
def merge_sort(arr, start, end):
"""
归并排序递归函数
:param arr:
:param start:
:param end:
:return:
"""
if end == start:
return
mid = int((start + end) / 2)
merge_sort(arr, start, mid)
merge_sort(arr, mid + 1, end)
merge(arr, start, mid, end)
a = random.sample(range(100), 100)
print(a)
merge_sort(a, 0, len(a) - 1)
print(a)
5、选择排序
挺垃圾的一种排序方法,还不如冒泡
import random
def select_sort(arr, n):
"""
选择排序
:param arr:
:return:
"""
for i in range(n):
minIdx = i
for j in range(i, n):
if arr[j] < arr[minIdx]:
minIdx = j
if minIdx != i:
arr[i], arr[minIdx] = arr[minIdx], arr[i]
a = random.sample(range(100), 100)
print(a)
select_sort(a, len(a))
print(a)
6、插入排序
时间复杂度也挺高,但是代码实现起来设计巧妙如下,循环遍历数组,将未排序的数一个个插入到前面已排好序的数组中,未申请额外空间
import random
def insert_sort(arr, n):
"""
插入排序
:param arr:
:param n:
:return:
"""
for i in range(1, n):
for j in range(i - 1, -1, -1):
if arr[j+1] < arr[j]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
a = random.sample(range(100), 100)
print(a)
insert_sort(a, len(a))
print(a)
7、希尔排序
插入排序的改进版,设计的非常巧妙,也可以说插入排序是特殊情况的希尔排序,即gap设为1时,两者就是一样的。只不过shell由小及大,通过设置不同的增量(这里的增量是[n/2, n/2/2, ..., 1],也可以设为其他)来实现最终的排序。
import random
def shell_sort(arr, n):
"""
希尔排序
:param arr:
:param n:
:return:
"""
gap = int(n / 2)
while gap:
for i in range(gap, n):
for j in range(i - gap, -1, -gap):
if arr[j] > arr[j + gap]:
arr[j], arr[j + gap] = arr[j + gap], arr[j]
gap = int(gap / 2)
a = random.sample(range(100), 100)
print(a)
shell_sort(a, len(a))
print(a)