zoukankan      html  css  js  c++  java
  • 算法之排序Low B三人组

    有序区:有的地方的数据已经完全变得有顺序,我们把这部分区域的数据成为有序区
    无序区:有的地方的数据依旧无序,我们把这部分数据成为无序区
    时间复杂度:用来估计算法运行时间的一个式子(单位)
    空间复杂度:用来评估算法内存占用大小的一个式子

    一般来说,时间复杂度高的算法比复杂度低的算法慢。
    常见的时间复杂度(按效率排序)
    O(1)<O(logn)<O(n)<O(nlogn)<O(n2)<O(n2logn)<O(n3)
    不常见的时间复杂度(看看就好)
    O(n!) O(2n) O(nn) …
    
    如何一眼判断时间复杂度?
    循环减半的过程O(logn)
    几次循环就是n的几次方的复杂度

    一、冒泡排序

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    #Author: nulige

    import time
    import functools
    import sys
    import random

    #设置递归限制
    sys.setrecursionlimit(1000000)
    from concurrent import futures

    def run_time(func):
    """为了装饰别的函数,统计函数执行的时间"""
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
    # 开始时间
    start_time = time.time()
    # 调用被装饰的函数
    func(*args,**kwargs)
    # 结束时间
    end_time = time.time()
    # 打印输出,更佳的方法是将其写入到log中
    print("%s函数的执行时间为: %s s" % (func.__name__, end_time - start_time))

    return wrapper

    @run_time #加了装饰器
    def bubble_sort(data_list):
    """
    冒泡排序
    首先拿到第一个元素,和它第二个作比较,看是否交换位置
    第二个再和第三个比较。一轮下来,最后一个就是最大的数
    冒泡都是临近的互相对比找到最大的数据
    :param data_list:
    :return:
    """
    #[6,3,2,7,8,9,5,1,4]
    for i in range(len(data_list)):
    flag = True #做一个标记,看是否在冒泡的过程中发生数据交换
    for j in range(len(data_list)-i-1):
    # [6,3]做对比,换成[3,6] ,然后 [6,2] 做对比......
    if data_list[j] > data_list[j+1]:
    data_list[j], data_list[j+1] = data_list[j+1],data_list[j]
    flag = False
    if flag:
    # 如果没有发生数据交互,那么数据本身就是排好序的
    break

    if __name__ == '__main__':
    a = list(range(100))
    random.shuffle(a) #打乱数字顺序
    print(a)

    bubble_sort(a)
    print(a)

    运行结果:

    [48, 20, 80, 83, 23, 53, 97, 78, 91, 29, 98, 73, 42, 40, 79, 67, 1, 56, 6, 55, 47, 14, 11, 15, 89, 19, 66, 85, 64, 77, 50, 87, 45, 38, 52, 54, 16, 68,
    82, 32, 95, 41, 84, 90, 22, 61, 39, 46, 37, 33, 27, 63, 62, 60, 92, 44, 49, 94, 28, 65, 8, 51, 93, 30, 12, 72, 21, 9, 75, 25, 0, 31, 17, 26, 34, 59,
    81, 7, 3, 24, 99, 36, 57, 88, 18, 74, 76, 10, 2, 35, 58, 5, 70, 69, 86, 13, 96, 4, 71, 43] bubble_sort函数的执行时间为: 0.0010006427764892578 s
    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
    40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77,
    78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] Process finished with exit code 0

    二、选择排序

    #!/usr/bin/env python
    # -*- coding:utf-8 -*- 
    # Author: nulige
    
    import time
    import functools
    import sys
    import random
    
    # 设置递归限制
    sys.setrecursionlimit(1000000)
    from concurrent import futures
    
    
    def run_time(func):
        """为了装饰别的函数,统计函数执行的时间"""
    
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 开始时间
            start_time = time.time()
            # 调用被装饰的函数
            func(*args, **kwargs)
            # 结束时间
            end_time = time.time()
            # 打印输出,更佳的方法是将其写入到log中
            print("%s函数的执行时间为: %s s" % (func.__name__, end_time - start_time))
    
        return wrapper
    
    
    @run_time
    def select_sort(data_list):
        """
         选择排序
         不断找到最大或者最小的
         首先拿到第一个,然后发现比它大的,记住下标,找到最大的和第一个数交换位置
         都是和最大的数据做对比
        :param data_list:
        :return:
        """
        #     # [6,3,2,7,8,9,5,1,4]
        for i in range(len(data_list)):
            # 做一个标记
            flag = True
            # 当前元素无序区的第一个元素是最小的
            min_loc = i
            for j in range(i + 1, len(data_list)):
                # 循环遍历无序区
                if data_list[j] < data_list[min_loc]:
                    # 如果无序区的元素比假定的小,那将该元素标记为最小的
                    min_loc = j
                    flag = False
                    # 循环遍历结束,将无序区的最小元素和第一个元素的位置做一下交换
            if flag:
                continue
            data_list[i], data_list[min_loc] = data_list[min_loc], data_list[i]
    
    
    if __name__ == '__main__':
        a = list(range(100))
        random.shuffle(a)
        print(a)
    
        select_sort(a)
        print(a)

    运行结果:

    [13, 39, 5, 97, 71, 17, 44, 64, 4, 80, 52, 33, 34, 79, 62, 82, 18, 50, 63, 93, 26, 30, 96, 2, 14, 27, 11, 46, 6, 88, 31, 98, 91, 32, 36, 94, 42, 60,
    99, 19, 66, 25, 12, 7, 65, 40, 70, 37, 28, 23, 9, 74, 38, 10, 1, 51, 90, 48, 81, 59, 55, 75, 56, 67, 89, 0, 92, 61, 78, 54, 43, 16, 73, 86, 45, 8,
    83, 15, 85, 21, 95, 29, 41, 53, 3, 76, 69, 84, 35, 24, 22, 72, 58, 47, 68, 57, 77, 87, 20, 49] select_sort函数的执行时间为: 0.0004999637603759766 s [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,

    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
    76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] Process finished with exit code 0

    三、插入排序

    #!/usr/bin/env python
    # -*- coding:utf-8 -*- 
    # Author: nulige
    
    import time
    import functools
    import sys
    import random
    
    # 设置递归限制
    sys.setrecursionlimit(1000000)
    from concurrent import futures
    
    
    def run_time(func):
        """为了装饰别的函数,统计函数执行的时间"""
    
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 开始时间
            start_time = time.time()
            # 调用被装饰的函数
            func(*args, **kwargs)
            # 结束时间
            end_time = time.time()
            # 打印输出,更佳的方法是将其写入到log中
            print("%s函数的执行时间为: %s s" % (func.__name__, end_time - start_time))
    
        return wrapper
    
    @run_time
    def insert_sort(data_list):
        """
        插入排序:有点像抓牌,插牌
        :param data_list: 将数据传递过来
        :return: 返回有序的list
        """
        for i in range(1,len(data_list)):
            # 从第二数据开始
            for j in range(0,i):
                # 它左边的数字都是有序的
                if data_list[i] < data_list[j]:
                    # 如果这数字比左边的某个数字小,则交换这两个数字的位置
                    data_list[i],data_list[j] = data_list[j], data_list[i]
    
    if __name__ == '__main__':
        a = list(range(100))
        random.shuffle(a)
        print(a)
    
        insert_sort(a)
        print(a)

    运行结果:

    [58, 88, 62, 14, 22, 17, 10, 50, 79, 76, 78, 80, 32, 4, 36, 31, 95, 92, 16, 41, 42, 70, 13, 99, 60, 67, 20, 86, 35, 91, 82, 38, 89, 23, 61, 5, 6,
    74, 97, 73, 37, 64, 44, 30, 18, 25, 1, 48, 12, 90, 51, 24, 40, 52, 66, 19, 77, 8, 94, 28, 9, 63, 59, 85, 55, 29, 98, 93, 0, 39, 81, 49, 72, 65,

    26, 46, 7, 21, 3, 2, 71, 69, 43, 11, 53, 96, 68, 54, 75, 27, 87, 84, 34, 57, 83, 56, 45, 15, 47, 33] insert_sort函数的执行时间为: 0.0005004405975341797 s [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
    76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]

    四、快排(提供二种方法)

    #!/usr/bin/env python
    # -*- coding:utf-8 -*- 
    # Author: nulige
    
    import time
    import functools
    import sys
    import random
    import copy
    
    # 设置递归限制
    sys.setrecursionlimit(1000000)
    from concurrent import futures
    
    
    def run_time(func):
        """为了装饰别的函数,统计函数执行的时间"""
    
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 开始时间
            start_time = time.time()
            # 调用被装饰的函数
            func(*args, **kwargs)
            # 结束时间
            end_time = time.time()
            # 打印输出,更佳的方法是将其写入到log中
            print("%s函数的执行时间为: %s s" % (func.__name__, end_time - start_time))
    
        return wrapper
    
    
    @run_time
    def fast_sort_1(data_list):
        """
        快排方法一:
        因为快排包含递归,所以不能直接被装饰,套一层外壳
        :param data_list:
        :return:
        """
        return fast_sort_basic1(data_list)
    
    
    def fast_sort_basic1(data_list):
        """简单的快速排序,消耗内存,空间复杂度略高"""
        if len(data_list) == 0:
            # 如果传过来的数据为[],直接返回
            return []
        else:
            # 把第一个数据拿出来,
            # 比它小的数据放在左边,再次调用本函数                                    +第一个数据      +比它小的数据放在右边,再次调用本函数
            return fast_sort_basic1([i for i in data_list[1:] if i < data_list[0]]) + [data_list[0]] 
          + fast_sort_basic1([i for i in data_list[1:] if i > data_list[0]]) @run_time def fast_sort_2(data_list): """ 快排方法二: 拿到第一个元素,然后整理,直到左边元素比他小,右边元素比他大 整理的过程 :param data_list: :return: """ # 然后结束,把6放在位置上,然后就这个中间的数字的位置就是最终 的位置 fast_sort_basic2(data_list, 0, len(data_list) - 1) def fast_sort_basic2(data, left, right): if left < right: # 调用partiton函数 mid 处为第一个元素应该待的地方 mid = partition(data, left, right) # 对左边的数据继续做快速排序 fast_sort_basic2(data, left, mid - 1) # 对右边的数据继续做快速排序 fast_sort_basic2(data, mid + 1, right) def partition(data, left, right): """ #-------> 小 #大<------- #将数据的左边的第一个数据,数据调整为自己应该待的位置 #[5,2,1,4,3] # 从第一个数字开始,把它放在它应该在的位置,什么叫它应该在的位置,就是左边的数字都比它小,右边的数字都比它大 1、从最右边开始找,找到第一个比它小的数 和 它 交换位置,把第一个数字放到新的位置 2、然后从这个新的位置, 左边开始找比它大的数字,和它大小比较,然后和新的位置交换 3、不断重复,就会使第一个数字出现在它应该出现的位置 #那么这个数字所在的位置就是有序区 """ # 找到左边的第一个数据 tmp = data[left] # 一直循环直到这个数据待在它自己该待的位置 while left < right: # 从右边开始找数据 while data[right] > tmp and left < right: # 找不到,继续往左找 right = right - 1 # 右边找到一个比它小,赶紧交换位置 data[left] = data[right] # 从左边开始找数据 while data[left] < tmp and left < right: # 找不到继续往右找 left = left + 1 # 左边找到一个比它大的赶紧交换位置 data[right] = data[left] # 此时此刻左边和右边完全相同 # 这个数据已经待在它该待的位置 data[left] = tmp return left if __name__ == '__main__': a = list(range(10000)) random.shuffle(a) d = copy.deepcopy(a) e = copy.deepcopy(a) fast_sort_1(d) fast_sort_2(e)

    运行结果:

    fast_sort_1函数的执行时间为: 0.043027639389038086 s
    fast_sort_2函数的执行时间为:
    0.04052925109863281 s
  • 相关阅读:
    基于51单片机数码管显示经ADC0808转化1K电位器分压5V模拟量为数字量的项目工程
    基于51单片机数码管显示经ADC0808转化1K电位器分压5V模拟量为0V-5V数字量的项目工程
    浅谈移动端过长文本溢出显示省略号的实现方案
    浅谈自动化测试
    Tomcat 优雅关闭之路
    InnoDB 事务加锁分析
    Tomcat 9.0.26 高并发场景下DeadLock问题排查与修复
    Kotlin 协程真的比 Java 线程更高效吗?
    Spark 数据倾斜及其解决方案
    大数据平台架构设计探究
  • 原文地址:https://www.cnblogs.com/nulige/p/6857053.html
Copyright © 2011-2022 走看看