用python实现经典排序算法
01 冒泡排序
时间复杂度:O(n^2)
算法描述:
比较相邻的元素,如果第一个比第二个大,就交换它们两个;对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;针对所有的元素重复以上的步骤,除了最后一个;重复上述步骤,直到排序完成。
算法实现:
def bubbleSort(alist):
n = len(alist)
for j in range(n - 1):
count = 0
for i in range(n - 1 - j):
if alist[i] > alist[i + 1]:
alist[i], alist[i + 1] = alist[i + 1], alist[i]
count += 1
if count == 0:
break
return alist
02 选择排序
时间复杂度:O(n^2)
算法描述:
首先从未排序的序列中找到最小(大)的元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
算法实现:
def selectSort(alist):
n = len(alist)
for i in range(n):
for j in range(i + 1, n):
if alist[i] > alist[j]:
alist[i], alist[j] = alist[j], alist[i]
return alist
03 插入排序
时间复杂度:O(n^2)
算法描述:
原理是通过构建有序序列,对于未排序数据,在已排序序列中从后往前扫描,找到相应位置并插入。
核心在于把一个无序序列看成两个数列,如第一个元素构成了第一个数列,那剩余元素构成第二个数列,显然第一个数列是有序的(只有一个元素),把第二个数列中的第一个元素拿出来插到第一个数列,使它构成一个有序数列,直到第二个数列中的元素全部插入到第一个数列。
将待插入元素与前一个元素进行比较,若小于,则将前一个元素后移一位,再跟前前一位进行比较,直到遇到小于待插入元素,插入到该位后一位。
算法实现:
def insertSort(alist):
n = len(alist)
for j in range(1, n):
i = j
while i > 0:
if alist[i] < alist[i - 1]:
alist[i], alist[i - 1] = alist[i - 1], alist[i]
i -= 1
else:
break
return alist
04 希尔排序(缩小增量排序)
时间复杂度:O(n^1.3)
算法描述:
是插入排序的优化版,当数据规模较小或数据已基本有序时非常有效。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序,随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法终止。
算法实现:
def shellSort(alist):
n = len(alist)
t = n // 2
while t > 0:
for i in range(t, n):
j, cur = i, alist[i]
while (j - t >= 0) and (cur < alist[j - t]):
alist[j] = alist[j - t]
j = j - t
alist[j] = cur
t = t // 2
return alist
05 归并排序
时间复杂度:O(nlogn)
算法描述:
先按组拆,拆到都剩单独一个数据为止,再按照拆分的顺序进行合并,小的在前,大的在后,使用左右两个游标进行比较。
分析时间复杂度:因为涉及递归所以不通过代码来看。横向为n次,纵向是除二除二,也就是logn,最坏最好都是nlogn,需要额外空间复杂度。
稳定性:代码中可保证稳定。
算法实现:
def mergeSort(alist):
n = len(alist)
if n <= 1:
return alist
mid = n // 2 #求得列表中间位置
#对左边列表进行归并排序
left_list = mergeSort(alist[:mid])
#对右边列表进行归并排序
right_list = mergeSort(alist[mid:])
#将两个有序的子序列进行合并
right_pointer = 0, 0
result = []
while left_pointer < len(left_list) and right_pointer < len(right_list):
if left_list[left_pointer] < right_list[right_pointer]:
result.append(left_list[left_pointer])
left_pointer += 1
else:
result.append(right_list[right_pointer])
right_pointer += 1
#走到头之后,将剩下的部分直接添加上
result += left_list[left_pointer:]
result += right_list[right_pointer:]
return result
06 快速排序
时间复杂度:O(nlogn)
算法描述:
通过一趟排序将待排记录分隔成独立的两部分,一部分记录的关键字比另一部分的关键字小,则可分别对这两部分继续进行排序,代价是需要额外的内存空间。
算法实现:
def quickSort(alist, first, last):
if first >= last:
return
mid_value = alist[first]
low = first
high = last
while low < high:
#high左移
while low < high and alist[high] >= mid_value:
high -= 1
alist[low] = alist[high]
while low < high and alist[low] < mid_value:
low += 1
alist[high] = alist[low]
#从循环退出时,low=high
alist[low] = mid_value
#对low左边的列表执行快速排序
quickSort(alist, first, low - 1)
#对low右边的列表执行快速排序
quickSort(alist, low + 1, last)
完结。
能力有限,所以我就学习了以上六种排序算法。面试中遇到过冒泡、归并和快排的手写代码考察。笔试中好像堆排序会经常考察,然而我是真的没学会。你们可不要学我,想进一步学习的可以参考这里(https://b23.tv/yj3k6y)的方法讲述。
友情提示:百分之八九十的数分笔试都会手撕算法coding(数据结构),这方面能力欠缺的同学建议多练习,多思考,别学我。或者抓住提前批(一些公司没有笔试)的机会,还有某些厂笔试不考手撕算法的机会。