桶排序详细说明及实现-python

news2024/11/15 10:57:09

前言:

        说到桶排序,那必定要有桶,那么桶的作用是什么呢?桶的作用就是将序列分为若干份放到桶中,每个桶中能装入的数量范围是一定的,只有最后一个桶可以设置装入很多。这是因为当分的桶一定时,前面的桶装入的数的范围有限,这时还有序列中的数大于最后一个桶的数值范围,就把多余的装到最后一个桶中。

       那么如何把序列一个个放入不同的桶中呢,好比有从1到100这么多个数,我们要怎么分桶,分多少桶,可以根据序列的性质来设置。可以分10个桶,然后每个桶就是装10个数的范围,第一个桶装1-10的数,第二个桶装11-20的数,......,第十个桶装91-100的数,当然若有超过100的数由于没有第十一个桶,我们就把它装入第十个桶中。由此可知,每个桶装一定范围的数。

        把序列装入桶中就完了么,当然不是,还没有排序呢。这里当把一个序列装入桶中时,就用插入排序,从后往前插入,如果该数比前面的数大就插入其后面,不然就向前比较插入。就是说桶中每插入一个数就会把该数放到合适的位置使桶整体有序。

        最后就是按顺序逐个把每个桶中的元素放回原来的序列中。

        

 如下图,我们以序列【5, 24, 78, 65, 54, 94, 15, 36, 68, 35, 3, 78, 89, 56, 47】为例,进行桶排序。可以分配5个桶,每个桶中包含20个数的范围。


 

 实现代码:

def BucketSort(li, n=100, max_num=10000):
    buckets = [[] for _ in range(n)] #创建桶
    for var in li:
        i = min(var // (max_num // n), n-1)  # i 表示当前的数(var)放到几号桶里,最后一个桶是最大的一段数
        buckets[i].append(var)      #把var加到对应的桶里面
        #保持桶内的顺序
        for j in range(len(buckets[i])-1, 0, -1):  # 从最后一个位置往前比较
            if buckets[i][j] < buckets[i][j-1]:
                buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]
            else:
                break
    # 把桶内数据放回原序列
    li.clear()
    for buc in buckets: #每个桶内都是有序的,连接起来
        li.extend(buc)
    return li


import random

li = [random.randint(0,10000) for i in range(100000)]  # 创建一个0-10000的随机数列表

li = BucketSort(li)
print(li)

 排序结果如图:


 桶排序改进:

        从代码中可以看出在每个数插入到桶中时,要对该数在通中的顺序进行排序调整,用的是插入排序进行比较来使桶序列有序的,这种方法还是比较慢的,我们可以使用其他的排序方法来代替插入排序。如快速排序。

 代码实现:

由于我们用到快速排序,我们可以把我们之前写的快速排序进行一下改装,放到QuickSort.py下

        之前的快速排序代码:

def partition(li, left, right):
    tmp = li[left]  # 设置tmp为最左边起始值
    while left < right:
        while left < right and li[right] >= tmp:  # 从右边找比tmp小的数
            right -= 1  # 没找到就往左走一步
        li[left] = li[right]  # 找到了比tmp小的,就把右边的值写到左边空位上,否则就是left=right
        while left < right and li[left] <= tmp:  # 从左边找比tmp大的数
            left += 1  # 没找到就往右走一步
        li[right] = li[left]  # 找到了比tmp大的,就把左边的值写到右边空位上,否则就是left=right
    li[left] = tmp  # 此时,right=left为空,把tmp值放置到此处,
    return left   # 返回下标,对左右两边进行递归排序

def QuickSort(li, left, right):
    if left < right:  # 至少两个元素,一个不需要
        mid = partition(li, left, right)  # 排序并返回mid(相对)
        QuickSort(li, left, mid - 1)  # 对mid左边排序
        QuickSort(li, mid + 1, right)  # 对mid右边排序

        我们为了比较一下改进是否有效,比较其排序时间更直观。因此我们需要一个装饰器。来记录每个函数的排序时间。

        装饰器代码如下:

import time

def cal_time(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        result = func(*args, **kwargs)
        t2 = time.time()
        print("%s 运行时间: %s secs." %(func.__name__, t2-t1))
        return result

    return wrapper

        改进版桶排序及比较:

import copy
import random
import sys
from cal_time import *
import QuickSort

# 原版桶排序
@cal_time
def BucketSort(li, n=100, max_num=10000):
    buckets = [[] for _ in range(n)]  # 创建桶
    for var in li:
        i = min(var // (max_num // n), n-1)  # i 表示var放到几号桶里,最后一个桶是最大的一段数
        buckets[i].append(var)      # 把var加到对应的桶里面

        # 保持桶内的顺序
        for j in range(len(buckets[i])-1, 0, -1):
            if buckets[i][j] < buckets[i][j-1]:
                buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]
            else:
                break
    li.clear()
    for buc in buckets:  # 每个桶内都是有序的,连接起来
        li.extend(buc)
    return li

# 改进版
@cal_time
def BucketSortPro(li, n=100, max_num=10000):
    buckets = [[] for _ in range(n)]  # 创建桶
    for var in li:
        i = min(var // (max_num // n), n-1)  # i 表示var放到几号桶里,最后一个桶是最大的一段数
        buckets[i].append(var)      # 把var加到对应的桶里面

    # 保持桶内的顺序, 使用快排进行每个桶的排序
    for i in buckets:
        QuickSort.QuickSort(i,0,len(i)-1)

    li.clear()
    for buc in buckets:  # 每个桶内都是有序的,连接起来
        li.extend(buc)
    return li

# 快速排序
@cal_time
def quicksort(li):  
    """
    :type li: list
    """
    QuickSort.QuickSort(li,0,len(li)-1)
    return li

li = [random.randint(0,10000) for i in range(100000)]  # 创建范围很大的随机序列

li1 = copy.deepcopy(li)  # 将序列深拷贝3份
li2 = copy.deepcopy(li)
li3 = copy.deepcopy(li)

li1 = BucketSort(li1)  
li2 = BucketSortPro(li2)
li3 = quicksort(li3)  # 排序结果是一样的,我们看排序时间快慢

运行时间比较:

        可以看到改进前桶排序用时达到了9秒多, 而快速排序用时0.3341秒,明显快排较快,而改进后的桶排序内部也采用了快速排序,结果比快排还要快为0.2383秒,所以改进是有效的且显著的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/171697.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringMVC-基础入门

文章目录SpringMVC1&#xff0c;SpringMVC概述2&#xff0c;SpringMVC入门案例2.1 需求分析2.2 案例制作步骤1:创建Maven项目步骤2:补全目录结构步骤3:导入jar包步骤4:创建配置类步骤5:创建Controller类步骤6:使用配置类替换web.xml步骤7:配置Tomcat环境步骤8:启动运行项目步骤…

【软考】系统集成项目管理工程师(十五)项目采购管理

一、项目采购管理概述二、项目采购管理子过程1. 编制采购管理计划2. 实施采购3. 控制采购4. 结束采购三、招投标1. 招标人的权利和义务2. 招标代理机构的权利和义务3. 招标方式和招投标程序4. 相关的法律责任一、项目采购管理概述 采购意味着从外界来源获得商品或服务,采购一…

Vue3组件初始化流程分析

本文主要来分析 vue3 组件的初始化(基于runtime-core(核心运行时)包)&#xff0c;将从createApp、mount 等常用 API 入手来分析组件的挂载、普通元素的挂载流程。 createApp 1、创建一个应用实例。使用方式如下: import { createApp } from vue import App from ./App.vueco…

进制转换(二进制、八进制、十进制、十六进制)超详细版

今天来总结一下各种进制转换问题&#xff0c;详细齐全易于理解&#xff0c;希望对你有帮助哦&#xff01; 各种进制之间的相互转换 先从我们最熟悉的十进制入手吧&#xff0c;其他进制与十进制的转换方法都是一样的。 整型有4种进制形式&#xff1a; 1.十进制&#xff1a; …

[ChatGPT]

最近hatGPT火爆全宇宙&#xff0c;几乎所有圈内人都在谈论这个美国人工智能公司OpenAI发布免费机器人对话模型ChatGPT&#xff08;GPT-3.5系列&#xff09;&#xff0c;模型中首次采用RLHF&#xff08;从人类反馈中强化学习&#xff09;方式。模型目前处于测试阶段&#xff0c;…

Windows 服务器刷题(2)(带答案)

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.刷题 前言 本章将会讲解Windows服务器刷题&#xff08;2&#xff09; 一…

新年礼物已收到!2022 Apache IoTDB Commits 数量排名 3/351!

社区喜报&#xff01;据 The Apache Software Foundation 官方 Projects Statistics&#xff08;项目信息统计网站&#xff09;的实时数据显示&#xff0c;Apache IoTDB 在过去 12 个月&#xff08;即 2022 年度&#xff09;共发表 6829 Commits&#xff0c;排名 2022 年度 Apa…

C++ Primer笔记——默认移动操作、移动迭代器、左右值引用成员函数、标准库仿函数、function包装器

目录 一.P476 合成的移动操作 二.P480 移动迭代器 三.P483 右值和左值引用成员函数 四.P510 标准库定义的仿函数 五.P512 标准库function类型&#xff08;包装器&#xff09; 一.P476 合成的移动操作 什么时候会有默认的移动构造和移动赋值函数&#xff0c;需满足以下几点…

Java设计模式-中介者模式Mediator

介绍 中介者模式&#xff08;Mediator Pattern&#xff09;&#xff0c;用一个中介对象来封装一系列的对象交互。中介者使各个对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。中介者模式属于行为型模式&#xff0c;使代…

linux搭建webapp实战

首先介绍下linux&#xff0c;linux因其开源&#xff0c;定制化高&#xff0c;安全等原因&#xff0c;成为了目前web应用部署首选的操作系统&#xff0c;linux操作系统有很多版本&#xff0c;常见的有centos&#xff0c;debian&#xff0c;RHLE&#xff0c;redhat&#xff0c;乌…

【Linux】gcc/g++编译器、make/Makefile自动化构建工具

作者&#xff1a;小卢 专栏&#xff1a;《Linux》 喜欢的话&#xff1a;世间因为少年的挺身而出&#xff0c;而更加瑰丽。 ——《人民日报》 目录 1.gcc/c的概念&#xff1a; 2.程序编译过程详解&#xff1a; 2.1程序编译过程&#xff1a; 2.…

微电网(风、光、储能、需求响应)【Simulink 仿真实现】

目录 1 展现 2 典型几个介绍 2.1 采用PR的三相逆变器电压控制 2.2 太阳能直流微电网系统 2.3 主电网故障时的交流微电网性能 2.4 混合光伏、双馈发电和电池能源的微电网集成 3 写在后面 4 完整资源 1 展现 随便打开一个&#xff0c;就以第一个&#xff08;采用PID的三…

【GD32F427开发板试用】macOS/Linux系统开发环境搭建(开发、编译、烧录、调试)

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;HonestQiao 我日常的工作环境使用的是macOS系统或者Linux系统&#xff0c;万不得已才使用Windows。 GD32官方提供了Keil MDK-ARM和IAR两款工具…

如何使用Dx命令将jar打包成Dex,需要使用D8命令

使用dx打包的完整命令&#xff0c;将D:\ssh1.0.jar打包成MyClass.dex&#xff0c;MyClass.dex将会输出在当前CMD命令窗口的目录下。dx --dex --no-strict --min-sdk-version26 --outputMyClass.dex D:\ssh1.0.jar运行结果&#xff1a;不要使用dx命令&#xff0c;打出来的dex可以…

NestJS 项目实战 技术选型 (文末附视频)

前言 通过上一章的学习&#xff0c;我们了解了网关系统&#xff0c;并且针对要做的功能做了项目架构设计与需求拆解。 那在一个项目正式开发之前&#xff0c;我们还需要做一个技术调研&#xff0c;从开发框架、使用的工具、数据库等等进行一系列的预研&#xff0c;避免在业务…

嘿~ 基于分布式架构的技术交流社区(WhiteHoleV0.7)即将竣工!

文章目录前言项目介绍WhiteHole期望立项作者功能/模块简介用户模块问答模块社区模块博文模块Next前言 拖更&#xff0c;拖延了这么久&#xff0c;耗时超过3个月的项目&#xff0c;WhiteHoleV0.7 版本即将迎来最后的收尾工作。当然考虑到服务成本&#xff0c;和开发进度&#x…

【以太网硬件十九】SGMII到底能不能直接出光模块?

SGMII接口到底能不能直接出光模块&#xff1f;先说结论&#xff1a;我认为可以&#xff0c;但是有限制&#xff0c;此时的光口只支持强制模式&#xff0c;不支持自协商。如果对端是1000base-X接口&#xff0c;对端也需要把自协商关闭才能与SGMII直出的光口建立连接。为什么SGMI…

你是真的“C”——C语言详解求素数n种境界~

详解C语言函数模块知识(下篇&#xff09;&#x1f60e;前言&#x1f64c;必备小知识~&#x1f618;C语言详解《试除法》求解素数&#x1f64c;试除法第一层境界~ &#x1f60a;试除法境界2~&#x1f60a;试除法境界3~&#x1f60a;试除法境界4~&#x1f60a;C语言详解《筛选法》…

为何限制英伟达出售GPU芯片?中国的AI技术领先,让美国怕了

2022年下半年美国突然要求GPU芯片领军者NVIDIA停止对中国出售高端GPU芯片&#xff0c;此举让人疑惑不解&#xff0c;近期日本媒体《日本经济新闻》与荷兰的一家学术信息巨头的分析给出了答案&#xff0c;中国在AI技术上已领先于美国&#xff0c;而NVIDIA的高端GPU芯片有助于中国…

Web端即时通信技术-WebSocket

最近在做项目的时候&#xff0c;遇到了一个前端页面需要实时刷新的功能&#xff0c;一种方法是我们通过短轮询的方式&#xff0c;但这种方式虽然简单&#xff0c;但是无用的请求过多&#xff0c;占用资源&#xff0c;并且如果是对数据要求高较高的场景&#xff0c;就不适用了。…