首页 > 其他分享 >高效利用队列的空间

高效利用队列的空间

时间:2023-11-11 20:45:34浏览次数:20  
标签:frontCount 高效 end 队列 front MAXSIZE endCount 空间 return

  大家都知道队列是可以用数组来模拟的,可以先开辟一段定长的数组空间,然后分别使用两个变量head和tail来代指队列的头和尾,从而维护整个队列,相信到这里大家都比较熟悉。不过这种做法是有弊端的,比如说下图这种情况

  假设经过不断地增删元素,Head和Tail已经来到了数组最后两个位置,这时候整个队列中只有两个元素,并且我们也不能再增加元素了,因为已经到达了容量的上限。然而,这时候前面一大片连续空间就造成了浪费。因此我们重新设想一下

  这是另外一种构思,此时队列当中存有三个元素,那么该怎么实现呢?

#define MAXSIZE (1 << 16)

template <typename _Tp>
struct fifo {
	uint16_t front = 1;
	uint16_t end = 1;
	int frontCount = -0x3f3f3f3f;
	int endCount = -0x3f3f3f3f;

	_Tp arr[MAXSIZE];
}

  对于front和end两个变量,可以用无符号整型来实现,当无符号整型溢出的时候,会自然的变成0,问题就爽快的解决了。不过这里还引入了两个变量,frontCount和endCount,这是为了判断front是在end的前面还是后面。换句话说,当end发生溢出的时候,end就来到了front前面,这时候endCount就加1,frontCount同理。

 

    bool empty() {
		if (endCount > frontCount)
			return false;
		
		return (front == end) ? true : false;
	}

	bool full() {
		if (endCount > frontCount && end == front)
			return true;

		return false;
	}

	std::size_t size() {
		if (full())
			return MAXSIZE;
		else if (empty())
			return 0;
		else if (frontCount == endCount)
			return (end - front);
		else 
			return (MAXSIZE - front + end);
	}

  以上是判断队列容量的一些相关成员函数,实现都比较简略,较为关键的是入队和出队的操作实现。

    void push(_Tp&& element) {
		if (full()) {
			std::cerr << "Full\n";
			return;
		}

		if (((uint16_t) (end + 1)) == 0)
			++endCount;

		arr[++end] = element;
	}

	void push(const _Tp& element) {
		if (full()) {
			std::cerr << "Full\n";
			return;
		}

		if (((uint16_t) (end + 1)) == 0)
			++endCount;

		arr[++end] = element;
	}

	std::optional<_Tp> pop() {
		if (empty()) 
			return std::nullopt;

		if (((uint16_t) (front + 1)) == 0)
			++frontCount;

		return arr[++front];
	}

  有个小区别,这里的front指向的位置在逻辑上是不存储元素的,其它的和开篇所讲的都差不多。那么,对于(end + 1) ,为什么要加一个强制转换呢?因为如果不加的话,end和1进行运算之后就提升为了int类型,这时候结果是int类型的,它不会因为溢出而变成0。

  完整代码:

#include <iostream>
#include <cstdint>
#include <optional>

#define MAXSIZE (1 << 16)

template <typename _Tp>
struct fifo {
	uint16_t front = 1;
	uint16_t end = 1;
	int frontCount = -0x3f3f3f3f;
	int endCount = -0x3f3f3f3f;

	_Tp arr[MAXSIZE];

	void push(_Tp&& element) {
		if (full()) {
			std::cerr << "Full\n";
			return;
		}

		if (((uint16_t) (end + 1)) == 0)
			++endCount;

		arr[++end] = element;
	}

	void push(const _Tp& element) {
		if (full()) {
			std::cerr << "Full\n";
			return;
		}

		if (((uint16_t) (end + 1)) == 0)
			++endCount;

		arr[++end] = element;
	}

	std::optional<_Tp> pop() {
		if (empty()) 
			return std::nullopt;

		if (((uint16_t) (front + 1)) == 0)
			++frontCount;

		return arr[++front];
	}

	bool empty() {
		if (endCount > frontCount)
			return false;
		
		return (front == end) ? true : false;
	}

	bool full() {
		if (endCount > frontCount && end == front)
			return true;

		return false;
	}

	std::size_t size() {
		if (full())
			return MAXSIZE;
		else if (empty())
			return 0;
		else if (frontCount == endCount)
			return (end - front);
		else 
			return (MAXSIZE - front + end);
	}
};

  相信看完本篇,你也多多少少有收获,喜欢的可以动动手指点赞加关注!  

标签:frontCount,高效,end,队列,front,MAXSIZE,endCount,空间,return
From: https://www.cnblogs.com/ChebyshevTST/p/17826324.html

相关文章

  • 抖音小程序开发:打造高效餐饮团购平台的技术指南
    在餐饮行业,通过抖音小程序开发一个高效的团购平台,可以为餐厅提供更广泛的曝光,增加销售机会。本文将从技术角度出发,为您提供一份详细的抖音小程序开发指南,助您打造一流的餐饮团购平台。一、确定需求和功能在开始抖音小程序的开发之前,首先要明确平台的需求和功能。这包括但不限于菜单......
  • 《空间三角面片对相交判断算法》的matlab实现
    function[flag]=InsectTriPatch(T1,T2)%判断两个空间三角形面片是否相交%T1=[000;%200;%01.50;%001];%T2=[00-1;%20-1;%02-1;%001];%出自:《空间三角面片对相交判断算法......
  • 改善Go语言编程质量的50个有效实践,技能落地总结50个高效Go程序设计技巧
    改善Go语言编程质量的50个有效实践,技能落地总结50个高效Go程序设计技巧 慕课专栏:《改善Go语言编程质量的50个有效实践》Go语言是Google大牛团队(RobertGriesemer、RobPike以及KenThompson)设计的一种静态类型、编译型编程语言,支持垃圾回收和轻量级并发,它于2009年11月诞......
  • 从低维空间到高维空间
    前言我们通常接触到的维度是\(1\sim3\)维,我们的认知大部分都是从这些维度得到的,虽然我们常常会想象高维空间的事物,但是难免有一些不同之处。我们理解一个事物,通常要转换为图像,但是高维空间的事物显然我们无法在脑海中形成图像,只能用数学来解释。正文先放结论:在极高维度下,球的......
  • 从低维空间到高维空间
    前言我们通常接触到的维度是\(1\sim3\)维,我们的认知大部分都是从这些维度得到的,虽然我们常常会想象高维空间的事物,但是难免有一些不同之处。我们理解一个事物,通常要转换为图像,但是高维空间的事物显然我们无法在脑海中形成图像,只能用数学来解释。正文先放结论:在极高维度下,球的......
  • 高效技巧:Node.js文件写入
    文件写入是 Node.js 中的一项重要任务,它允许你将数据保存到本地文件系统中,供后续使用。这个功能在许多应用中都有广泛的应用,包括数据备份、日志记录、配置文件更新等。在本文,我们将介绍如何在Node.js中执行文件写入操作,提供基本概念、常用方法、使用场景和实践案例。基本概念在......
  • 【chatgpt问答记录】双端队列、栈和函数调用栈
    collections.deque和queue.Queue的区别Q:collections.deque()跟queue.Queue()有什么区别?collections.deque()和queue.Queue是两种不同的数据结构,它们有一些区别:实现方式:collections.deque()是Python标准库提供的双端队列数据结构,使用双向链表实现,具有高效的在两端进行......
  • Linux平台下的进程地址空间
    “地址空间”在之前讨论C++内存管理,以及平常写C/C++程序时,有如下的存储空间布局:虽然不是所有的实例都按照上图所示的分区排布,但这是一种最典型的做法,足以说明问题。这个示意图与在C++内存管理中所示的相似,但还是需要说明一下:(方便起见,暂时将这个空间称为程序的“地址空间”)在32位......
  • 前端开发进阶:前端开发中如何高效渲染大数据量?
    在日常工作中,有时会遇到一次性往页面中插入大量数据的场景,在数栈的离线开发(以下简称离线)产品中,就有类似的场景。本文将通过分享一个实际场景中的前端开发思路,介绍当遇到大量数据时,如何实现高效的数据渲染,以达到提升页面性能和用户体验的目的。渲染大数据量时遇到的问题在离线的数据......
  • 波士顿大学「鸭嘴兽-70B」登顶Hugging Face大模型排行榜!高效数据集+独特LoRA微调是关
    HuggingFace上的开源大模型排名榜又更新了,这次荣登榜一的是:鸭嘴兽(Platypus2-70B)!和现在抱脸开源榜单上大部分的模型一样,鸭嘴兽是来自波士顿大学的研究人员基于Llama2微调而来。同时,鸭嘴兽的进步就像之前所有的开源大模型那样:在提升性能的同时,使用更少的计算资源和数据。一个13B的......