• 在路上---学习篇(一)Python 数据结构和算法 (4) --希尔排序、归并排序


    独白

      希尔排序是经过优化的插入排序算法,之前所学的排序在空间上都是使用列表本身。而归并排序是利用增加新的空间,来换取时间复杂度的减少。这俩者理念完全不一样,注定造成的所消耗的时间不同以及空间上的不同。

      归并排序涉及到递归的使用,需要理解其中精髓才能更好了解归并排序,以及其他应用到递归的算法。理解其本质才能更好的应用。


    希尔排序

    希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

    时间复杂度

    • 最优时间复杂度:根据步长序列的不同而不同
    • 最坏时间复杂度:O(n2)
    • 稳定想:不稳定
    """
    希尔排序
    最优时间复杂度: 根据步长序列不同而不同
    最坏时间复杂度: O(n*n)
    稳定性 : 不稳定
    """
    
    import time
    import random
    
    
    def shell_sort(list):
        n = len(list)
        #初始步长
        gap = n // 2
        while gap > 0:
            # 按初始步长进行插入排序
            for j in range(gap, n):
                i = j
                # 插入排序
                while i >= gap and list[i-gap] > list[i]:
                    list[i-gap], list[i] = list[i], list[i-gap]
                    i -= gap
    
            # 得到新的步长
            gap = gap // 2
    
    
    def new_num(lis):
        """随机生成50个数加入列表中"""
        for i in range(50):
            j = random.randint(0, 10000)
            lis.append(j)
    
    if __name__ == '__main__':
        first_time = time.time()
        # 空列表
        lis = [54,26,93,17,77,31]
    
        # 随机函数添加到列表中
        # new_num(lis)
        print(lis)
    
        # 列表排序
        shell_sort(lis)
        print(lis)
    
        # 结束时间
        last_time = time.time()
    
        print("共用时%s" % (last_time - first_time))

    归并排序

    归并排序是采用分治法的一个非常典型的应用。归并排序的思想就是先递归分解数组,再合并数组。

    将数组分解最小之后,然后合并两个有序数组,基本思路是比较两个数组的最前面的数,谁小就先取谁,取了后相应的指针就往后移一位。然后再比较,直至一个数组为空,最后把另一个数组的剩余部分复制过来即可。

    时间复杂度

    • 最优时间复杂度:O(nlogn)
    • 最坏时间复杂度:O(nlogn)
    • 稳定性:稳定
    """
    归并排序
    最优时间复杂度:O(nlogn)
    最坏时间复杂度:O(nlogn)
    稳定性:稳定
    
    
    与其他排序区别
    利用一个新列表讲算法排序后的元素储存当中
    空间换时间
    """
    
    import time
    import random
    
    
    def merge_sort(list):
        """归并排序"""
        n = len(list)
        if n <= 1:
            return list
        # 最大整除
        mid = n // 2
        # left 利用递归  截取的列表形成的有序列表
        left_list = merge_sort(list[:mid])
        # right 利用递归  截取的列表形成的有序列表
        right_list =merge_sort(list[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
    
    
    def new_num(lis):
        """随机生成50个数加入列表中"""
        for i in range(50):
            j = random.randint(0, 100)
            lis.append(j)
    
    if __name__ == '__main__':
        first_time = time.time()
        # 空列表
        lis = []
    
        # 随机函数添加到列表中
        new_num(lis)
        print(lis)
    
        # 列表排序
        # 因为归并排序最后是返回一个新列表,所以打印输出为新列表
        alist = merge_sort(lis)
        print(alist)
    
        # 结束时间
        last_time = time.time()
    
        print("共用时%s" % (last_time - first_time))
  • 相关阅读:
    使用脚本进入一个命令行控制台,并预设执行的命令列表
    cifs挂载远程文件出现 No such device or address错误
    longtable 跨越多个页面时,如何在跨页时自动断行并加上横线及去掉页眉
    matplotlib中文显示-微软雅黑
    latex编译过程-关于嵌入所有字体
    python做图笔记
    linux启动全过程
    连接并同步windows下的git仓库
    反向ssh
    Ubuntu更改启动内存
  • 原文地址:https://www.cnblogs.com/Dreamxin/p/7896313.html
Copyright © 2020-2023  润新知