插入排序及其Python实现

本文详细介绍了插入排序的概念及其几种变种,包括直接插入排序、折半插入排序和希尔排序。每种排序方法都提供了详细的步骤说明及示例,帮助读者理解各种插入排序的工作原理。
部署运行你感兴趣的模型镜像

插入排序

  插入排序每步将一个带排序的对象,按其关键码大小,插入到前面已经排好序的一组对象的适当位置上,知道对象全部插入为止。插入排序边插入边排序,子序列随时都是排好序的。
  插入排序一般分三步进行:
 (1)在R[1…i-1]中查找R[i]的插入位置; R[1..j].key < R[i].key< R[j+1..i-1].key
 (2)将R[j+1..i-1]中的所有记录均后移一个位置;
 (3)将R[i]插入到R[j+1]的位置上。
插入排序
  根据具体实现方法的不同可分为基于顺序查找的直接插入排序、基于折半查找的折半插入排序、基于链表存储的表插入排序、基于逐趟缩小增量的希尔排序

1.直接插入排序

  直接插入排序主要利用顺序查找实现在R[1..i-1]中查找R[i]的插入位置,是一种稳定的排序算法。具体做法:R[0]作为监视哨,从R[i-1]起向前进行顺序查找,寻找R[i]的插入位置;在查找过程中找到的关键字不小于R[i].key的记录,在查找的同时,实现记录向后移动,循环结束后可以直接插入R[i]。

[13, 6, 3, 31, 9, 27, 5, 11]
第 1 次: [【13】, 6, 3, 31, 9, 27, 5, 11]
第 2 次: [【6, 13】, 3, 31, 9, 27, 5, 11]
第 3 次: [【3, 6, 13】, 31, 9, 27, 5, 11]
第 4 次: [【3, 6, 13, 31】, 9, 27, 5, 11]
第 5 次: [【3, 6, 9, 13, 31】, 27, 5, 11]
第 6 次: [【3, 6, 9, 13, 27, 31】, 5, 11]
第 7 次: [【3, 5, 6, 9, 13, 27, 31】, 11]
第 8 次: [【3, 5, 6, 9, 11, 13, 27, 31】]

一般情况下,直接插入排序的时间复杂度为O(n2),空间复杂度为O(1)(监视哨R[0]占用1空间)
如果记录基本有序,则每次只需比较一次,将R[i]直接加入到有序序列中,最好情况下的事件复杂度为O(n)

def direct_insert_sort(R):
    num = len(R)
    print "第 1 次:", R[1:]
    for i in range(2, num):  # start sorting from the second record
        R[0] = R[i]
        if R[i-1] <= R[0]:
            R[i] = R[0]
        else:
            for t in range(i):  # find the place to insert R[i]
                j = i-t
                if R[j] > R[0]:
                    R[j+1] = R[j]  # R[j]记录后移
                if R[j-1] <= R[0]:
                    R[j] = R[0]  # 记录R[i]插入位置j
                    break
        print "第", i, "次:", R[1:]
    return R

2.折半插入排序

  折半插入排序是在直接插入排序的基础上改进的插入排序算法。R[1..i-1] 是一个按关键字有序的有序序列,则可以利用折半查找实现“在R[1..i-1]中查找R[i]的插入位置”,把原来位置上的元素向后顺移。
  在已形成的有序表中折半查找,比较的次数大大减少,全部元素的比较次数为O(nlog2n)。但由于移动次数并未减少,所以折半插入排序的时间效率依然为O(n2),空间效率仍为O(1),是一种稳定的排序算法。

def half_insert_sort(R):
    num = len(R)
    for i in range(2, num):
        R[0] = R[i]
        if R[i-1] <= R[i]:
            R[i] = R[0]
        else:
            # 找到位置m插入 R[i]
            low = 0
            high = i - 1
            while low <= high:  
                m = (high + low)/2
                if R[m] > R[0]:
                    high = m - 1
                else:
                    low = m + 1
            R[m+1:i+1] = R[m:i]  #R[m:i]记录后移
            R[m] = R[0]  # insert R[i] on the record m
    return R

  如果记录用链表结构存储,用直接插入排序无需移动元素,时间效率更高。但是链表结构无法进行折半查找。

3.希尔排序(缩小增量排序)

  希尔排序的基本思想是先将整个带排序记录序列分割成若干个子序列,分别进行直接插入排序,待整个序列中的记录”基本有序“时,在对记录进行一次直接插入排序。值得注意的是子序列的构成不是简单地逐段分割,而是将相隔某个增量dk的记录组成一个子序列,让增量dk逐趟缩短(如依次取5,3,1),知道dk=1为止。
  希尔排序的优点是让关键值小的元素能很快的前移,并且在序列基本有序时,在使用直接插入排序处理,时间效率会大大提高。希尔排序的时间效率根据经验公式在O(n1.25)~O(1.6n1.25)。空间效率仍为O(1)。但由于记录交换位置后再采用直接插入排序,希尔排序算法并不稳定。

def shell_sort(R):
    num = len(R) - 1
    print R[1:]
    for dk in [5,3,1]:
        if num % dk == 0:
            dk_num = num/dk
        else:
            dk_num = num/dk + 1
        for a in range(dk):
            # 将dk增量记录存储到列表l,直接插入排序后赋值到列表R中,思路清晰但空间复杂度为O(n)
            # 也可不单独存储为l,空间复杂度为O(1)
            l = []
            for i in range(dk_num):
                if (1+a+dk * i) <= num:
                    l.append(R[1+a + dk * i])
            l.insert(0, 0)
            print dk, l
            for i in range(2, len(l)):
                l[0] = l[i]
                if l[i] >= l[i-1]:
                    l[i] = l[0]
                else:
                    for t in range(i):
                        j = i - t
                        if l[j] > l[0]:
                            l[j+1] = l[j]
                        if l[j-1] <= l[0]:
                            l[j] = l[0]
                            break
            for i in range(len(l) - 1):
                R[1+a + i * dk] = l[i + 1]
        print R[1:]
        return R

希尔排序的中间过程:

[13, 6, 3, 31, 9, 27, 5, 11]
第 1 次dk=5:[13, 27, 49, 55, 4, 49, 38, 65, 97, 76]#13 27排序 2 次dk=3:[13, 4, 49, 38, 27, 49, 55, 65, 97, 76]#13 31 5排序3 次dk=1:[4, 13, 27, 38, 49, 49, 55, 65, 76, 97]#5,6,3,13,9,27,31,11排序 

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

基于 NSFW Model 色情图片识别鉴黄 后面更新视频检测 项目背景: 随着互联网的快速发展,网络上的信息量呈现出爆炸式的增长。然而,互联网上的内容良莠不齐,其中不乏一些不良信息,如色情、暴力等。这些信息对青少年的健康成长和社会风气产生了不良影响。为了净化网络环境,保护青少年免受不良信息的侵害,我国政府加大了对网络内容的监管力度。在此背景下,本项目应运而生,旨在实现对网络图片和视频的自动识别与过滤,助力构建清朗的网络空间。 项目简介: 本项目基于 NSFW(Not Safe For Work)Model,利用深度学习技术对色情图片进行识别与鉴黄。NSFW Model 是一种基于卷积神经网络(CNN)的图像识别模型,通过学习大量的色情图片和非色情图片,能够准确地判断一张图片是否含有色情内容。本项目在 NSFW Model 的基础上,进一步优化了模型结构,提高了识别的准确率和效率。 项目功能: 色情图片识别:用户上传图片后,系统会自动调用 NSFW Model 对图片进行识别,判断图片是否含有色情内容。如果含有色情内容,系统会给出相应的提示,并阻止图片的传播。 视频检测:针对网络视频,本项目采用帧提取技术,将视频分解为一帧帧图片,然后使用 NSFW Model 对这些图片进行识别。如果检测到含有色情内容的图片,系统会给出相应的提示,并阻止视频的传播。 实时监控:本项目可应用于网络直播、短视频平台等场景,实时监控画面内容,一旦检测到含有色情内容的画面,立即进行屏蔽处理,确保网络环境的纯洁。
### 如何在本地部署 NSFW 模型或服务 要在本地环境中成功部署 NSFW(不适宜工作场合内容)检测模型或服务,以下是详细的说明: #### 准备环境 为了确保能够顺利运行模型和服务,需要安装必要的依赖项。这些工具和库包括但不限于以下几类: - **Python 环境**: 推荐使用 Python 3.7 或更高版本。 - **Transformers 库**: 提供加载预训练模型的功能[^1]。 - **PyTorch/TensorFlow**: 支持深度学习框架的计算需求。 - **Pillow (PIL)**: 处理图像文件并将其转换为适合输入模型的形式。 具体命令如下所示: ```bash pip install transformers torch Pillow ``` #### 加载模型与测试 通过 Hugging Face 的 `transformers` 工具包可以直接访问已有的 NSFW 图片分类模型。例如,可以采用名为 `"Falconsai/nsfw_image_detection"` 的公开模型来完成此任务[^1]。 下面是一个简单的代码片段展示如何加载该模型并对单张图片执行预测操作: ```python from PIL import Image from transformers import pipeline def classify_nsfw(image_path): # 打开指定路径下的图片文件 img = Image.open(image_path) # 初始化 image-classification 流水线对象,并指明使用的特定模型名称 classifier = pipeline("image-classification", model="Falconsai/nsfw_image_detection") # 对传入的图片调用流水线方法得到其类别标签及其置信度分数列表形式的结果 result = classifier(img) return result if __name__ == "__main__": test_img_path = "<your_test_image>" output_results = classify_nsfw(test_img_path) print(output_results) ``` 注意替换 `<your_test_image>` 成实际存在的图片绝对或者相对地址字符串值之前再尝试运行以上脚本。 #### 构建 RESTful API 服务 如果希望进一步扩展功能至 Web 应用程序层面,则可考虑利用 Flask/Django 这样的轻量级 web 开发框架构建起支持 HTTP 请求交互的服务端接口。这里给出基于 FastAPI 实现的一个简单例子作为示范用途: ```python import uvicorn from fastapi import FastAPI, File, UploadFile from PIL import Image from io import BytesIO from typing import List from pydantic import BaseModel app = FastAPI() class Prediction(BaseModel): label: str score: float @app.post("/predict/", response_model=List[Prediction]) async def predict(file: UploadFile = File(...)): try: contents = await file.read() pil_image = Image.open(BytesIO(contents)) clf_pipeline = pipeline('image-classification', model='Falconsai/nsfw_image_detection') predictions = clf_pipeline(pil_image) formatted_preds = [{"label": pred['label'], "score": round(pred['score'], 4)} for pred in predictions] return formatted_preds except Exception as e: raise ValueError(f"Error processing uploaded file {e}") if __name__ == '__main__': uvicorn.run(app, host='0.0.0.0', port=8000) ``` 启动服务器之后即可向 `/predict/` 路径发送 POST 请求附带上传待分析的目标图片获取返回结果了。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值