十大排序算法思想与 Python 实现(下)

简介: 一般排序算法最常考的:快速排序和归并排序。这两个算法体现了分治算法的核心观点,而且还有很多出题的可能。

1.7 堆排序

堆是一种特殊的树形数据结构,其每个结点都有一个值,通常提到的堆都是指一棵完全二叉树,根结点的值小于(或大于)两个子结点的值,同时根结点的两个子树也分别是一个堆。

1.7.1 算法思想:

对于给定的序列,初始把这些记录看成一刻顺序存储的二叉树,然后将其调整为一个大顶堆,然后将堆的最后一个元素与堆顶元素进行交换后,堆的最后一个元素即为最大记录;接着将前(n-1)个元素重新调整为一个大顶堆,在将堆顶元素与当前堆的最后一个元素进行交换后得到次大的记录,重复该过程直到调整的堆中只剩一个元素为止,该记录即为最小记录,此时可得到一个有序序列。


过程:1. 构建堆;2. 交换堆顶元素与最后一个元素的位置

1.7.2 实现
def heapify(unsorted, index, heap_size):
    largest = index
    left_index = 2 * index + 1
    right_index = 2 * index + 2
    if left_index < heap_size and unsorted[left_index] > unsorted[largest]:
        largest = left_index
    if right_index < heap_size and unsorted[right_index] > unsorted[largest]:
        largest = right_index
    if largest != index:
        unsorted[largest], unsorted[index] = unsorted[index], unsorted[largest]
        heapify(unsorted, largest, heap_size)
def heap_sort(unsorted):
    """堆排序"""
    length = len(unsorted)
    for i in range(length // 2 - 1, -1, -1):
        heapify(unsorted, i, length)
    for i in range(length - 1, 0, -1):
        unsorted[0], unsorted[i] = unsorted[i], unsorted[0]
        heapify(unsorted, 0, i)
    return unsorted
if __name__ == '__main__':
    gList = [5, 4, 2, 1, 7, 3, 6]
    print("-----yuzhou1su-----", gList)
    print("-----堆排序后:", heap_sort(gList))
1.7.3 堆排序分析

时间复杂度: 主要耗费在创建堆和反复调整堆上,最坏情况下,时间复杂度也为O(nlogn)

空间复杂度O(1)

稳定性: 不稳定

1.8 计数排序

1.8.1 算法思想

对于某种整数 K,计数排序假定每个元素都是 1 到 K 范围内的整数。 计数排序的基本思想是为每个输入元素 x 确定小于 x 的元素数量, 此信息可用于直接将其放置在正确的位置。 例如,如果 10 个元素小于 x,则 x 属于输出中的位置 11。

1.8.2 实现
# -*- coding: utf-8 -*-
# @Author    : 宇宙之一粟
# @File      : counting_sort.py
def counting_sort(unsorted):
    """计数排序
    :param unsorted:给定一组序列
    :return: 升序序列
    """
    if unsorted is []:
        return []
    # 根据给定序列求信息
    coll_len = len(unsorted)
    coll_max = max(unsorted)
    coll_min = min(unsorted)
    # 创建计数数组
    counting_arr_length = coll_max + 1 - coll_min
    counting_arr = [0] * counting_arr_length
    # 计数操作
    for number in unsorted:
        counting_arr[number - coll_min] += 1
    # 将每个位置与它的前一个相加。counting_arr[i]统计出多少个
    # element <= i的元素
    for i in range(1, counting_arr_length):
        counting_arr[i] = counting_arr[i] + counting_arr[i - 1]
    # 创建保存升序结果的数组
    ordered = [0] * coll_len
    for i in reversed(range(0, coll_len)):
        ordered[counting_arr[unsorted[i] - coll_min] - 1] = unsorted[i]
        counting_arr[unsorted[i] - coll_min] -= 1
    return ordered
if __name__ == '__main__':
    gList = [5, 4, 2, 1, 3, 6]
    print("-----yuzhou1su:", gList)
    print("-----计数排序后:", counting_sort(gList))
1.8.3 计数排序分析

时间复杂度: O(n)ifK=O(n)


空间复杂度:O(n)ifK=O(n)


Ps: 如果 K 特别大,时间复杂度会很高;如果面试官让你设计数据规模小的线性排序算法,可能就是考察计数排序

1.9 桶排序

1.9.1 算法思想

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。为了使桶排序更加高效,我们需要做到这两点:


  1. 在额外空间充足的情况下,尽量增大桶的数量
  2. 使用的映射函数能够将输入的 N 个数据均匀的分配到 K 个桶中
1.9.2 实现
# -*- coding: utf-8 -*-
import math
def insertion_sort(collection):
    for i in range(1, len(collection)):
        temp = collection[i]
        index = i
        while index > 0 and temp < collection[index - 1]:
            collection[index] = collection[index-1]
            index -= 1
        collection[index] = temp
def bucket_sort(collection):
    code = hashing(collection)
    buckets = [list() for _ in range(code[1])]
    for i in collection:
        x = rehashing(i, code)
        buck = buckets[x]
        buck.append(i)
    for bucket in buckets:
        insertion_sort(bucket)
    ndx = 0
    for buc in range(len(buckets)):
        for val in buckets[buc]:
            collection[ndx] = val
            ndx += 1
    return collection
def hashing(collection):
    m = collection[0]
    for i in range(1, len(collection)):
        if m < collection[i]:
            m = collection[i]
    result = [m, int(math.sqrt(len(collection)))]
    return result
def rehashing(i, code):
    return int(i / code[0] * (code[1] - 1))
if __name__ == '__main__':
    gList = [5, 4, 2, 1, 3, 6]
    print("-----yuzhou1su:", gList)
    print("-----桶排序后:", bucket_sort(gList))
1.9.3 桶排序分析
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)

1.10 基数排序

1.10.1 算法思想

与计数排序/桶排序类似,基数排序跟输入元素相关。比如:根据基数 d 对给定序列进行排序,这意味着所有的数字都是 d 位数。过程:


  1. 取每个元素的最低有效位
  2. 根据该数字对元素列表进行排序,但保持相同数字的元素顺序
  3. 用更高有效位重复排序,直到最高位
1.10.2 实现
def radix_sort(unsorted):
    radix = 10
    max_len = False
    tmp, placement = -1, 1
    while not max_len:
        max_len = True
        buckets = [list() for _ in range(radix)]
        for i in unsorted:
            tmp = int(i / placement)
            buckets[tmp % radix].append(i)
            if max_len and tmp > 0:
                max_len = False
        a = 0
        for b in range(radix):
            buck = buckets[b]
            for i in buck:
                unsorted[a] = i
                a += 1
        # move to next digit
        placement *= radix
    return unsorted
if __name__ == '__main__':
    gList = [5, 4, 2, 1, 3, 6]
    print("-----yuzhou1su:", gList)
    print("-----基数排序后:", radix_sort(gList))
1.10.3 基数排序分析

基数排序适用于位数小的数字序列。


  • 时间复杂度: O(nlog(r)m),其中 r 为所采取的基数,而 m 为堆数
  • 稳定性:稳定

1.11 其他排序

  • 拓扑排序:在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。
  • 外部排序:大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。
  • 位图排序:当待排序数据规模较大,而堆内存大小又没有限制时,位图排序则最高效。
  • Tim-sort:Python 的 list 标准排序算法,由 Tim Peters 设计。本质上是一种自下而上的归并排序,利用一些数据的初始运行,之后进行额外的插入排序。Tim-sort 也成为 Java7 中数组排序的默认算法。

2. 各种排序算法比较?


image.png


根据上图总结:


  • 不稳定算法有:选择、快速、希尔、堆  ( 记忆口诀:"快选七(希)堆不稳定的排序")
  • 时间复杂度O(n2):选择、冒泡、插入
  • 时间复杂度O(nlogn):快速、归并、堆、希尔
  • 时间复杂度O(n):计数、桶
  • 空间复杂度O(1):选择、插入、冒泡、希尔、堆
  • 空间复杂度O(n):归并、计数、桶
  • 空间复杂度O(logn):快速排序

3.总结

一定要根据数据的规模、规律来给出合适的算法,不能觉得快速排序名字就以为是快速的,切记不能什么排序问题都回答快排。


  1. 虽然插入排序和冒泡排序平均速度较慢,但当初始序列整体或局部有序时,这两者效率较高
  2. 排序数据较小,且不要求稳定的情况下,选择排序效率较高;要求稳定,选择冒泡排序。
  3. 堆排序在更大的序列上往往优于快速排序和归并排序。
  4. 针对小数据追求线性时间复杂度,考虑计数排序和桶排序
  5. 除了上面几种常见的排序算法,还有众多其他排序算法,每种排序算法都有其最佳适用场合。具体情况具体分析。
相关文章
|
1月前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
眼疾识别系统,本系统使用Python作为主要开发语言,基于TensorFlow搭建卷积神经网络算法,并收集了4种常见的眼疾图像数据集(白内障、糖尿病性视网膜病变、青光眼和正常眼睛) 再使用通过搭建的算法模型对数据集进行训练得到一个识别精度较高的模型,然后保存为为本地h5格式文件。最后使用Django框架搭建了一个Web网页平台可视化操作界面,实现用户上传一张眼疾图片识别其名称。
163 5
基于Python深度学习的眼疾识别系统实现~人工智能+卷积网络算法
|
2月前
|
机器学习/深度学习 人工智能 算法
猫狗宠物识别系统Python+TensorFlow+人工智能+深度学习+卷积网络算法
宠物识别系统使用Python和TensorFlow搭建卷积神经网络,基于37种常见猫狗数据集训练高精度模型,并保存为h5格式。通过Django框架搭建Web平台,用户上传宠物图片即可识别其名称,提供便捷的宠物识别服务。
381 55
|
10天前
|
算法 Serverless 数据处理
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
38 12
|
8天前
|
算法 安全 网络安全
基于 Python 的布隆过滤器算法在内网行为管理中的应用探究
在复杂多变的网络环境中,内网行为管理至关重要。本文介绍布隆过滤器(Bloom Filter),一种高效的空间节省型概率数据结构,用于判断元素是否存在于集合中。通过多个哈希函数映射到位数组,实现快速访问控制。Python代码示例展示了如何构建和使用布隆过滤器,有效提升企业内网安全性和资源管理效率。
44 9
|
2月前
|
存储 缓存 监控
局域网屏幕监控系统中的Python数据结构与算法实现
局域网屏幕监控系统用于实时捕获和监控局域网内多台设备的屏幕内容。本文介绍了一种基于Python双端队列(Deque)实现的滑动窗口数据缓存机制,以处理连续的屏幕帧数据流。通过固定长度的窗口,高效增删数据,确保低延迟显示和存储。该算法适用于数据压缩、异常检测等场景,保证系统在高负载下稳定运行。 本文转载自:https://www.vipshare.com
136 66
|
16天前
|
监控 算法 安全
内网桌面监控软件深度解析:基于 Python 实现的 K-Means 算法研究
内网桌面监控软件通过实时监测员工操作,保障企业信息安全并提升效率。本文深入探讨K-Means聚类算法在该软件中的应用,解析其原理与实现。K-Means通过迭代更新簇中心,将数据划分为K个簇类,适用于行为分析、异常检测、资源优化及安全威胁识别等场景。文中提供了Python代码示例,展示如何实现K-Means算法,并模拟内网监控数据进行聚类分析。
33 10
|
1月前
|
存储 算法 安全
控制局域网上网软件之 Python 字典树算法解析
控制局域网上网软件在现代网络管理中至关重要,用于控制设备的上网行为和访问权限。本文聚焦于字典树(Trie Tree)算法的应用,详细阐述其原理、优势及实现。通过字典树,软件能高效进行关键词匹配和过滤,提升系统性能。文中还提供了Python代码示例,展示了字典树在网址过滤和关键词屏蔽中的具体应用,为局域网的安全和管理提供有力支持。
55 17
|
6天前
|
存储 算法 量子技术
解锁文档管理系统高效检索奥秘:Python 哈希表算法探究
在数字化时代,文档管理系统犹如知识宝库,支撑各行各业高效运转。哈希表作为核心数据结构,通过哈希函数将数据映射为固定长度的哈希值,实现快速查找与定位。本文聚焦哈希表在文档管理中的应用,以Python代码示例展示其高效检索特性,并探讨哈希冲突解决策略,助力构建智能化文档管理系统。
|
3月前
|
搜索推荐 Python
利用Python内置函数实现的冒泡排序算法
在上述代码中,`bubble_sort` 函数接受一个列表 `arr` 作为输入。通过两层循环,外层循环控制排序的轮数,内层循环用于比较相邻的元素并进行交换。如果前一个元素大于后一个元素,就将它们交换位置。
160 67
|
3月前
|
存储 搜索推荐 Python
用 Python 实现快速排序算法。
快速排序的平均时间复杂度为$O(nlogn)$,空间复杂度为$O(logn)$。它在大多数情况下表现良好,但在某些特殊情况下可能会退化为最坏情况,时间复杂度为$O(n^2)$。你可以根据实际需求对代码进行调整和修改,或者尝试使用其他优化策略来提高快速排序的性能
153 61

热门文章

最新文章