• chatGPT教你算法(1)——常用的排序算法


    0. 引言

    最近喜闻ChatGPT能够帮助我们认识世界了,我必须得作为先行者下场一波了。虽然ChatGPT对主观的一些看法是拿不准的,但是常规的基础性教学真的是信手拈来,别的地方不说,作为助教,我给他打200分。

    这真的让我想起来了小时候看的一个小说《师士传说》中的没有感情的牧,两者真的是太像了。

    好了闲话不说,我们来看看ChatGPT教你常见的排序算法吧!是不是通俗易懂,而且代码都给你了。

    这次,我们要讲的是常见的排序算法(以下部分包括代码,99%的部分由chatGPT模型自动生成,还有1%的人工编排)。

    1. 常见的算法有哪些

    常见的排序算法包括冒泡排序、插入排序、选择排序、快速排序、归并排序、基数排序等。

    排序算法可以根据它们的时间复杂度进行划分。常见的时间复杂度包括: O ( n 2 ) 、 O ( n l o g n ) 、 O ( n ) 、 O ( l o g n ) 、 O ( 1 ) O(n^2)、O(nlogn)、O(n)、O(logn)、O(1) O(n2)O(nlogn)O(n)O(logn)O(1)。例如,冒泡排序和插入排序的时间复杂度都是 O ( n 2 ) O(n^2) O(n2),而快速排序的时间复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)

    排序算法还可以根据它们的排序方式进行划分。例如,插入排序是一种内部排序方式,因为它只需要较少的额外空间就可以进行排序。而归并排序和快速排序是外部排序方式,因为它们需要大量的额外空间来进行排序。

    2. 冒泡排序(Bubble Sort)

    冒泡排序是一种简单的排序算法,它的原理是通过对待排序数组进行多次比较和交换来排序。它的基本思想是,每次比较相邻的两个元素,如果它们的顺序错误,就交换它们的位置,直到整个数组有序。

    """
    冒泡排序
    数组中元素如泡沫般
    按照大小排列
    自然整齐
    """
    def bubble_sort(arr):
      # 数组长度
      length = len(arr)
      
      # 外层循环控制比较轮数
      for i in range(length):
        # 内层循环控制每轮比较的次数
        for j in range(length - i - 1):
          # 比较相邻元素,如果左边比右边大,则交换位置
          if arr[j] > arr[j + 1]:
            arr[j], arr[j + 1] = arr[j + 1], arr[j]
      
      # 返回排序后的数组
      return arr
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3. 插入排序

    插入排序是一种基本的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到 O ( 1 ) O(1) O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

    对于插入排序的时间复杂度,最坏情况下为 O ( n 2 ) O(n^2) O(n2),最好情况下为 O ( n ) O(n) O(n),平均情况下为 O ( n 2 ) O(n^2) O(n2)

    """
    插入排序
    数组中元素如箭矢般
    有序插入
    精确到位
    """
    def insertion_sort(arr):
      # 数组长度
      length = len(arr)
      
      # 从第二个元素开始,依次插入到前面已经排好序的序列中
      for i in range(1, length):
        # 取出当前元素
        current = arr[i]
        # 取出当前元素的前一个元素的索引
        pre_index = i - 1
        
        # 当前元素的前一个元素比当前元素大,则需要将前一个元素后移
        while pre_index >= 0 and arr[pre_index] > current:
          arr[pre_index + 1] = arr[pre_index]
          pre_index -= 1
        
        # 插入当前元素
        arr[pre_index + 1] = current
      
      # 返回排序后的数组
      return arr
    
    • 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

    4. 选择排序

    选择排序是一种简单直观的排序算法,它的工作原理是每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

    选择排序的时间复杂度为 O ( n 2 ) O(n^2) O(n2),因为它需要进行n-1次比较来找出最小值,每次比较都需要 O ( n ) O(n) O(n)的时间,所以总时间复杂度为 O ( n 2 ) O(n^2) O(n2)

    """
    选择排序
    数组中元素如月光般
    逐一挑选
    明亮耀眼
    """
    def selection_sort(arr):
      # 数组长度
      length = len(arr)
      
      # 从第一个元素开始,遍历数组
      for i in range(length):
        # 记录当前最小元素的索引
        min_index = i
        # 从当前元素后面的所有元素中,逐一比较,找出最小的元素
        for j in range(i + 1, length):
          if arr[j] < arr[min_index]:
            min_index = j
        
        # 交换当前元素和最小元素
        arr[i], arr[min_index] = arr[min_index], arr[i]
      
      # 返回排序后的数组
      return arr
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    5. 快速排序

    快速排序是一种高效的排序算法,它的工作原理是通过一趟排序将待排序数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

    快速排序的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),因为它的平均时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)。最坏情况下的时间复杂度为 O ( n 2 ) O(n^2) O(n2),但这种情况很少发生。

    """
    快速排序
    数组中元素如流光般
    快速按序排列
    顺畅自如
    """
    def quick_sort(arr):
      # 数组长度
      length = len(arr)
      
      # 如果数组长度小于等于1,则直接返回
      if length <= 1:
        return arr
      
      # 取第一个元素为基准值
      pivot = arr[0]
      # 定义左右两个数组
      left = []
      right = []
      
      # 循环遍历数组,把小于基准值的元素放到左边数组,把大于基准值的元素放到右边数组
      for i in range(1, length):
        if arr[i] < pivot:
          left.append(arr[i])
        else:
          right.append(arr[i])
      
      # 递归排序左边和右边的数组
      sorted_left = quick_sort(left)
      sorted_right = quick_sort(right)
      
      # 把排序后的左边和右边的数组,合并成一个新的数组
      return sorted_left + [pivot] + sorted_right
    
    • 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

    6.请你给出最快的排序算法(桶排序)

    最快的排序算法是桶排序。桶排序是一种非常高效的排序算法,它的工作原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法)。最后,依次枚举每个桶子中的元素,然后将它们连接起来。
    桶排序的时间复杂度为 O ( n + k ) O(n+k) O(n+k),其中n为数组的长度,k为桶的数量。对于一个有n个元素的数组,如果我们采用桶排序,设k为桶的数量,则桶排序的时间复杂度为 O ( n + k ) O(n+k) O(n+k)

    """
    桶排序
    数组中元素如雨水般
    分桶计数
    顺滑流畅
    """
    def bucket_sort(arr):
      # 数组长度
      length = len(arr)
      
      # 创建桶
      bucket = [0] * length
      
      # 遍历数组,将数组中的元素放入桶中
      for i in range(length):
        bucket[arr[i]] += 1
      
      # 创建结果数组
      result = []
      
      # 遍历桶,将桶中的元素添加到结果数组中
      for i in range(length):
        for j in range(bucket[i]):
          result.append(i)
      
      # 返回排序后的数组
      return result
    
    • 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

    7. Timsort算法

    老师,你说的不对,我去查了一下,人家说Timsort算法才是最快的。

    Timsort是一种高效的排序算法,它的工作原理是对数组进行分段,将小的子段归并排序,然后再将有序的子段进行合并。Timsort的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),其中n为数组的长度。

    由于Timsort是Python中的内置排序算法,因此可以直接使用Python的内置函数sorted()进行排序。下面是一个使用Timsort进行排序的例子:

    arr = [3, 7, 4, 9, 5, 2, 6, 1]
    sorted_arr = sorted(arr)
    print(sorted_arr)  # 输出 [1, 2, 3, 4, 5, 6, 7, 9]
    
    
    • 1
    • 2
    • 3
    • 4

    在上面的例子中,我们直接使用Python的内置函数sorted()对数组进行排序,它会自动使用Timsort算法进行排序。

    另外,如果你想手动实现Timsort算法,可以参考下面的代码:

    def timsort(arr):
        # 定义一个增量序列,表示每次进行归并排序的子段长度
        incs = [57, 23, 10, 4, 1]
    
        # 对每个增量进行归并排序
        for inc in incs:
            for i in range(0, len(arr), inc * 2):
                arr[i:i + 2 * inc] = merge(arr[i:i + inc], arr[i + inc:i + 2 * inc])
    
        return arr
    
    # 合并两个有序数组
    def merge(arr1, arr2):
        result = []
    
        while arr1 and arr2:
            if arr1[0] < arr2[0]:
                result.append(arr1.pop(0))
            else:
                result.append(arr2.pop(0))
    
        result.extend(arr1)
        result.extend(arr2)
    
        return result
    
    • 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

    8. 如果想设计一个很好的排序算法,有哪些指导性原则?

    设计一种更好的排序算法需要考虑许多因素,包括时间复杂度、空间复杂度、稳定性、可扩展性、实现复杂度等。一些指导性原则如下:

    1. 设计算法时,应该尽量降低时间复杂度。一般来说,常见的排序算法时间复杂度都在 O ( n 2 ) O(n^2) O(n2) O ( n l o g n ) O(nlogn) O(nlogn)之间,因此,如果能够设计出时间复杂度更低的排序算法,就可以提高算法的性能。

    2. 设计算法时,应该尽量降低空间复杂度。排序算法的空间复杂度通常要小于时间复杂度,因此,如果能够设计出空间复杂度更低的排序算法,就可以节省内存空间,提高算法的效率。

    3. 设计算法时,应该尽量保证稳定性。排序算法的稳定性指的是在排序过程中,如果有多个元素的值相同,排序后它们的相对位置不变。稳定的排序算法可以保证排序后的结果更加有序,更加满意人类的阅读习惯。

    4. 设计算法时,应该尽量考虑可扩展性。排序算法的可扩展性指的是它能够在不同的硬件平台上运行,并且能够高效地处理大型数据集。可扩展的排序算法能够更好地适应不同的硬件环境,例如多核处理器、分布式系统、移动设备等。这样的算法可以利用多核处理器的优势,提高排序的速度;也可以在分布式系统中分配多个节点来进行排序,提高排序的容错性。可扩展的排序算法还能够高效地处理大型数据集。例如,外部排序算法能够利用磁盘存储来进行排序,因此即使数据集非常大,也能够进行高效的排序。因此,在设计排序算法时,应该尽量考虑可扩展性,以便在不同的硬件平台和数据集上都能够取得良好的性能。

    9. 小结

    以上就是ChatGPT教你算法的第一课,怎么样,学会排序算法了吗?接下来还想学哪个部分,请评论告诉我,我来安排!

  • 相关阅读:
    【C++】动态内存管理 ① ( C 语言中的动态内存管理 | C 语言 内存申请 | C 语言 内存释放 | 代码示例 )
    js如何实现选项卡功能
    Dolphinscheduler的API接口问题
    解密Socks5代理和代理IP:网络工程师的隐秘武器
    webpack配置单页面和多页面
    【Redis入门笔记 06】发布和订阅
    HBuilderX打包web网站之wap2app设置底部菜单tabBar
    DicomObjects COM 8.XX.1102.0: 2022-10-18
    vue中用js实现循环可编辑表格
    超全详细,解决校园网没有路由器实现开发板和虚拟机直连
  • 原文地址:https://blog.csdn.net/qq_35082030/article/details/128210306