可视化
a = [5, 3, 4, 1, 2, 2]
冒泡排序
def bubble(a):
"""
冒泡排序 时间复杂度o(n2)
比较相邻的元素大小,将小的前移,大的后移
:param a:list
:return: sorted(a)
"""
num = 0
for i in range(len(a) - 1):
for j in range(len(a) - i - 1):
if a[j] > a[j + 1]:
a[j], a[j + 1] = a[j + 1], a[j]
print(' %s和 %s互换位置, %s -->> %s ' % (a[j], a[j + 1], a[j], a[j + 1]))
num += 1
print('移动次数: %s 次' % num)
print(a)
return a
选择排序
def selection_sort(a):
"""
选择排序 时间复杂度o(n2)
第1趟,在待排序记录r1 ~ r[n]中选出最小的记录,
将它与r1交换;第2趟,在待排序记录r2 ~ r[n]中选出最小的记录,
将它与r2交换;以此类推,第i趟在待排序记录r[i] ~ r[n]中选出最小的记录
:param a: list
:return: sorted(a)
"""
num = 0
for i in range(len(a) - 1):
min = i
for j in range(i + 1, len(a)):
if a[min] > a[j]:
min = j
if min != i:
a[i], a[min] = a[min], a[i]
print(' %s和 %s互换位置, %s -->> %s ' % (a[i], a[min], a[i], a[min]))
num += 1
print('移动次数: %s 次' % num)
print(a)
return a
插入排序
def insert_sort(a):
"""
插入排序 时间复杂度 o(n2)
插入排序:插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,
从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序;
首先将第一个作为已经排好序的,
然后每次从后的取出插入到前面并排序;
:param a:list
:return:sorted(a)
"""
for i in range(len(a)):
for j in range(i):
if a[i] < a[j]:
a.insert(j, a.pop(i))
break
print(a)
return a
希尔排序
def shell_sort(a):
"""
希尔排序 时间复杂度 o(nlogn) or o(n^(1.3—2))
希尔排序是把记录按下标的一定增量分组,
对每组使用直接插入排序算法排序;
随着增量逐渐减少,每组包含的关键词越来越多,
当增量减至1时,整个文件恰被分成一组,算法便终止
:param a:list
:return:sorted(a)
"""
num = 0
gap = len(a)
while gap > 1:
gap = gap // 2 # 取商
for i in range(gap, len(a)):
for j in range(i % gap, i, gap):
if a[i] < a[j]:
a[i], a[j] = a[j], a[i]
print(' %s和 %s互换位置, %s -->> %s ' % (a[i], a[j], a[i], a[j]))
num += 1
print('移动次数: %s 次' % num)
print(a)
return a
快速排序
def quick_sort(a):
"""
快速排序 时间复复杂度nlogn
通过一趟排序将要排序的数据分割成独立的两部分,
其中一部分的所有数据都比另外一部分的所有数据都要小,
然后再按此方法对这两部分数据分别进行快速排序,
整个排序过程可以递归进行,
以此达到整个数据变成有序序列
:param a:list
:return:sorted(a)
"""
if a == []:
return a
else:
a_first = a[0]
a_less = quick_sort([i for i in a[1:] if i <= a_first])
a_more = quick_sort([j for j in a[1:] if j > a_first])
result = a_less + [a_first] + a_more
return result
堆排序
def heap_sort(a):
"""
堆排序 时间复杂度 nlogn
选择排序的一种,可以利用数组的特点快速定位指定索引的元素。
堆分为大根堆和小根堆,是完全二叉树
大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。
在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,
最大的值一定在堆顶
:param a:list
:return:sort(a)
"""
import copy
def heap_adjust(parent):
child = 2 * parent + 1 # left child
while child < len(heap):
if child + 1 < len(heap):
if heap[child + 1] > heap[child]:
child += 1 # right child
if heap[parent] >= heap[child]:
break
heap[parent], heap[child] = heap[child], heap[parent]
parent, child = child, 2 * child + 1
heap, hlist = copy.copy(a), []
for i in range(len(heap) // 2, -1, -1):
heap_adjust(i)
while len(heap) != 0:
heap[0], heap[-1] = heap[-1], heap[0]
hlist.insert(0, heap.pop())
heap_adjust(0)
return hlist
基数排序
def radix_sort(a):
"""
基数排序 时间复杂度 o(LOGrB)
透过键值的部份资讯,将要排序的元素分配至某些“桶”中,藉以达到排序的作用
:param a:list
:return:sort(a)
"""
bucket, digit = [[]], 0
while len(bucket[0]) != len(a):
bucket = [[], [], [], [], [], [], [], [], [], []]
for i in range(len(a)):
num = (a[i] // 10 ** digit) % 10
bucket[num].append(a[i])
a.clear()
for i in range(len(bucket)):
a += bucket[i]
digit += 1
return a
归并排序
def merge_sort(a):
"""
归并排序 时间复杂度 nlogn
采用分治法(Divide and Conquer)的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列;
即先使每个子序列有序,再使子序列段间有序。
若将两个有序表合并成一个有序表,称为二路归并
:param a:list
:return:sorted(a)
"""
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 = result + left[i:] + right[j:] # 剩余的元素直接添加到末尾
return result
# 递归过程
if len(a) <= 1:
return a
mid = len(a) // 2
left = merge_sort(a[:mid])
right = merge_sort(a[mid:])
return merge(left, right)
网友评论