热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

cringbuffer源码_PythonRingBuffer的实现

RingBuffer,或者说CircularBuffer,是一个长度固定的缓冲区,当从一端插入元素超过指定的最大长度时,缓冲区另一端的元素

RingBuffer,或者说Circular Buffer,是一个长度固定的缓冲区,当从一端插入元素超过指定的最大长度时,缓冲区另一端的元素会溢出。当用户仅对近期一定长度的历史记录感兴趣时,这种数据结构就特别有用。

* 缓冲区的长度固定

* 先进先出

* 当往缓冲区中增加或者删除元素时,其它元素的位置保持不变。

本文介绍了三种实现方法及各自的特点。

# collections.dequeue实现

RingBuffer的一个直观实现是使用Pyhton collections的dequeue(发音deck):

```Python

import collections

import time

d = collections.deque(maxlen=1000)

tm1 = time.time()

for i in range(int(1e6)):

d.append(i)

print(list(d)[:10])

d.clear()

tm2 = time.time()

print("{:.2f}seconds".format(tm2 - tm1))

执行结果如下:

[999000, 999001, 999002, 999003, 999004, 999005, 999006, 999007, 999008, 999009]

0.20seconds

支持的操作有pop, append;以及从左端操作的popleft, appendleft。但没有缓冲区需要的read操作。缓冲区read操作包括两个动作,一是从缓冲区中读取数据;二是在读取后清除掉数据。我们可以通过list(d:dequeue)和clear的组合来实现这一功能。

# 一个有趣的自定义实现

David Ascher在[这篇文章](#Implementing a Ring Buffer [Book])里给出了一个自定义的实现:

```python

class RingBuffer:

""" class that implements a not-yet-full buffer """

def __init__(self,size_max):

self.max = size_max

self.data = []

class __Full:

""" class that implements a full buffer """

def append(self, x):

""" Append an element overwriting the oldest one. """

self.data[self.cur] = x

self.cur = (self.cur+1) % self.max

def get(self):

""" return list of elements in correct order """

ret = self.data[self.cur:]+self.data[:self.cur]

self.data.clear()

return ret

def append(self,x):

"""append an element at the end of the buffer"""

self.data.append(x)

if len(self.data) == self.max: #line 21

self.cur = 0

# Permanently change self's class from non-full to full

self.__class__ = self.__Full

def get(self):

""" Return a list of elements from the oldest to the newest. """

return self.data

x = RingBuffer(1000)

import time

tm1 = time.time()

for i in range(int(1e6)):

x.append(i)

print(x.get()[:10])

tm2 = time.time()

print("{:.2f}seconds".format(tm2 - tm1))

执行结果如下:

[999000, 999001, 999002, 999003, 999004, 999005, 999006, 999007, 999008, 999009]

0.64seconds

这个实现的特点是,使用了数组,而不是双端队列来作为基础存储数据结构。当然由于Ring Buffer的访问特性,我们也基本上只对队头、队尾元素进行操作,所以无论是使用数组还是双端队列,操作复杂度都是O(1)。

另一个值得一提的点是,它使用了动态改变对象_class_实现的方式,避免了不必要的判断语句操作,即在创建之初,缓冲区未满时,每插入一个元素,都要在第19行处进行一次判断;而一旦缓冲区被充满后,RingBuffer对象升级为__Full类,从而行为也从此改变--今后再向缓冲区添加新的元素时,不再进行条件语句判断。

尽管代码做了足够的优化,python内建dequeue的实现性能更高一些。

# 使用C语言的实现-pyringbuf

[sirlark](#sirlark)用C语言实现了一个开源的[RingBuffer](#pyringbuf 0.1b2 : Python Package Index),可以通过pip来安装使用。

pip install pyringbuf

这个模块提供了push, pop, write, read等函数,使用示例如下:

>>> from ringbuf import RingBuffer

>>> R = RingBuffer(5) #choose your buffer size

>>> R.push("a") #push a single character into the buffer

>>> R.pop() #pop a single character

'a'

>>> R.write("bcdef") #fill buffer with many characters at once

>>> R.read(4) #read many characters at once

'bcde'

>>> R.read(1)

'f'

>>> R.read(1) #returns an empty string if the buffer is empty

这个模块以c语言源码提供,使用前需要编译。



推荐阅读
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本题探讨如何通过最大流算法解决农场排水系统的设计问题。题目要求计算从水源点到汇合点的最大水流速率,使用经典的EK(Edmonds-Karp)和Dinic算法进行求解。 ... [详细]
  • Python处理Word文档的高效技巧
    本文详细介绍了如何使用Python处理Word文档,涵盖从基础操作到高级功能的各种技巧。我们将探讨如何生成文档、定义样式、提取表格数据以及处理超链接和图片等内容。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文深入探讨了 Python 中的循环结构(包括 for 循环和 while 循环)、函数定义与调用,以及面向对象编程的基础概念。通过详细解释和代码示例,帮助读者更好地理解和应用这些核心编程元素。 ... [详细]
  • 深入理解Redis的数据结构与对象系统
    本文详细探讨了Redis中的数据结构和对象系统的实现,包括字符串、列表、集合、哈希表和有序集合等五种核心对象类型,以及它们所使用的底层数据结构。通过分析源码和相关文献,帮助读者更好地理解Redis的设计原理。 ... [详细]
  • 本题旨在通过给定的评级信息,利用拓扑排序和并查集算法来确定全球 Tetris 高手排行榜。题目要求判断是否可以根据提供的信息生成一个明确的排名表,或者是否存在冲突或信息不足的情况。 ... [详细]
  • 由二叉树到贪心算法
    二叉树很重要树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。单就面试而言,在 ... [详细]
  • LeetCode: 实现队列与栈的高级应用
    本文介绍如何使用队列和栈实现特定功能,包括动态维护队列元素并计算其平均值,以及栈操作中的优化技巧。 ... [详细]
  • 主要用了2个类来实现的,话不多说,直接看运行结果,然后在奉上源代码1.Index.javaimportjava.awt.Color;im ... [详细]
  • 深入解析:手把手教你构建决策树算法
    本文详细介绍了机器学习中广泛应用的决策树算法,通过天气数据集的实例演示了ID3和CART算法的手动推导过程。文章长度约2000字,建议阅读时间5分钟。 ... [详细]
  • 本文深入探讨了Python中的高阶函数和Lambda表达式的使用方法,结合实际案例解析其应用场景,帮助开发者更好地理解和运用这些强大的工具。 ... [详细]
  • 本文介绍了如何在 C# 和 XNA 框架中实现一个自定义的 3x3 矩阵类(MMatrix33),旨在深入理解矩阵运算及其应用场景。该类参考了 AS3 Starling 和其他相关资源,以确保算法的准确性和高效性。 ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
author-avatar
思铮同学要努力工作
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有