用python实现经典排序算法

在正经的笔试题中,排序算法基本不会出现,出现的时候也会作为解题环节的一个小部分。不过,在面试中可能会遇到,毕竟作为数据分析师,难点的可能考你手推公式,简单的可能就说:“来,那你写个快排吧。”

来,那我就奉上我之前使用的部分排序算法的python实现吧,毕竟我是正经算法coding基本撕不出来的人,只能在这种简单算法上使点劲了。

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:])
    #将两个有序的子序列进行合并
    left_pointer, 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(数据结构),这方面能力欠缺的同学建议多练习,多思考,别学我。或者抓住提前批(一些公司没有笔试)的机会,还有某些厂笔试不考手撕算法的机会。

再挂一下之前的推文:

估算下北京有多少个加油站?

2020互联网数分求职面经

拼多多2020届数据分析面试题合集(上)

拼多多2020届数据分析面试题合集(下)

扫码关注吧

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值