python 优先队列 快速_优先队列如何使用Python实现及海量数据中寻找K大数

本文介绍了如何使用Python实现优先队列,特别是最大优先队列,通过二叉堆实现高效操作。此外,还探讨了在海量数据中寻找K大数的问题,提出使用优先队列(Python的`queue`模块)实现,时间复杂度为O(nlogk)。文中给出了具体的代码示例和步骤解释。
摘要由CSDN通过智能技术生成

优先队列如何使用Python实现及海量数据中寻找K大数

优先队列如何使用Python实现及海量数据中寻找K大数

今天是2020.10.01,是个喜庆的日子,中秋和国庆同天贺。祝福祖国越来越好,祝福普天下的家庭幸福美满。今天,主要介绍一下数据结构中的优先队列(PriorityQueue)如何使用Python实现以及优先队列的应用之海量数据中如何寻找K大数。

什么是优先队列(取自百度百科)?

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。通俗一些描述就是,出队的时候,元素按照优先级进行出队。

优先队列不再遵循先入先出的原则,而是分为两种情况:

最大优先队列,无论入队顺序,当前最大的元素优先出队。

最小优先队列,无论入队顺序,当前最小的元素优先出队。

比如有一个最大优先队列,它的最大元素是8,那么虽然元素8并不是队首元素,但出队的时候仍然让元素8首先出队:

要满足以上需求,利用线性数据结构并非不能实现,但是时间复杂度较高,最坏时间复杂度O(n),并不是最理想的方式。其实借助二叉堆可以大大降低时间复杂度。如下介绍。

二叉堆特性

最大堆的堆顶是整个堆中的最大元素

最小堆的堆顶是整个堆中的最小元素

因此,用最大堆来实现最大优先队列,每一次入队操作就是堆的插入操作,每一次出队操作就是删除堆顶节点。如下演示:

借助堆实现优先队列

入队操作(插入元素5):

(1) 首先将元素5插入到树的末尾

(2) 向上调整,找到5合适位置,使得满足大根堆

出队操作(删除根节点):

(1).把原堆顶节点10“出队”

(2).最后一个节点1替换到堆顶位置

(3).节点1下沉,节点9成为新堆顶

代码实现

# coding:utf-8

'''

普通队列:先进先出,插入在队尾,删除在队头

优先队列:优先队列具有最高级先出 (first in, largest out)的行为特征。通常采用堆数据结构来实现。

堆是完全二叉树

'''

class priorityQueue(object):

def __init__(self):

self.queue = []

def put(self,val):

# 向最小堆中插入元素,需要调整,直到满足最小堆的要求

self.queue.append(val)

cur = len(self.queue) - 1

while cur > 0:

parent = (cur - 1) // 2

if self.queue[parent] > self.queue[cur]:

self.queue[parent],self.queue[cur] = self.queue[cur],self.queue[parent]

else:

break

cur = parent

def get(self):

first = self.top()

last = self.queue.pop()

if not self.empty():

self.queue[0] = last

cur = 0

left = 2 * cur + 1

right = 2 * cur + 2

if left >= len(self.queue) or right >= len(self.queue):

break

if self.queue[cur] <= min(self.queue[left],self.queue[right]):

break

if self.queue[left] < self.queue[right]:

self.queue[left],self.queue[cur] = self.queue[cur],self.queue[left]

cur = left

else:

self.queue[right],self.queue[cur] = self.queue[cur],self.queue[right]

cur = right

return first

def find(self,val):

return val in self.queue

def getIndex(self,index):

if index >= len(self.queue):

raise Exception("The index is out of range!")

return self.queue[index]

def top(self):

# 取堆的根元素

if self.empty():

raise Exception("The Queue is Empty!")

return self.queue[0]

def empty(self):

return len(self.queue) == 0

海量数据中寻找K大数

借助python优先队列包来实现优先队列。时间复杂度为nlog(k).

# coding:utf-8

from queue import PriorityQueue

# 适合海量数据的o(nlogk)的方法

def heapFindNk(nums,k):

pq = PriorityQueue()

for num in nums:

pq.put(num)

if pq.qsize() > k:

pq.get()

res = []

while pq.qsize():

res.append(pq.get())

return res

nums = [4,5,1,2,0]

k = 2

print(heapFindNk(nums,k))

参考博客:

https://www.sohu.com/a/256022793_478315

https://baike.baidu.com/item/%E4%BC%98%E5%85%88%E9%98%9F%E5%88%97/9354754?fr=aladdin

优先队列如何使用Python实现及海量数据中寻找K大数相关教程

微服务架构环境下运维如何应对各种挑战

微服务架构环境下,运维如何应对各种挑战? 一. 微服务架构面临的挑战 1 微服务核心价值:3S 2 微服务架构带来的运维挑战 1)单服务流量激增时扩容 2)调用链条变长,调用关系更加复杂 3)微服务拆分导致故障点增多 ▼▼▼▼▼ 1)单服务变更性能影响如何评

如何用终端命令打开一个网址? 简简单单 - 快快乐乐

如何用终端命令打开一个网址? 简简单单 - 快快乐乐 如何用终端命令打开一个网址? 简简单单 - 快快乐乐 JERRY_Z. ~ 2020 / 10 / 1 转载请注明出处!?? 文章目录 如何用终端命令打开一个网址? 简简单单 - 快快乐乐 一、如何才能让终端识别一个命令 二、.exe

如何实现bilibili最新头部景深效果~炫酷

如何实现bilibili最新头部景深效果~炫酷 #如何实现bilibili最新头部景深效果~炫酷 最近烟雨仔注意到 B站 主页导航栏头部有个相当炫酷的交互效果, 类似于摄影里面的 小景深 , 除了聚焦的人物, 其他前景和背景都是模糊状态. 最炫酷的地方在于, 鼠标左右移动, 会

C#-运算符以及运算符的优先级

C#-运算符以及运算符的优先级 C#语言提供了3大类运算符 一元运算符:一个操作数,比如i++ 二元运算符:比如x+y 三元运算符:只有一个:“?:”。 点运算符 指定类型或命名空间的成员,如System.Console.WriteLine(“hello”); 圆括号运算符() (1)制定表

Spark(8) -- Spark的RDD创建

Spark(8) -- Spark的RDD创建 ?如何将数据封装到RDD集合中,主要有两种方式: 并行化本地集合(Driver Program中)和引用加载外部存储系统(如HDFS、Hive、HBase、Kafka、Elasticsearch等)数据集。 官方文档:resilient-distributed-datasets-rdds 1. RDD的创

如何理解 JS 异步编程的,EventLoop、消息队列,什么是宏任务,

如何理解 JS 异步编程的,EventLoop、消息队列,什么是宏任务,什么是微任务? JS 异步编程 JavaScript 语言的执行环境是单线程的,一次只能执行一个任务,多任务需要排队等候,这种模式可能会阻塞代码,导致代码执行效率低下。为了避免这个问题,出现了异步

ROS 学习踩坑笔记3-如何使用VScode IDE (安装+打开工作空间+Cma

ROS 学习踩坑笔记3-如何使用VScode IDE (安装+打开工作空间+Cmake编译+debug)- 持续更新 之前一直使用Roboware对ROS 的工作空间进行编辑,编译和测试,但是用于Roboware已经不再更新,因此近期转换到VScode这个IDE,发现还是很好用的,以下为VScode简略安装

Spring Boot第四弹,一文教你如何无感知切换日志框架?

Spring Boot第四弹,一文教你如何无感知切换日志框架? 前言 Spring Boot 版本 什么是日志门面? 如何做到无感知切换? 如何切换? 引入依赖 指定配置文件 日志如何配置? 总结 首先要感谢一下读者朋友们的支持,你们每一个的赞都是对陈某最大的肯定,陈某也

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值