各种排序算法
O(n2)
——————————————————————————————
冒泡排序,稳定排序
每一轮都要遍历所有元素,总共遍历(元素数量 - 1)轮
# 冒泡排序,最大的冒泡上去,最后元素最大
def bubble_sort1(array = []):
for i in range(len(array) - 1):
for j in range(len(array) - i - 1):
if array[j] > array[j + 1]:
temp = array[j]
array[j] = array[j + 1]
array[j + 1] = temp
# 冒泡优化,设置标志位
def bubble_sort2(array = []):
for i in range(len(array) - 1):
# 有序标记,每一轮初始值是True
is_sorted = True
for j in range(len(array) - i - 1):
if array[j] > array[j + 1]:
temp = array[j]
array[j] = array[j + 1]
array[j + 1] = temp
# 有元素交换,所以是有序的,标记变为False
is_sorted = False
# 如果发现标志位没有变为False,意思是没有交换,已经有序,则直接退出
if is_sorted:
break
# 优化3,在每一轮排序后,记录下最后一次元素交换的位置,则该位置即为无序数列的边界,再往后就是有序曲了
def bubble_sort3(array = []):
# 记录最后一次交换的位置
last_exchange_index = 0
# 无序数列的边界,每次比较只需比到这里
sort_border = len(array) - 1
for i in range(len(array) - 1):
# 有序标记,每一轮的初始是True
is_sorted = True
for j in range(sort_border):
if array[j] > array[j + 1]:
temp = array[j]
array[j] = array[j + 1]
array[j + 1] = temp
# 已经交换,所以变为False
is_sorted = False
# 把无序数列的边界值更新为最后一次交换元素的位置
last_exchange_index = j
sort_border = last_exchange_index
if is_sorted:
break
my_array = list([3,5,7,2,3,44,5,0])
bubble_sort1(my_array)
print(my_array) #[0, 2, 3, 3, 5, 5, 7, 44]
选择排序
插入排序
O(nlogn)
——————————————————————————————
快速排序
找基准元素,partition
递归基准元素左边的,递归右边的
# 得到基准元素
pivot_index = partition1(start_index, end_index, array)
# 根据基准元素,分成俩部分递归排序
quick_sort(start_index, pivot_index - 1, array)
quick_sort(pivot_index + 1, end_index, array)
code
# 快排算法
# 双边循环法实现的快排
def quick_sort(start_index, end_index, array = []):
# 递归结束的条件
if start_index >= end_index:
return
# 得到基准元素
pivot_index = partition1(start_index, end_index, array)
# 根据基准元素,分成俩部分递归排序
quick_sort(start_index, pivot_index - 1, array)
quick_sort(pivot_index + 1, end_index, array)
def partition1(start_index, end_index, array = []):
# 取第一个位置的元素为基准元素
pivot = array[start_index]
left = start_index
right = end_index
while left != right:
# 控制rigth 右指针进行比较并左移
while left < right and array[right] > pivot:
right -= 1
# 控制left 左指针进行比较并右移
while left < right and array[left] <= pivot:
left += 1
# 交换left 指针和right 指针所指向的元素
temp = array[left]
array[left] = array[right]
array[right] = temp
# pivot和指针重合点交换
array[start_index] = array[left]
array[left] = pivot
return left
# 单边循环法
def partition2(start_index, end_index, array= []):
pivot = array[start_index]
# mark指针指向数列起始位置,这个mark指向代表小于基准元素的区域边界
mark = start_index
for i in range(start_index + 1, end_index + 1):
if array[i] < pivot:
mark += 1
temp = array[mark]
array[mark] = array[i]
array[i] = temp
# 循环结束后,mark 和pivot 交换
array[start_index] = array[mark]
array[mark] = pivot
return mark
my_array = list([3,4,14,1,5,6,7,8,-1,11])
quick_sort(0, len(my_array) - 1, my_array)
print(my_array)
归并排序
堆排序
1.把无序数组构建成最大堆
2.循环交换集合尾部元素到堆顶,并调节堆产生新的堆顶
注意,此时排序出的结果是从小到大,如果想从大到小,只需改变函数down_adjust1里面的while 循环里面的俩个if语句,使之构建的是大根堆。
"""
堆排序
1.把无序数组构建成最大堆
2.循环交换集合尾部元素到堆顶,并调节堆产生新的堆顶
"""
def heap_sort(array = []):
# 1.把无序数组构建成最大堆
for i in range((len(array) - 2) // 2, -1, -1):
down_adjust1(i, len(array), array)
# 2.循环交换集合尾部元素到堆顶,并调节堆产生新的堆顶
for i in range(len(array) - 1, 0 ,-1):
# 最后一个元素和第一个元素交换
temp = array[i]
array[i] = array[0]
array[0] = temp
# 下沉调整最大堆
down_adjust1(0, i, array)
def down_adjust1(parant_index, length, array = []):
temp = array[parant_index] # 保存栈顶元素array[0]
child_index = 2 * parant_index + 1
while child_index < length:
if child_index + 1 < length and array[child_index + 1] > array[child_index]:
child_index += 1
if temp >= array[child_index]:
break
array[parant_index] = array[child_index]
parant_index = child_index
child_index = 2 * parant_index + 1
array[parant_index] = temp
my_array_2 = list([3,5,6,3,2,6,77,-1,6,78])
heap_sort(my_array_2)
print(my_array_2)
计算排序,不基于比较的
“”"
1.得到数列的最大值
2.根据数列最大值确定体积数组的最大值
3.遍历数组,填充统计数组
4.遍历统计数组,输出结果
“”"
优化版:
“”"
1.得到数列的最大值和最小值,并计算出插值d
2.创建统计数组并统计对应元素个数
3.统计数组变形,后面的元素等于前面的元素之和
4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
“”"
原始数列规模n,最大值和最小值差值m,
时间复杂度:O(n+m)
空间复杂度:O(m)
局限性:
1.当数列最大值和最小值差距过大时,并不适合计数排序
2.当数列不是整数时,也不适合计数排序
# 计算排序,不需要比较的排序
"""
1.得到数列的最大值
2.根据数列最大值确定体积数组的最大值
3.遍历数组,填充统计数组
4.遍历统计数组,输出结果
"""
def count_sort(arrey = []):
# 1.得到数列的最大值
max_value = arrey[0]
for i in range(1, len(arrey)):
if max_value < arrey[i]:
max_value = arrey[i]
# 2.根据数列最大值确定统计数组的最大值
count_array = [0] * (max_value + 1)
# 3.遍历数组,填充统计数组
for i in range(0, len(arrey)):
count_array[arrey[i]] += 1
# 4.遍历统计数组,输出结果
ans = []
for i in range(0, len(count_array)):
for j in range(0, count_array[i]):
ans.append(i)
print(ans)
"""
1.得到数列的最大值和最小值,并计算出插值d
2.创建统计数组并统计对应元素个数
3.统计数组变形,后面的元素等于前面的元素之和
4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
"""
def count_sort2(arrey = []):
# 1.得到数列的最大值和最小值,并计算出插值d
max_value = arrey[0]
min_value = arrey[0]
for i in range(1, len(arrey)):
if arrey[i] > max_value:
max_value = arrey[i]
if arrey[i] < min_value:
min_value = arrey[i]
d = max_value - min_value + 1
# 2.创建统计数组并统计对应元素个数
count_array = [0] * d
for i in range(0, len(arrey)):
count_array[arrey[i] - min_value] += 1
# 3.统计数组变形,从第二个元素开始,后面的元素等于前面的元素之和
for i in range(1, len(count_array)):
count_array[i] += count_array[i - 1]
# 4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
ans = [0] * len(arrey)
for i in range(len(arrey) - 1 , -1, -1):
ans[count_array[arrey[i] - min_value] - 1] = arrey[i]
count_array[arrey[i] - min_value] -= 1
return ans
my_array = list([95,94,91,98,99,90,99,99,91,92])
print(count_sort2(my_array))
桶排序
1.得到数列的最大值和最小值,并计算出差值d
2.初始化桶
3.遍历原始数组,将每个元素放入桶中
4.对每个桶内部进行排序
5.输出全部元素
桶区间跨度:(最大值 - 最小值) / (桶的数量 - 1 )
桶的数量 = len(array)
时间复杂度 :O(n)
空间复杂度 :O(n)
# 桶排序
"""
1.得到数列的最大值和最小值,并计算出差值d
2.初始化桶
3.遍历原始数组,将每个元素放入桶中
4.对每个桶内部进行排序
5.输出全部元素
"""
def bucket_sort(array = []):
# 1.得到数列的最大值和最小值,并计算出差值d
max_value = array[0]
min_value = array[0]
for i in range(1, len(array)):
if array[i] > max_value:
max_value = array[i]
if array[i] < min_value:
min_value = array[i]
d = max_value - min_value
# 2.初始化桶
bucket_num = len(array) # 桶的数量等于数组长度
bucket_list = []
for i in range(0, bucket_num):
bucket_list.append([])
# 3.遍历原始数组,将每个元素放入桶中
for i in range(0, len(array)):
# 确定这个数是属于那个编号的桶
num = int((array[i] - min_value) * (bucket_num - 1) / d)
bucket = bucket_list[num] # 拿到大数组中的桶号
bucket.append(array[i]) #再这个桶中添加数字
# 4.对每个桶内部进行排序
for i in range(0, len(bucket_list)):
bucket_list[i].sort()
# 5.输出全部元素
ans = []
# 双循环,sub_list是代表桶和上次循环的bucket 一样
for sub_list in bucket_list:
for i in sub_list:
ans.append(i)
return ans
my_list = list([4.12,0.0045,4,2.34,8.67,45.3])
print(bucket_sort(my_list))