【Python】List 二级归并排序(不使用sorted)

做了一道跟二级排序相关的笔试题,不用sorted函数,手撸Python归并排序,一直忙着做项目学习,撸了很久才出来,最后被参数传递坑了一道,太菜了我~~~
怀念C++,参数传递很清晰,想传值传引用都是自己说了算。我用Python在赋值、传参、返回值的时候,总是忍不住去想,这个赋值、参数或者返回是不是又开辟空间了?我的原变量会不会被修改掉?我要不要传引用?怎么节省内存?毕竟是以前写C++留下来的病。

言归正传。

问题描述

给出一个n*m列表,先按第二列进行升序排序,第二列值相同的,按第一列的值进行升序排序。

输入:

[[4, 88], [1, 33], [2, 88], [5, 43], [1, 68], [4, 22], [3, 22], [5, 41], [4, 42], [2, 22]]

输出:

[[2, 22], [3, 22], [4, 22], [1, 33], [5, 41], [4, 42], [5, 43], [1, 68], [2, 88], [4, 88]]

输入:

[[4, 88, 999], [1, 33, 199], [2, 88, 111], [5, 43, 123], [1, 68, 144], [4, 22, 232], [3, 22, 566], [5, 41, 0], [4, 42, 234], [2, 22, 555]]

输出:

[[2, 22, 555], [3, 22, 566], [4, 22, 232], [1, 33, 199], [5, 41, 0], [4, 42, 234], [5, 43, 123], [1, 68, 144], [2, 88, 111], [4, 88, 999]]

Python的sorted函数

if __name__ == '__main__':
    l = [[4, 88], [1, 33], [2, 88], [5, 43], [1, 68], [4, 22],  [3, 22], [5, 41], [4, 42], [2, 22]]
    l1 = [[4, 88, 999], [1, 33, 199], [2, 88, 111], [5, 43, 123], [1, 68, 144], [4, 22, 232], [3, 22, 566], [5, 41, 0], [4, 42, 234], [2, 22, 555]]

    print(sorted(l, key=lambda x: (x[1], x[0]), reverse=False))
    print(sorted(l1, key=lambda x: (x[1], x[0]), reverse=False))

无返回值的归并排序代码:

def merge_sort(l):
    length = len(l)
    if length <= 1:
        return

    p = int(length / 2)
    l1 = l[:p]
    l2 = l[p:]
    merge_sort(l1)  # 前半段会排序
    merge_sort(l2)  # 后半段也会排序
    merge(l1, l2, l)    # 传入排序后的前后半段,并合并

    # 这种方法是错误的,思考为什么?
    # merge_sort(l[:p])     # 切片返回的是一个新对象
    # merge_sort(l[p:])
    # merge(l[:p], l[p:], l)    # 错误在于,又传递新对象,前半段未改变,后半段也未改变,合并的时候还是无序的


def merge(l1, l2, l):
    len_l1, len_l2 = len(l1), len(l2)

    i = j = 0
    while i != len_l1 and j != len_l2:
        # 此处是排序规则,按第二位升序,若第二位相同,按第一位升序
        if l1[i][1] < l2[j][1] or (l1[i][1] == l2[j][1] and l1[i][0] <= l2[j][0]):
            l[i+j] = l1[i]
            i += 1
        else:
            l[i+j] = l2[j]
            j += 1

    # 剩余元素
    while i != len_l1:
        l[i+j] = l1[i]
        i += 1

    while j != len_l2:
        l[i+j] = l2[j]
        j += 1

if __name__ == '__main__':
    l = [[4, 88], [1, 33], [2, 88], [5, 43], [1, 68], [4, 22],  [3, 22], [5, 41], [4, 42], [2, 22]]
    merge_sort(l)
    print(l)
    l1 = [[4, 88, 999], [1, 33, 199], [2, 88, 111], [5, 43, 123], [1, 68, 144], [4, 22, 232], [3, 22, 566], [5, 41, 0], [4, 42, 234], [2, 22, 555]]
    merge_sort(l1)
    print(l1)

有返回值的归并排序

def merge_sort(l):
    length = len(l)
    if length <= 1:
        return l

    p = length // 2
    l1 = l[:p]
    l2 = l[p:]
    left = merge_sort(l1)
    right = merge_sort(l2)
    res = merge(left, right)
    return res


def merge(l1, l2):
    len_l1 = len(l1)
    len_l2 = len(l2)

    l = []
    i = j = 0
    while i != len_l1 and j != len_l2:
        if l1[i][1] < l2[j][1] or (l1[i][1] == l2[j][1] and l1[i][0] <= l2[j][0]):
            l.append(l1[i])
            i += 1
        else:
            l.append(l2[j])
            j += 1

    while i != len_l1:
        l.append(l1[i])
        i += 1

    while j != len_l2:
        l.append(l2[j])
        j += 1

    return l

if __name__ == '__main__':
    l = [[4, 88], [1, 33], [2, 88], [5, 43], [1, 68], [4, 22],  [3, 22], [5, 41], [4, 42], [2, 22]]
    l1 = [[4, 88, 999], [1, 33, 199], [2, 88, 111], [5, 43, 123], [1, 68, 144], [4, 22, 232], [3, 22, 566], [5, 41, 0], [4, 42, 234], [2, 22, 555]]

    # print(sorted(l, key=lambda x: (x[1], x[0]), reverse=False))
    print(merge_sort(l))
    # print(sorted(l1, key=lambda x: (x[1], x[0]), reverse=False))
    print(merge_sort(l1))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值