首页 > 其他分享 >2.队列

2.队列

时间:2022-11-08 11:45:10浏览次数:35  
标签:head 队列 next int _- front rear

环形队列

环形队列理论

环形队列的本质就是一个数组。用两个标识分别表示对头和队尾,在逻辑上呈现为一个环形
当队列不为空时,对头指向头元素,队尾指向最后一个元素的下一个元素

下图为空队列(队列的初始状态)

入队:从对尾入队,arr[rear_] = val; (rear_+1) % arr.length();
出队:从对头出队,(head_+1) % arr.length();

考虑到一个问题,队列空与队列满的表示都为 head_ = rear_; 这显然是错误的。为了解决这个问题,就不能将数组中的全部空间都使用(这会导致对头与队尾相遇,这与对空的判断吻合)。
而要预留一个数组元素

对满状态如图:

那么堆满的判断就变成了 (rear_+1) % arr.length() == head_

环形队列代码

#include<iostream>
using namespace std;

class Queue
{
public:
	Queue(int size = 10)
		:cap_(size)
		, front_(0)
		, rear_(0)
		, pQue_(new int[cap_])
	{
	}
	~Queue()
	{
		delete[] pQue_;
		pQue_ = nullptr;
	}
	void push(int val)
	{
		if (full())
		{
			expand(2 * cap_);
		}
			pQue_[rear_] = val;
			rear_ = (rear_ + 1) % cap_;
	}
	void pop()
	{
		if (empty()) 
			throw " queue is empty";
		else
		{
			front_ = (front_ + 1) % cap_;
		}
	}
	int front() const
	{
		if (empty()) throw "queue is empty";
		else
		{
			return pQue_[front_];
		}
	}
	int back() const
	{
		if (empty()) throw "queue is empty";
		else
		{
			return pQue_[(rear_ - 1 + cap_) % cap_];
			//为了解决访问数组末尾元素
			//当要访问最后一个元素时,rear_位于数组头
		}
	}
	int size()
	{
		int size = 0;
		for (int i = front_; i != rear_; i=((i+1)%cap_))
		{
			size++;
		}
		return size;
	}

	bool full() const
	{
		if ((rear_ + 1)%cap_ == front_)
			return true;
		else
			return false;
	}
	bool empty() const
	{
		if (rear_ == front_)
			return true;
		else
			return false;
	}

private:

	void expand(int size)
	{
		//不可以和栈、数组一样 使用memcpy,来进行内存拷贝
		int* ret = new int[size];
		int num = 0;
		for (int i = front_; i != rear_; num++,i=(i + 1) % cap_)
		{
			ret[num] = pQue_[i];
		}
		delete[] pQue_;
		pQue_ = ret;
		front_ = 0;
		rear_ = num;
		cap_ = size;
	}

	int cap_;
	int* pQue_;
	int front_;
	int rear_;
};

不能使用memcpy的原因

这使拷贝变得无意义

链式队列 (基于双向循环链表)

与链式栈相同,都是为了解决当数组内元素过多时,扩容的事件负责都为O(n),浪费时间。若采用链式队列,就可以使扩容操作的时间复杂度将为O(1)

#include<iostream>
using namespace std;

class listQueue
{
public:
	listQueue()
	{
		head_ = new Node();
		head_->next_ = head_;
		head_->pre_ = head_;
	}
	~listQueue()
	{
		while (head_->next_ != head_)
		{
			Node* t = head_->next_;
			head_->next_ = head_->next_->next_;
			t->next_->pre_ = head_;
			delete t;
		}
		delete head_;
		head_ = nullptr;
	}
	void  push(int val)
	{
		Node* p = head_->pre_;
		Node* node = new Node(val);
		node->next_ = head_;
		node->pre_ = p;
		head_->pre_ = node;
		p->next_ = node;
	}
	void pop()
	{
		Node* p = head_->next_;
		head_->next_ = head_->next_->next_;
		p->next_->pre_ = head_;
		delete p;
	}
	int front()
	{
		if (head_->next_ != head_)
		{
			return head_->next_->data_;
		}
		else throw "is empty";
	}
	int back()
	{
		if (head_->pre_ != head_)
		{
			return head_->pre_->data_;
		}
		else throw "is empty";
	}
private:

	struct Node
	{
		Node(int data = 0)
			:data_(data)
			,pre_(nullptr)
			,next_(nullptr)
		{ }
		int data_;
		Node* pre_;
		Node* next_;
	};
	Node* head_; //指向头节点
};

标签:head,队列,next,int,_-,front,rear
From: https://www.cnblogs.com/zyx-c/p/16869133.html

相关文章

  • JS数据结构与算法-队列结构
    队列结构一.认识队列受限的线性结构:我们已经学习了一种受限的线性结构:栈结构.并且已经知道这种受限的数据结构对于解决某些特定问题,会有特别的效果.下面,我们再......
  • 【Leetcode】 剑指offer:栈与队列 --Day01
    写在前面2023届秋招形势严峻,作为2024届本科生倍感压力。时间紧迫,需要加快脚步。计划之一是在未来的36天时间里通关Leetcode的剑指offer系列算法题。这一系列的学习周期为......
  • leetcode(34)优先队列系列题目
    218.天际线问题用SortedList存边界,每次删除或加入边界判断最高点是否变化classSolution:defgetSkyline(self,buildings:List[List[int]])->List[List[int]]:......
  • 025 通过链表学Rust之使用栈实现双端队列
    介绍视频地址:https://www.bilibili.com/video/av78062009/相关源码:https://github.com/anonymousGiga/Rust-link-list详细内容本节我们使用栈来实现双端队列。实现栈栈的实......
  • 14-组件篇之消息队列(3)_ev
                                                   ......
  • 使用单调队列解决 “滑动窗口最大值” 问题
    1\.单调队列的典型问题单调队列是一种用来高效地解决“滑动窗口最大值”问题的数据结构。举个例子,给定一个整数数组,要求输出数组中大小为K的窗口中的最大值,这就是窗口......
  • 13-组件篇之消息队列(2)_ev
    在app端生成一个客户端id到最后面进行去重就做到幂等性  面试重点      存储是最耗时的                   ......
  • 微服务Spring Boot 整合Redis 基于Redis的Stream 消息队列 实现异步秒杀下单
    文章目录​​一、什么是Redis消息队列?​​​​二、Redis消息队列--基于RedisList实现消息队列​​​​三、Redis消息队列--基于Pubsub的消息队列​​​​四、......
  • 阻塞队列 - BlockingQueue
     线程通信的一个工具。在任意时刻,不管并发有多高,在单JVM上面,同一时间永远只有一个线程能够对队列进行入队或者出队操作。1.线程安全的队列;2.队列类型:无限队列、有限队......
  • C++——优先级队列(priority_queue)
    其为队列需要包含头文件#include,其与queue的不同之处在于,可以自定义数据的优先级,让优先级高的排在队列的前面,优先出队;优先队列具有队列的所有特性,包括基本操作,只是在此基......