【数据结构】实验六:队列

news2024/10/7 20:29:32

实验六  队列

一、实验目的与要求

1)熟悉C/C++语言(或其他编程语言)的集成开发环境;

2)通过本实验加深对队列的理解,熟悉基本操作;

3  结合具体的问题分析算法时间复杂度。

二、实验内容

  设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。

  循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。

你的实现应该支持如下操作:

MyCircularQueue(k): 构造器,设置队列长度为 k 。

Front: 从队首获取元素。如果队列为空,返回 -1 。

Rear: 获取队尾元素。如果队列为空,返回 -1 。

enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。

deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。

isEmpty(): 检查循环队列是否为空。

isFull(): 检查循环队列是否已满。

三、实验结果

1)请将调试通过的源代码粘贴在下面。(代码注意书写规范、主要模块要有功能注释)

源代码:

#include <iostream>
using namespace std;

template <typename T>
class MyCircularQueue{
	T * data;//当前位置的数据 
	int front,rear,size;//头指针、尾指针、队列长度 
public:
	//MyCircularQueue(k): 构造器,设置队列长度为 k 。
	MyCircularQueue(int k=0){
		data=new T[k+1];//k+1 -> 区分isEmpty和isFull的判断条件 
		front=rear=0;
		size=k+1;
	}
	//Front: 从队首获取元素。如果队列为空,返回 -1 。
	T Front(){
		if(isEmpty()){
			return -1;
		}
		else{
			return data[front];
		}
	}
	//Rear: 获取队尾元素。如果队列为空,返回 -1 。
	T Rear(){
		if(isEmpty()){
			return -1;
		}
		else{
			return data[rear-1];
		}
	}
	//enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
	bool enQueue(T value){
		if(isFull()){
			return 0;
		}
		else{
			data[rear]=value;
			rear=(rear+1)%size;
			return 1;
		}
	} 
	//deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
	bool deQueue(){
		if(isEmpty()){
			return 0;
		}
		else{
			front=(front+1)%size;
			return 1;
	    }
	}
	//isEmpty(): 检查循环队列是否为空。
	bool isEmpty(){
		if(rear==front){
			return 1;
		}
		else{
			return 0;
		}
	}
	//isFull(): 检查循环队列是否已满。
	bool isFull(){
		if((rear+1)%size==front){
			return 1;
		}
		else{
			return 0;
		}
	}
};

int main(){
    //初始化循环链表
	int len;
	cout<<"Please input the length of your queue"<<endl;
	cin>>len; 
	MyCircularQueue <int> queue(len);
	
	//查看空表 
	if(queue.isEmpty() ==1){
		cout<<"The current queue is empty"<<endl;
	}
	else{
		cout<<"The current queue is not empty"<<endl;
	}
	cout<<"The front now is "<<queue.Front() <<endl;
	cout<<"The rear now is "<<queue.Rear() <<endl;
	cout<<endl;
	
	//输入元素 
	int times;
	cout<<"Please select the times you want to input"<<endl;
	cin>>times;
	int i=0;
	for(;i<times;i++){
		int value;
		cout<<"Please input your value"<<endl;
		cin>>value;
		int t=queue.enQueue(value); 
		if(t==1){
			cout<<"Valid input"<<endl;
		}
		else{
			cout<<"Invalid input"<<endl;
			break;
		}
	}
	cout<<endl;
	
	//判断输入后的情况 
	if(queue.isEmpty() ==1){
		cout<<"The current queue is empty"<<endl;
	}
	else{
		cout<<"The current queue is not empty"<<endl;
	}
	cout<<"The front now is "<<queue.Front() <<endl;
	cout<<"The rear now is "<<queue.Rear() <<endl;
	cout<<endl;
	
	//删除元素 
	int dels;
	cout<<"Please select the times you want to delete"<<endl;
	cin>>dels;
	int ii=0;
	for(;ii<dels;ii++){
		int tt=queue.deQueue(); 
		if(tt==1){
			cout<<"Valid delete"<<endl;
		}
		else{
			cout<<"Invalid delete"<<endl;
			break;
		}
	}
	cout<<endl;
	
	//判断删除后的情况
	if(queue.isEmpty() ==1){
		cout<<"The current queue is empty"<<endl;
	}
	else{
		cout<<"The current queue is not empty"<<endl;
	}
	cout<<"The front now is "<<queue.Front() <<endl;
	cout<<"The rear now is "<<queue.Rear() <<endl;
	cout<<endl;
	
	return 0;
}

结果展示:

2)请分析你程序中每个功能模块的算法时间复杂度。

构造循环队列,只需要设置队列长度为k+1并设置相应数组,同时初始头指针和尾指针为0即可。所以,时间复杂度为O(1)。

判断循环队列是否为空队列,只需要判断头指针是否与尾指针重合即可,即return(rear==front)。所以,时间复杂度为O(1)。

判断循环队列是否为空队列,只需要判断尾指针加一取余后是否与头指针重合即可,即return((rear+1)%size==front)。所以,时间复杂度为O(1)。

获取队首元素,只需要先判断循环队列是否为空队列,如果队列非空则直接返回头指针所对应的元素。所以,时间复杂度为O(1)。

获取队尾元素,只需要先判断循环队列是否为空队列,如果队列非空则直接返回尾指针所对应的元素。所以,时间复杂度为O(1)。

向循环队列插入一个元素,只需要先判断循环队列是否为满队列,如果队列非满则直接插入输入元素并重置尾指针。所以,时间复杂度为O(1)。

从循环队列中删除一个元素,只需要先判断循环队列是否为空队列,如果队列非空则直接改变头指针的位置,即可删除队首元素。所以,时间复杂度为O(1)。

 


其他:

#include<stdlib.h>
#include<iostream>
using namespace std;
#define SIZE 6
#define Type char
typedef struct{
	Type *elem;
	int front,rear,length;//注意,队列的所谓的指针不是指针,是int 
}Queue;
bool isEmpty(Queue &Q)//: 检查循环队列是否为空。
{
	if(Q.rear==Q.front)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
bool isFull(Queue &Q)//: 检查循环队列是否已满。
{
	if((Q.rear+1)%Q.length==Q.front)
	{
		return true;
	}
	else
	{
		return false;
	}
}
void MyCircularQueue(Queue &Q,int k)//: 构造器,设置队列长度为 k 。
{
	Q.length=k;
	Q.elem=new Type[Q.length];
	Q.front=Q.rear=0;
	cout<<"长度为k的队列构造完毕"<<endl;
}
int Front(Queue &Q,Type &e)//: 从队首获取元素。如果队列为空,返回 -1 。
{
	if(isEmpty(Q))
	{
		cout<<"空队列"<<endl; 
		return -1;
	}
	else
	{
		e=Q.elem[Q.front];
		cout<<"非空"<<endl; 
		cout<<"队首元素"<<e<<"获取成功"<<endl;
		return 1;
	}
}
int Rear(Queue &Q,Type &e)//: 获取队尾元素。如果队列为空,返回 -1 。
{
	if(isEmpty(Q))
	{
		cout<<"空队列"<<endl;
		return -1;
	}
	else
	{
		cout<<"非空"<<endl;
		if(Q.rear==0)
		{
			e=Q.elem[5];
			cout<<"队尾元素"<<e<<"获取成功"<<endl;
			return 1;
		}
		else
		{
			e=Q.elem[Q.rear-1];
			cout<<"队尾元素"<<e<<"获取成功"<<endl;
			return 1;
		}
	}
}
bool enQueue(Queue &Q,Type value)//: 向循环队列插入一个元素。如果成功插入则返回真。
{
	if(!isFull(Q))
	{
		cout<<"非满"<<endl;
		Q.elem[Q.rear]=value;//因为初始front和rear都是0开头,所以与下标一致 
		Q.rear=(1+Q.rear)%Q.length;
		cout<<value<<"已经插入"<<endl;
		return true;
	}
	else
	{
		cout<<"队列已满!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<value<<"无法入队"<<endl; 
		return false;
	}
}
int deQueue(Queue &Q,Type &e)//: 从循环队列中删除一个元素。如果成功删除则返回真。
{
	if(isEmpty(Q))
	{
		cout<<"已空"<<endl;
		return -1;
	}
	else
	{
		cout<<"非空"<<endl;
		e=Q.elem[Q.front];
		Q.front=(Q.front+1)%Q.length;
		cout<<"删除了"<<e<<endl;
		return 1;
	}
}
int getlength(Queue &Q)
{
	int len;
	len=(Q.rear-Q.front+Q.length)%Q.length;
	return len;
}
int main()
{
	Queue a;
	Type temp;
	Type e[11]={'a','b','c','d','e','f','g','h','i','j','k'};
	int length=SIZE;
	MyCircularQueue(a,length);//初始化 
	enQueue(a,e[0]);//入队,到第一次满 
	enQueue(a,e[1]);
	enQueue(a,e[2]);
	enQueue(a,e[3]);
	enQueue(a,e[4]);
	if(isFull(a))//判断是否已满 
	{
		cout<<"队列已满!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"<<endl;
	} 
	deQueue(a,temp);//删除队首 
	Front(a,temp);//输出队首队尾元素 
	Rear(a,temp);
	enQueue(a,e[5]);//插入两次,看看当队列已满,溢出时的效果  证明了程序在溢出时的插入无效 
	enQueue(a,e[6]);//队列以满,试图插入的这个是g,查看满后队列是否可以阻止进入 
	cout<<"该队列长度为"<<getlength(a)<<endl; 
	Front(a,temp);//再次确定   1.队列确实是循环使用的,即0号位被再次利用   2.溢出的那一次插入无效 
	Rear(a,temp);
} 

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

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

相关文章

Qt完成文本转换为语音播报与保存(系统内置语音引擎)(一)

一、前言 在当今数字化社会,人们对于交互式应用程序的需求越来越高。除了传统的图形用户界面,语音交互也成为了一种流行的交互方式。在这种情况下,将文本转换为语音成为了一项重要的技术,它可以为用户提供更加人性化和便捷的交互方式。在此背景下,Qt提供了QTextToSpeech类…

python测试开发面试常考题:装饰器

目录 简介 应用 第一类对象 装饰器 描述器descriptor 资料获取方法 简介 Python 装饰器是一个可调用的(函数、方法或类)&#xff0c;它获得一个函数对象 func_in 作为输入&#xff0c;并返回另一函数对象 func_out。它用于扩展函数、方法或类的行为。 装饰器模式通常用…

flask中的常用装饰器

flask中的常用装饰器 Flask 框架中提供了一些内置的装饰器&#xff0c;这些装饰器可以帮助我们更方便地开发 Web 应用。以下是一些常用的 Flask 装饰器&#xff1a; app.route()&#xff1a;这可能是 Flask 中最常用的装饰器。它用于将 URL 路由绑定到一个 Python 函数&#x…

【前端知识】React 基础巩固(三十五)——ReduxToolKit (RTK)

React 基础巩固(三十五)——ReduxToolKit (RTK) 一、RTK介绍 Redux Tool Kit &#xff08;RTK&#xff09;是官方推荐的编写Redux逻辑的方法&#xff0c;旨在成为编写Redux逻辑的标准方式&#xff0c;从而解决上面提到的问题。 RTK的核心API主要有如下几个&#xff1a; confi…

Pytorch深度学习-----神经网络的基本骨架-nn.Module的使用

系列文章目录 PyTorch深度学习——Anaconda和PyTorch安装 Pytorch深度学习-----数据模块Dataset类 Pytorch深度学习------TensorBoard的使用 Pytorch深度学习------Torchvision中Transforms的使用&#xff08;ToTensor&#xff0c;Normalize&#xff0c;Resize &#xff0c;Co…

Cadence OrCAD Capture绘制符号时缩小栅格距离的方法图文教程

🏡《总目录》   🏡《宝典目录》 目录 1,概述2,问题概述3,常规方法4,正确方法3,总结1,概述 本文简单介绍,使用Capture软件绘制原理图符号时,缩小或自定义栅格间距的方法。 2,问题概述 如下图所示,在进行原理图符号绘制时,管脚元件实体的线条等,均只能放置在栅…

佰维存储面向旗舰智能手机推出UFS3.1高速闪存

手机“性能铁三角”——SoC、运行内存、闪存决定了一款手机的用户体验和定位&#xff0c;其中存储器性能和容量对用户体验的影响越来越大。 针对旗舰智能手机&#xff0c;佰维推出了UFS3.1高速闪存&#xff0c;写入速度最高可达1800MB/s&#xff0c;是上一代通用闪存存储的4倍以…

C++ 缺省参数

1.缺省参数 一般情况下&#xff0c;函数调用时的实参个数应与形参相同&#xff0c;但为了方便地使用函数&#xff0c;C允许定义具有缺省参数的函数&#xff0c;这种函数调用时&#xff0c;实参个数可以与形参不相同。 缺省参数指在定义函数时为形参指定缺省值&#xff08;默认…

SSIS对SQL Server向Mysql数据转发表数据 (二)

1、在SQL Server数据库创建一个数据库表&#xff1a;users USE [Test1] GO/****** Object: Table [dbo].[users] Script Date: 2023/7/27 16:25:11 ******/ SET ANSI_NULLS ON GOSET QUOTED_IDENTIFIER ON GOCREATE TABLE [dbo].[users]([id] [int] IDENTITY(1,1) NOT NUL…

【数据结构】实验八:树

实验八 树 一、实验目的与要求 1&#xff09;理解树的定义&#xff1b; 2&#xff09;掌握树的存储方式及基于存储结构的基本操作实现&#xff1b; 二、 实验内容 题目一&#xff1a;采用树的双亲表示法根据输入实现以下树的存储&#xff0c;并实现输入给定结点的双亲结点…

实验二十五、压控振荡电路的测试

一、题目 研究压控振荡电路输出波形频率随输入电压幅度的变化。 二、仿真电路 仿真电路如图1所示。集成运放采用 LM324AJ&#xff0c;其电源电压为 15 V。输入直流电压采用虚拟电压源&#xff0c;锯齿波才用函数发生器产生的锯齿波输出。 三、仿真内容 &#xff08;1&…

[自然语言处理] 自然语言处理库spaCy使用指北

spaCy是一个基于Python编写的开源自然语言处理库。基于自然处理领域的最新研究&#xff0c;spaCy提供了一系列高效且易用的工具&#xff0c;用于文本预处理、文本解析、命名实体识别、词性标注、句法分析和文本分类等任务。 spaCy的官方仓库地址为&#xff1a;spaCy-github。本…

mysql的整体架构

服务层-引擎层-硬盘层 一条语句执行的整体过程: 先建立连接&#xff08;mysql -h -p 密码&#xff09;–预处理-词法分析-语法分析-优化器选择用什么索引表如何连接等-执行器 到这里都是属于server层&#xff0c;大多数功能包括视图&#xff0c;存储过程&#xff0c;触发器都是…

透明屏能在商业广告中使用吗?

透明屏是一种新型的显示技术&#xff0c;它可以将图像或文字显示在透明的玻璃或塑料材料上&#xff0c;使得观看者可以同时看到背后的物体。 这种技术在商业广告、展览、零售和家庭娱乐等领域有着广泛的应用前景。 首先&#xff0c;透明屏可以用于商业广告。传统的广告牌通常…

100个网络安全测试面试题

1、Burpsuite常用的功能是什么&#xff1f; 2、reverse_tcp和bind_tcp的区别&#xff1f; 3、拿到一个待检测的站或给你一个网站&#xff0c;你觉得应该先做什么&#xff1f; 4、你在渗透测试过程中是如何敏感信息收集的&#xff1f; 5、你平时去哪些网站进行学习、挖漏洞提交到…

React 前端应用中快速实践 OpenTelemetry 云原生可观测性(SigNoz/K8S)

OpenTelemetry 可用于跟踪 React 应用程序的性能问题和错误。您可以跟踪从前端 web 应用程序到下游服务的用户请求。OpenTelemetry 是云原生计算基金会(CNCF)下的一个开源项目&#xff0c;旨在标准化遥测数据的生成和收集。已成为下一代可观测平台的事实标准。 React(也称为 Re…

基于物联网、视频监控与AI视觉技术的智慧电厂项目智能化改造方案

一、项目背景 现阶段&#xff0c;电力行业很多企业都在部署摄像头对电力巡检现场状况进行远程监控&#xff0c;但是存在人工查看费时、疲劳、出现问题无法第一时间发现等管理弊端&#xff0c;而且安全事件主要依靠人工经验判断分析、管控&#xff0c;效率十分低下。 为解决上述…

一文了解什么是Selenium自动化测试?

目录 一、Selenium是什么&#xff1f; 二、Selenium History 三、Selenium原理 四、Selenium工作过程总结&#xff1a; 五、remote server端的这些功能是如何实现的呢&#xff1f; 六、附&#xff1a; 一、Selenium是什么&#xff1f; 用官网的一句话来讲&#xff1a;Sel…

Vue2基础六、组件通信

零、文章目录 Vue2基础六、组件通信 1、组件通信 &#xff08;1&#xff09;组件通信是什么 组件通信, 就是指 组件与组件 之间的数据传递。 组件的数据是独立的&#xff0c;无法直接访问其他组件的数据。 想使用其他组件的数据&#xff0c;就需要组件通信 &#xff08;…

QTday2信号和槽

点击登录按钮,关闭Widget登录窗口,打开QQList窗口 widget.cpp #include "widget.h"void my_setupUI(Widget *w);Widget::Widget(QWidget *parent): QWidget(parent) {my_setupUI(this); }Widget::~Widget() { }void Widget::login_slots() {//fixemit jump_signal(…