在一些技术面中,有些面试官会让我们手写一些排序算法的实现,为了巩固大家的算法实现能力,在这里使用python编写五种基本的排序算法:冒泡排序,选择排序,插入排序,希尔排序,快速排序。希望能帮到大家:
冒泡排序(Bubble Sort)作为一种最简单的排序算法,其平均时间复杂度为O(n^2).就像英语单词Abandon一样,一说到排序算法,首先映入眼帘的就是冒泡算法 。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,此时说明数列已经排序完成。这个算法的名字的由来就是因为越小的元素会经由交换慢慢“浮”到数列的顶端,跟水下的冒泡泡一样。
算法步骤
比较相邻的元素。如果第一个比第二个大,就交换他们两者的位置。
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
针对所有的元素重复以上的步骤,直到没有任何一对数字需要比较。
Python实现
my_list = [3,5,38,15,36,26,27,2,38,4,19,44,46,50,48] #待排序数列
def BubbleSort(my_list):
length = len(my_list)
for i in range(1,length):
for j in range(0,length-1):
if my_list[j] > my_list[j+1]: #每次只比较两个数的大小
my_list[j],my_list[j+1] = my_list[j+1],my_list[j]
return my_list
print(BubbleSort(my_list))
#[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 48, 50]
选择排序(Selection Sort)也是一种简单直观的排序算法,其平均时间复杂度为O(n^2)。唯一的好处算是不占用额外的内存空间。
算法步骤
1、首先在未排序序列中找到最小(大)元素,存放到排序序列的起始(末尾)位置;
2、再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾;
3、重复第二步,直到所有元素均排序完毕。
Python实现
my_list = [3,5,38,15,36,26,27,2,38,4,19,44,46,50,48] #待排序数列
def SelectionSort(my_list):
length = len(my_list)
for i in range(0,length-1):
#默认设置最小值得index为当前值
minIndex = i
#用当先最小index的值分别与后面的值进行比较,以便获取最小index
for j in range(i+1,length):
#如果找到比当前值小的index,则进行两值交换
if my_list[j] < my_list[minIndex]:
tmp = my_list[j]
my_list[j] = my_list[minIndex]
my_list[minIndex]=tmp
#打印每一轮比较好的列表
print("Round ",i,": ",my_list)
print(SelectionSort(my_list))
#结果如下所示:
Round 0 : [2, 5, 38, 15, 36, 26, 27, 3, 38, 4, 19, 44, 46, 50, 48]
Round 1 : [2, 3, 38, 15, 36, 26, 27, 5, 38, 4, 19, 44, 46, 50, 48]
Round 2 : [2, 3, 4, 38, 36, 26, 27, 15, 38, 5, 19, 44, 46, 50, 48]
Round 3 : [2, 3, 4, 5, 38, 36, 27, 26, 38, 15, 19, 44, 46, 50, 48]
Round 4 : [2, 3, 4, 5, 15, 38, 36, 27, 38, 26, 19, 44, 46, 50, 48]
Round 5 : [2, 3, 4, 5, 15, 19, 38, 36, 38, 27, 26, 44, 46, 50, 48]
Round 6 : [2, 3, 4, 5, 15, 19, 26, 38, 38, 36, 27, 44, 46, 50, 48]
Round 7 : [2, 3, 4, 5, 15, 19, 26, 27, 38, 38, 36, 44, 46, 50, 48]
Round 8 : [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 50, 48]
Round 9 : [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 50, 48]
Round 10 : [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 50, 48]
Round 11 : [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 50, 48]
Round 12 : [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 50, 48]
Round 13 : [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 48, 50]
None
[Finished in 0.4s]
插入排序(Insertion Sort)也是一种简单直观的排序算法。 其通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。其时间复杂度为O(n^2)。该算法的好处是稳定。
算法步骤
先将前两个排序
再将前三个排序
前四个
…
一直到最末尾
Python实现
my_list = [3,5,38,15,36,26,27,2,38,4,19,44,46,50,48] #待排序数列
def InsertSort(arr):
length = len(arr)
for i in range(1,length):
x = arr[i]
for j in range(i,-1,-1):
# j为当前位置,试探j-1位置
if x < arr[j-1]:
arr[j] = arr[j-1]
else:
# 位置确定为j
break
arr[j] = x
print(InsertSort(my_list))
#[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 48, 50]
如果当要排序数列是”5, 4, 3, 2, 1“的时候,此时我们将“无序块”中的记录插入到“有序块”时,emmm…效率可想而知,因为插入排序每次只能将数据移动一位。而希尔(Shell)于1959年根据这个弱点进行了算法改进,融入了一种叫做“缩小增量排序法”的思想。其时间复杂度为O(n logn)
算法步骤
1、选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;
2、按增量序列个数 k,对序列进行 k 趟排序;
3、每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
Python实现
my_list = [3,5,38,15,36,26,27,2,38,4,19,44,46,50,48] #待排序数列
def ShellSort(my_list):
import math
length = len(my_list)
gap = 1
while(gap < length/3):
gap = gap*3 + 1
while gap > 0:
for i in range(gap,length):
temp = my_list[i]
j = i-gap
while j >= 0 and my_list[j] > temp:
my_list[j+gap] = my_list[j]
j -= gap
my_list[j+gap] = temp
gap = math.floor(gap/3)
return my_list
print(ShellSort(my_list))
#[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 48, 50]
快速排序是由东尼·霍尔所发展的一种排序算法。听到这个名字,就很简单粗暴,它存在的意义就是快,效率高!快速排序是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。其时间复杂度为O(n logn)
算法步骤
1、从数列中挑出一个元素,称为 “基准”;
2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序;
Python实现
my_list = [3,5,38,15,36,26,27,2,38,4,19,44,46,50,48] #待排序数列
def QuickSort(my_list, left=0, right=None):
#isinstance 是用来判断一个对象的变量类型
if not isinstance(right,(int,float)):
right = len(my_list)-1
else:
right = right
if left < right:
partition_Index = partition(my_list, left, right) #获取“基准”值的下标值
QuickSort(my_list, left, partition_Index-1)
QuickSort(my_list, partition_Index+1, right)
return my_list
def partition(my_list, low, high):
key = low
index = key+1
i = index
while i <= high:
if my_list[i] < my_list[key]: #如果后面的数小于前面的数,则调换位置
swap(my_list,i,index)
index += 1
i += 1
swap(my_list, key, index-1)
return index-1
def swap(arr, i, j):
arr[i], arr[j] = arr[j], arr[i]
print(QuickSort(my_list))
#[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 38, 44, 46, 48, 50]