最近准备面试,复习了一下排序算法,并且用Python实现了一遍,在这里记录一下。
1,插入排序
# 插入排序
def insert_sort(s):
#从第二个数字开始,将每个数字插入到前面的已排序数组中
for i in range(1,len(s) - 1):
j = i-1
if s[i] < s[j]:
temp = s[i]
#依次将比s[i]大的数字往后移动
while j >=0 and s[j] >temp:
s[j+1] = s[j]
j -= 1
#把s[i]插入到指定位置
s[j+1] = temp
return s
2,希尔排序
#希尔排序
def shell_sort(s):
#d为增量,为 n/2,n/4,n/8,...,1的序列,其中n为数组s的长度
d= int(len(s) / 2)
while d >= 1:
#根据增量d将数组进行分组,组内进行插入排序,可以参考插入排序
for i in range(d,len(s)):
j = i-d
if s[i] < s[j]:
temp = s[i]
while j >=0 and s[j] > temp:
s[j+d] = s[j]
j -= d
s[j+d] = temp
d = int(d/2)
return s
3,简单选择排序
#简单选择排序
def select_sort(s):
#从前往后依次把当前最小值交换到当前位置
for i in range(len(s)):
pos,_min = i,s[i]
#找出当前最小值
for j in range(i,len(s)):
if s[j] < _min:
pos,_min = j,s[j]
#交换位置
if i != pos:
s[i],s[pos] = s[pos],s[i]
return s
4,堆排序
#堆排序
#堆调整,首先每一个堆都是一个完全二叉树,可以利用数组进行存储。
#由于完全二叉树以及数组存储性质我们可知,对于一个长度为n的数组s:
# 1,注意我们这里数组的下标为[1,n-1]。
# 1,下标为0~int(n/2)的节点为非叶子节点,下标为int(n/2)~n-1的节点为叶子节点。
# 2,对于任意一个非叶子节点i,i*2+1为i的左子树,i*2+2为i的右子树,这里请参考第一点。
# 堆调整的过程为:
# 1,对于一个非叶子节点,首先比较左右子树值的大小(若右子树存在),然后在比较子树最大值与根节点的大小,将三者最大值挪到根节点。
# 2,若将左节点(右节点同理)与根节点互换则以左子树为根节点递归进行堆调整,直到叶子节点。
# 3,依次调整所有的非叶子节点。
def heapAdjust(s, i, length):
#i为根节点,k为左子树,k+1为右子树
temp,k = s[i],i*2+1
while k < length:
if k+1 < length and s[k] < s[k+1]:
k += 1
if s[k] > temp:
s[i] = s[k]
#若调整,则递归往下调整
i=k
else:
break
#更新左子树
k = k*2+1
#将最开始根节点赋给当前节点
s[i] = temp
def heap_sort(s):
#3,依次调整所有的非叶子节点。
for i in range(int(len(s)/2)-1,-1,-1):
heapAdjust(s,i,len(s));
#将根节点的值(最大值)与最后一个值互换,这时根节点为最小值,其他节点有序,只调整根节点。
for i in range(len(s)-1,0,-1):
s[i],s[0] = s[0], s[i]
heapAdjust(s,0,i);
return s
5,冒泡排序
#冒泡排序
def bubble_sort(s):
for i in range(len(s)):
for j in range(i,len(s)):
if s[i] > s[j]:
s[i],s[j] = s[j],s[i]
return s
6,快速排序
# 快速排序
def quick_sort(s,left,right):
if left >= right:
return
i, j = left, right
#首先保留基准
temp = s[i]
while i < j:
#这时候i为基准,当j大于基准的时候则跳过,直到遇到第一个小于基准的值
while i < j and s[j] >= temp:
j -= 1
#将违反者置换到上一个基准值所在的位置
s[i] = s[j]
#这时候j为基准,当i大于基准的时候则跳过,直到遇到第一个大于基准的值
while i < j and s[i] <= temp:
i += 1
#将违反者置换到上一个基准值所在的位置
s[j] = s[i]
#直到所有的违反者都调整完毕,则将基准值放在最中间的位置,也就是最后一个违反者的位置。
s[i] = temp
#递归调用
quick_sort(s,left,i-1)
quick_sort(s,j+1,right)
return s
7,归并排序
# 归并排序
# 两个有序序列合并排序
def merge(a,b):
c = []
i,j = 0,0
while(i <len(a) and j < len(b)):
if a[i] < b[j]:
c.append(a[i])
i += 1
else:
c.append(b[j])
j += 1
if i == len(a):
c += b[j:]
return c
if j == len(b):
c += a[i:]
return c
def merge_sort(c):
#当序列一分为二到最后只含有一个值或没有值,则已经是一个有序序列,直接返回即可
if len(c) <= 1:
return c
mid = int(len(c)/2)
#将序列一分为二,分别进行排序
left = merge_sort(c[:mid])
right = merge_sort(c[mid:])
#利用合并排序合并左右两个有序序列
return merge(left,right)
8,插入排序
#基数排序
#获取数字指定位置的数字,若位数不够则返回0,key_num为最大位数。
def getNumByPos(num,pos,key_num):
_str = str(num)
_str = '0'*(key_num-len(_str)) + _str
return int(_str[pos])
#获取一个数组中最大数字的位数
def getKeyNum(s):
maxNum = s[0]
for i in s[1:]:
maxNum = maxNum if maxNum > i else i
return len(str(maxNum))
def radix_sort(s):
radix_10 = 10
key_num = getKeyNum(s)
#十个‘桶’
radix_array = [[] for i in range(radix_10)]
#个十百千万...,依次比较每一个位置
for pos in range(key_num-1,-1,-1):
for i in s:
num = getNumByPos(i,pos,key_num)
#根据指定位置上的数字,将数组分到十个桶里
radix_array[num].append(i)
s = []
for i in radix_array:
s += i
#按照数字大小将桶合并
radix_array = [[] for i in range(radix_10)]
return s
9,测试代码
sort_funcs = ['insert_sort','shell_sort','select_sort','heap_sort','bubble_sort','quick_sort','merge_sort','radix_sort']
sort_names = ['插入排序','希尔排序','简单选择排序','堆排序','冒泡排序','快速排序','归并排序','基数排序']
s= [612,123,334,545,756,967,278,489,890,1001]
print('排序前:')
print(s)
for func,name in zip(sort_funcs,sort_names):
s= [612,123,334,545,756,967,278,489,890,1001]
print(name,':')
if func == 'quick_sort':
print(globals().get(func)(s,0,len(s)-1))
else:
print(globals().get(func)(s))
10,运行结果
排序前:
[612, 123, 334, 545, 756, 967, 278, 489, 890, 1001]
插入排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]
希尔排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]
简单选择排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]
堆排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]
冒泡排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]
快速排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]
归并排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]
基数排序 :
[123, 278, 334, 489, 545, 612, 756, 890, 967, 1001]