经典排序算法的Python实现


最近准备面试,复习了一下排序算法,并且用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]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值