排序(插入、冒泡、选择、归并、快排) + 二分查找 实现

# 排序算法的稳定与否决定于 会不会破坏原先序列里的相对顺序

# 排序
test = [1, 6, 8, 4, 7, 9, 3]
test_rep = [1, 3, 1, 9, 6, 1, 8, 5, 5]
print(test)


# 冒泡 时间复杂度 n**2 冒泡排序是比较排序,通过比较来排序,是稳定的排序算法
# 平均情况O(n2),最好情况O(n),最坏情况O(n2)
def bubble_sort(lst):
    while True:
        n = 0
        for i in range(len(lst) - 1):
            if lst[i] > lst[i + 1]:
                lst[i], lst[i + 1] = lst[i + 1], lst[i]
                n += 1
        if not n:
            print(lst)
            return lst


# 选择排序 ,找出最小的放在第一个,再找出第二小的放在第二个,排序极其不稳定,在n比较小的时候比冒泡快,因为交换使用的少。(比较比交换元素更耗费cpu)
def select_sort(lst):  # 可以实现原地改,也可以新建一个列表里插入
    for i in range(len(lst)):
        a = lst[i:]
        mini, posi = a[0], 0
        for j in range(len(a)):
            if a[j] < mini:
                mini, posi = a[j], j
        if lst[i] > mini:
            lst[i], lst[i + posi] = lst[i + posi], lst[i]
    print(lst)
    return lst


# 插入排序,创建个空列表,每次选一个元素放到这个已排序的列表里。
def insert_sort(lst):
    l = [lst[0]]
    for i in range(1, len(lst)):
        for j in range(len(l)):
            try:
                if lst[i] >= l[j] and lst[i] < l[j + 1]:
                    l.insert(j + 1, lst[i])
                    break
            except:  # 假如出现了数组越界的问题,说明已经到最后尾部了,直接插入就行
                l.insert(j + 1, lst[i])
                break
    print(l)
    return l


# 快排:随机选择一个基准值,然后小的放左边,大的放右边,对所有子序列执行相同步骤。
# 注意等值的中点会使得快排进入无限循环
# 平均情况O(nlog2n),最好情况O(nlog2n),最坏情况O(n2)
def quick_sort(lst):
    if not lst or len(lst) == 1:
        return lst
    mid = len(lst) // 2
    mid_value = lst[mid]
    big = [x for x in lst if x > mid_value]
    small = [x for x in lst if x < mid_value]
    mid = [x for x in lst if x == mid_value]
    return quick_sort(small) + mid + quick_sort(big)


# 归并:1、拆分单个元素,两两合并有序序列。
def bind(lst1, lst2):
    lst1.extend(lst2)
    return sorted(lst1)

def bind_sort(lst):
    l = [[x] for x in lst]
    while True:
        l2 = []
        for i in range(0, len(l), 2):
            if i < len(l) - 1:
                l2.append(bind(l[i], l[i + 1]))
            else:
                l2.append(l[i])
        l = l2[:]
        if len(l) == 1:
            print(l[0])
            return l[0]


# 堆排:1、首先构建大小顶堆。大顶堆表示树结构里所有节点都大于等于左右孩子节点。
def mk_pile(lst):
    if not len(lst):
        return None
    while True:
        n = 0
        for i in range(len(lst)):
            left, right = i * 2 + 1, i * 2 + 2
            l = lst[i * 2 + 1:i * 2 + 3]  # 注意切片前包后不包
            if not l:  # 如果l为空:
                continue
            else:
                if len(l) == 1 and l[0] > lst[i]:  # 只有一个左节点并且节点大于root
                    lst[i], lst[i * 2 + 1] = lst[i * 2 + 1], lst[i]
                    n = 1
                    continue
                if len(l) == 2 and l[0] > l[1] and l[0] > lst[i]:  # 有两个节点 且左子最大,交换
                    lst[i], lst[i * 2 + 1] = lst[i * 2 + 1], lst[i]
                    n = 1
                    continue
                if len(l) == 2 and l[1] > l[0] and l[1] > lst[i]:  # 右节点最大,交换
                    lst[i], lst[i * 2 + 2] = lst[i * 2 + 2], lst[i]
                    n = 1
                    continue
        if n == 0:
            return lst


def pile_sort(lst):
    length = len(lst)
    l = []
    piled = mk_pile(lst)
    for i in range(length):
        l.append(piled[0])
        piled = mk_pile(piled[1:])
        if piled is None:
            print(l)
            return l


# 二分查找
def binary_search(array, num):
    length = len(array)
    mid, head, tail = length // 2, 0, length - 1
    while True:
        if num == array[mid]:
            print('the posi is {}'.format(mid))
            return True
        if head == mid:
            if num != array[tail]:
                print('No such number')
                return False
            else:
                print('the posi is {}'.format(tail))
                return True
        if num > array[mid]:
            print('bi find gt')
            head = mid
            mid = sum((tail, head)) // 2
        if num < array[mid]:
            print('bi find lt')
            tail = mid
            mid = sum((tail, head)) // 2

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值