Datawhale组队学习 Task04:队列(2天)
Task04:队列(2天)
队列也是我们经常使用的一种数据结构,如下图所示,购物结账,去食堂打饭等都需要排队,而结账或打饭的顺序与我们排队的顺序是相同的,即谁先排队就为谁先服务。
比如我们发送邮件、打印资料,这些都是队列的具体应用。我们把需要发送的邮件先放到发送队列中,然后按照放入的顺序进行发送,把需要打印的文件先放到打印队列中, 然后按照放入的顺序进行打印。下面我们就来详细介绍“队列”这种数据结构。
1. 队列的定义与操作
1.1 队列的定义
插入(入队)在一端(队尾)进行而删除(出队)在另一端(队首)进行的线性表。即先进先出(First In First Out)的线性表。
例1 :线性表a0,a1,...,an
入队与出队演示。
如上所示,队列也存在两种实现方式,这两种实现方式的对比已经在栈与递归部分进行了解释,在这里就不再赘述了。
1.2 队列的操作
- 入队操作:将数据元素插入队尾。
- 出队操作:移除队首的数据元素。
- 是否为空:判断队中是否包含数据元素。
- 得到队长:获取队中实际包含数据元素的个数。
- 清空操作:移除队中的所有数据元素。
- 获取队首元素。
using System;namespace LinearStruct
{/// <summary>/// 队列的抽象数据类型/// </summary>/// <typeparam name="T">队列中元素的类型</typeparam>public interface IQueue<T> where T : IComparable<T>{/// <summary>/// 获取队列中实际包含元素的个数/// </summary>int Length { get; }/// <summary>/// 获取队首元素/// </summary>T QueueFront { get; }/// <summary>/// 数据元素入队/// </summary>/// <param name="data">要入队的元素</param>void EnQueue(T data);/// <summary>/// 数据元素出队/// </summary>void DeQueue();/// <summary>/// 判断队列中是否包含元素/// </summary>/// <returns>如果包含元素返回false,否则返回true.</returns>bool IsEmpty();/// <summary>/// 从队列中移除所有元素/// </summary>void Clear();}
}
2. 队列的存储与实现
2.1 顺序存储
顺序队列
顺序队列:(Sequence Queue):利用顺序表实现的队列。
实现:
using System;namespace LinearStruct
{/// <summary>/// 用顺序存储结构实现的队列--顺序队列/// </summary>/// <typeparam name="T">顺序队列中元素的类型</typeparam>public class SeqQueue<T> : IQueue<T> where T : IComparable<T>{private readonly SeqList<T> _lst;/// <summary>/// 初始化SeqQueue类的新实例/// </summary>/// <param name="max">SeqQueue中最多包含元素的个数</param>public SeqQueue(int max){if (max <= 0)throw new ArgumentOutOfRangeException();_lst = new SeqList<T>(max);}/// <summary>/// 获取SeqQueue中最多包含元素的个数/// </summary>public int MaxSize{get { return _lst.MaxSize; }}/// <summary>/// 获取SeqQueue中实际包含元素的个数/// </summary>public int Length{get { return _lst.Length; }}/// <summary>/// 获取SeqQueue中的队首元素/// </summary>public T QueueFront{get{if (_lst.IsEmpty())throw new Exception("队列为空,不能得到队首元素.");return _lst[0];}}/// <summary>/// 数据元素入队/// </summary>/// <param name="data">要入队的元素</param>public void EnQueue(T data){if (_lst.Length == _lst.MaxSize)throw new Exception("队列已满,不能入队.");_lst.Insert(_lst.Length, data);}/// <summary>/// 数据元素出队/// </summary>public void DeQueue(){if (_lst.IsEmpty())throw new Exception("队列为空,不能出队.");_lst.Remove(0);}/// <summary>/// 判断队列中是否包含元素/// </summary>/// <returns>如果包含元素返回false,否则返回true.</returns>public bool IsEmpty(){return _lst.IsEmpty();}/// <summary>/// 从队列中移除所有元素/// </summary>public void Clear(){_lst.Clear();}}
}
循环队列
循环队列(Circular Sequence Queue):利用数组采用循环的方式实现的队列。
实现:
using System;namespace LinearStruct
{/// <summary>/// 用顺序存储结构实现的队列--循环队列/// </summary>/// <typeparam name="T">循环队列中元素的类型</typeparam>public class CSeqQueue<T> : IQueue<T> where T : IComparable<T>{private int _pFront;private int _pRear;private readonly T[] _dataset;/// <summary>/// 获取CSeqQueue中实际包含元素的个数/// </summary>public int Length { get; private set; }/// <summary>/// 获取CSeqQueue中最多包含元素的个数/// </summary>public int MaxSize { get; }/// <summary>/// 获取CSeqQueue中的队首元素/// </summary>public T QueueFront{get{if (Length == 0)throw new Exception("队列为空不能得到队首元素.");return _dataset[_pFront];}}/// <summary>/// 初始化CSeqQueue类的新实例/// </summary>/// <param name="max">CSeqQueue中最多包含元素的个数</param>public CSeqQueue(int max){if (max <= 0)throw new ArgumentOutOfRangeException();MaxSize = max;Length = 0;_dataset = new T[MaxSize];_pFront = 0;_pRear = 0;}/// <summary>/// 数据元素入队/// </summary>/// <param name="data">要入队的元素</param>public void EnQueue(T data){if (Length == MaxSize)throw new Exception("队列已满,不能入队.");_dataset[_pRear] = data;_pRear = (_pRear + 1)%MaxSize;Length++;}/// <summary>/// 数据元素出队/// </summary>public void DeQueue(){if (Length == 0)throw new Exception("队列为空,不能出队.");_pFront = (_pFront + 1)%MaxSize;Length--;}/// <summary>/// 判断队列中是否包含元素/// </summary>/// <returns>如果包含元素返回false,否则返回true.</returns>public bool IsEmpty(){return Length == 0;}/// <summary>/// 从队列中移除所有元素/// </summary>public void Clear(){_pFront = 0;_pRear = 0;Length = 0;}}
}
2.2 链式存储(链队)
链队:利用单链表实现的队列。
实现:
using System;namespace LinearStruct
{/// <summary>/// 用链式存储结构实现的队列/// </summary>/// <typeparam name="T">队列中元素的类型</typeparam>public class LinkQueue<T> : IQueue<T> where T : IComparable<T>{private readonly SLinkList<T> _lst;/// <summary>/// 获取LinkQueue中实际包含元素的个数/// </summary>public int Length{get { return _lst.Length; }}/// <summary>/// 获取LinkQueue中的队首元素/// </summary>public T QueueFront{get{if (_lst.IsEmpty())throw new Exception("队列为空,不能取队首元素.");return _lst[0];}}/// <summary>/// 初始化LinkQueue类的新实例/// </summary>public LinkQueue(){_lst = new SLinkList<T>();}/// <summary>/// 数据元素入队/// </summary>/// <param name="data">要入队的元素</param>public void EnQueue(T data){_lst.InsertAtRear(data);}/// <summary>/// 数据元素出队/// </summary>public void DeQueue(){if (_lst.IsEmpty())throw new Exception("队列为空,不能出队.");_lst.Remove(0);}/// <summary>/// 判断队列中是否包含元素/// </summary>/// <returns>如果包含元素返回false,否则返回true.</returns>public bool IsEmpty(){return _lst.IsEmpty();}/// <summary>/// 从队列中移除所有元素/// </summary>public void Clear(){_lst.Clear();}}
}
3. 练习参考答案
1. 模拟银行服务的程序代码
以下代码为C#
版本:
表示银行队列的接口
using LinearStruct;namespace BankQueue
{public interface IBankQueue : IQueue<int>{/// <summary>/// 获得服务号码/// </summary>/// <returns>服务号码</returns>int GetCallnumber();int MaxSize { get; }}
}
利用链式存储结构存储银行队列
using LinearStruct;namespace BankQueue
{public class LinkBankQueue : LinkQueue<int>, IBankQueue{public int Callnumber { get; private set; }public int MaxSize { get; }public int GetCallnumber(){if (IsEmpty() && Callnumber == 0){Callnumber = 1;}else{Callnumber++;}return Callnumber;}public LinkBankQueue(){MaxSize = default(int);Callnumber = 0;}}
}
利用顺序存储结构存储银行队列
using LinearStruct;namespace BankQueue
{public class CSeqBankQueue : CSeqQueue<int>, IBankQueue{public int Callnumber { get; private set; }public CSeqBankQueue(int size) : base(size){Callnumber = 0;}public int GetCallnumber(){if (IsEmpty() && Callnumber == 0){Callnumber = 1;}else{Callnumber++;}return Callnumber;}}
}
服务窗口
using System;
using System.Threading;namespace BankQueue
{public class ServiceWindow{//服务队列属性public IBankQueue BankQ { get; set; }//线程方法public void Service(){while (true){lock (BankQ){Thread.Sleep(2000);if (!BankQ.IsEmpty()){Console.WriteLine();Console.WriteLine("请{0}号到{1}号窗口!", BankQ.QueueFront, Thread.CurrentThread.Name);BankQ.DeQueue();}}}}}
}
客户端
using System;
using System.Threading;namespace BankQueue
{class BankQueueApp{public static void Main(string[] args){try{IBankQueue bankQueue = null;Console.WriteLine("请选择存储结构的类型:1.顺序队列 2.链队列");string seleflag = Console.ReadLine();switch (seleflag){case "1":Console.Write("请输入队列可容纳人数:");int count = Convert.ToInt32(Console.ReadLine());bankQueue = new CSeqBankQueue(count);break;case "2":bankQueue = new LinkBankQueue();break;}int windowcount = 3;ServiceWindow[] serviceWindows = new ServiceWindow[windowcount];Thread[] serviceThread = new Thread[windowcount];for (int i = 0; i < windowcount; i++){serviceWindows[i] = new ServiceWindow();serviceWindows[i].BankQ = bankQueue;serviceThread[i] = new Thread(serviceWindows[i].Service);serviceThread[i].Name = (i + 1).ToString();serviceThread[i].Start();}while (true){Console.Write("请点击触摸屏获取号码:");Console.ReadLine();if (bankQueue != null && (bankQueue.Length < bankQueue.MaxSize || seleflag == "2")){int callnumber = bankQueue.GetCallnumber();Console.WriteLine("您的号码是:{0},你前面有{1}位,请等待!",callnumber, bankQueue.Length);bankQueue.EnQueue(callnumber);}elseConsole.WriteLine("现在业务繁忙,请稍后再来!");Console.WriteLine();}}catch (Exception ex){Console.WriteLine(ex.Message);}}}
}
相关文章:

ios(iphone/ipad)开发笔记(1)
CGContextRefCGContextRefiphone开发刚刚入门 求个师傅iphone拨号键盘请问自己如果做sdkOpenGL ES 2.0有没有顶点光照的例子?socket通信哪位大侠帮帮忙?如何在tableView中使用自定义的cell?新手求指导Iphone按大圆钮时触发什么事件flash视频转…

如何查看Linq to SQL运行时,实际执行的Sql语句
调试Linq to sql代码是, 如果遇到错误,很难判断错误的原因是什么,如果能够输出实际执行的sql原文,对于我们寻找错误的原因有有很大帮助。 以下是我用到的方法: StringBuilder sql new StringBuilder();try{using (var context n…

Java培训零基础学员必须要知道的知识点
学习java那么遇到的知识点有很多,很多同学都会问到一些关于java的编程知识点,下面小编就为大家整理一下java培训零基础学员必须要知道的6个知识点。 Java培训零基础学员必须要知道的6个知识点: JVM作为java运行的基础来说,掌握透析…

SpringCloud Alibaba集成 Gateway(自定义负载均衡器)、Nacos(配置中心、注册中心)、Loadbalancer
要为未被某些网关路由谓词处理的请求提供相同的CORS配置,请将属性spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping设置为true。断言(Predicate):Java8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是 Spring5.0框架中的ServerWebExchange。对于所有GET请求的路径,来自docs.spring.io的请求都将允许CORS请求。

并发编程下的集合:数组寻址、LinkedList、HashMap、ConcurrentHashMap
如果发现hash取模后的数组索引位下无元素则直接新增,若不是空那就说明存在hash冲突,则判断数组索引位链表结构中的第一个元素的key以及hash值是否与新的key一致则直接覆盖,若不一致则判断当前的数组索引下的链表结构是否为红黑树,若为红黑树则走红黑树的新增方法,若不为红黑树则遍历当前链表结构,遍历中发现某个节点元素的next为null是则直接将新元素指针与next进行关联,若在遍历到next为空前判断到,某个节点的key以及key的hash值与新的key与新的keyhash值一致时则走覆盖。

【日常开发之插件篇】IDEA plugins 神器助我!!
今早因为老代码的一些bug让我突然觉得Idea的一些插件特别好用,我准备将我平时所用到的一些插件做个推荐以及记录。

【日常开发之FTP】Windows开启FTP、Java实现FTP文件上传下载
FTP是一个专门进行文件管理的操作服务,一般来讲可以在任意的操作系统之中进行配置,但是如果考虑到简便性,一般来讲可以直接在Linux系统下进行安装。FTP (File Transfer Protocol、文件传输协议)是TCP/IP协议中的一部分,属于应用层协议。使用FTP最主要的功能是对文件进行管理,所以在FTP内部对于文件支持有两种传输模式:文本模式(ASCII、默认)和二进制模式(Binary),通常文本文件使用ASCIl模式,而对于图片、视频、声音、压缩等文件则会使用二进制的方式进行传输。

【Linux之升华篇】Linux内核锁、用户模式与内核模式、用户进程通讯方式
alloc_pages(gfp_mask, order),_ _get_free_pages(gfp_mask, order)等。字符设备描述符 struct cdev,cdev_alloc()用于动态的分配 cdev 描述符,cdev_add()用于注。外,还支持语义符合 Posix.1 标准的信号函数 sigaction(实际上,该函数是基于 BSD 的,BSD。从最初的原子操作,到后来的信号量,从。(2)命名管道(named pipe):命名管道克服了管道没有名字的限制,因此,除具有管道所具有的。

【Mongdb之数据同步篇】什么是Oplog、Mongodb 开启oplog,java监听oplog并写入关系型数据库、Mongodb动态切换数据源
oplog是local库下的一个固定集合,Secondary就是通过查看Primary 的oplog这个集合来进行复制的。每个节点都有oplog,记录这从主节点复制过来的信息,这样每个成员都可以作为同步源给其他节点。Oplog 可以说是Mongodb Replication的纽带了。

zookeeper集群部署以及zookeeper原理
ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。ZooKeeper的目标就是封装好复杂易出错的关键服务,将简单易用的接口和性能高效、功能稳定的系统提供给用户。ZooKeeper包含一个简单的原语集,提供Java和C的接口。

【日常开发之Windows共享文件】Java实现Windows共享文件上传下载
下拉框选择你选择的用户点击添加,然后共享确定。创建一个文件夹然后点击属性界面,点击共享。maven版本存在于SMB协议的兼容问题。首先开启服务,打开控制面板点击程序。点击启用或关闭Windows功能。我这边是专门创建了一个用户。SMB1.0选中红框内的。

rust wasm入门
demo## 编译 Rust 为 WebAssembly在本教程中,我们将使用 Rust 的 npm 包构建工具 wasm-pack 来构建一个 npm 包。

minikube环境搭建
📕作者简介:过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。📘相关专栏系列、spring教程等,大家有兴趣的可以看一看📙系列,系列、系列正在发展中,喜欢Java,GoLang,Rust,的朋友们可以关注一下哦!@[TOC]# minikube## 安装### 前置条件已经安装docker### 乌班图安装科学上网是我你们安装的前提。```shell。

Pods/Nodes
Pod 容器组 是一个k8s中一个抽象的概念,用于存放一组 container,以及这些 container (容器)的一些共享资源。共享存储,称为卷(Volumes),即图上紫色圆柱网络,每个 Pod(容器组)在集群中有个唯一的 IP,pod(容器组)中的 container(容器)共享该IP地址container(容器)的基本信息,例如容器的镜像版本,对外暴露的端口等Pod(容器组)是 k8s 集群上的最基本的单元。

公布应用程序
当 worker node(节点)故障时,节点上运行的 Pod(容器组)也会消失。然后,Deployment (opens new window)可以通过创建新的 Pod(容器组)来动态地将群集调整回原来的状态,以使应用程序保持运行。举个例子,假设有一个图像处理后端程序,具有 3 个运行时副本。这 3 个副本是可以替换的(无状态应用),即使 Pod(容器组)消失并被重新创建,或者副本数由 3 增加到 5,前端系统也无需关注后端副本的变化。

伸缩应用程序和执行滚动更新
原本 Service A 将流量负载均衡到 4 个旧版本的 Pod 上2. 更新完 Deployment 部署文件中的镜像版本后,master 节点选择了一个 worker 节点,并根据新的镜像版本创建 Pod(紫色容器)。新 Pod 拥有唯一的新的 IP。同时,master 节点选择一个旧版本的 Pod 将其移除。此时,Service A 将新 Pod 纳入到负载均衡中,将旧Pod移除同步骤2,再创建一个新的 Pod 替换一个原有的 Pod。

Kubernetes对象的定义和操作
Kubernetes对象指的是Kubernetes系统的持久化实体,所有这些对象合起来,代表了你集群的实际情况。常规的应用里,我们把应用程序的数据存储在数据库中,Kubernetes将其数据以Kubernetes对象的形式通过 api server存储在 etcd 中。集群中运行了哪些容器化应用程序集群中对应用程序可用的资源应用程序相关的策略定义,例如,重启策略、升级策略、容错策略其他Kubernetes管理应用程序时所需要的信息。

名称和命名空间
📕作者简介:过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。📘相关专栏系列、spring教程等,大家有兴趣的可以看一看📙系列,系列、系列正在发展中,喜欢Java,GoLang,Rust,的朋友们可以关注一下哦!

使用名称空间共享集群
可以限定使用某个名称空间的用户不能看到另外一个名称空间中的内容。默认情况下,安装Kubernetes集群时,会初始化一个 default 名称空间,用来将承载那些未指定名称空间的 Pod、Service、Deployment等对象。接下来,为 kubectl 定义一个上下文,以便在不同的名称空间中工作。此时,开发人员可以做任何他想要做的操作,所有操作都限定在名称空间 development 里,而无需担心影响到 production 名称空间中的内容。使用 kubectl 有两种方式可以创建名称空间。

k8s 标签和选择器
标签(Label)是附加在Kubernetes对象上的一组名值对,其意图是按照对用户有意义的方式来标识Kubernetes对象,同时,又不对Kubernetes的核心逻辑产生影响。管理这些对象时,很多时候要针对某一个维度的条件做整体操作,例如,将某个版本的程序整体删除,这种情况下,如果用户能够事先规划好标签的使用,再通过标签进行选择,就会非常地便捷。Kubernetes api server支持两种形式的标签选择器,equality-based 基于等式的 和 set-based 基于集合的。

iced 入门一
本教程的目标是创建一个简单的购物清单应用程序。我们希望允许添加和删除购物清单中的项目。在编写代码之前,我们必须首先了解 Iced 构建的结构:Elm 架构。它是 GUI 库使用的架构,最初用于 Elm 编程语言。它的核心原则很简单。它围绕三个概念构建:模型、视图和更新。

shell编程
简单来说“Shell 编程就是对一堆 Linux 命令的逻辑化处理”。

注解annotation
Kubernetes的系统组件(例如,kube-scheduler、kube-controller-manager、kube-apiserver、kubectl 或其他第三方组件)向用户的Kubernetes对象添加注解时,必须指定一个前缀。注解(annotation)可以用来向 Kubernetes 对象的 metadata.annotations 字段添加任意的信息。除了使用注解,您也可以将这类信息存放在一个外部的数据库,然而,在使用、分享这些信息的时候,可能会变得难以管理。

字段选择器
字段选择器(Field Selector)可以用来基于的一个或多个字段的取值来选取一组Kubernetes对象。

容器组_概述
Pod(容器组)是 Kubernetes 中最小的可部署单元。一个 Pod(容器组)包含了一个应用程序容器(某些情况下是多个容器)、存储资源、一个唯一的网络 IP 地址、以及一些确定容器该如何运行的选项。Pod 容器组代表了 Kubernetes 中一个独立的应用程序运行实例,该实例可能由单个容器或者几个紧耦合在一起的容器组成。一个 Pod 中只运行一个容器。“one-container-per-pod” 是 Kubernetes 中最常见的使用方式。

容器组_生命周期
只有一种例外,那就是 Pod 处于 Scucceeded 或 Failed 的 phase,并超过了垃圾回收的时长(在 kubernetes master 中通过 terminated-pod-gc-threshold 参数指定),kubelet 自动将其删除。每一个 Pod 都有一个数组描述其是否达到某些指定的条件。Pod phase 并不是用来代表其容器的状态,也不是一个严格的状态机。Kubernetes教程:在Kuboard中配置容器的健康检查/就绪检查。Kuboard 中配置健康检查/就绪检查。

容器组_初始化容器
Pod 可以包含多个工作容器,也可以包含一个或多个初始化容器,初始化容器在工作容器启动之前执行。初始化容器总是运行并自动结束kubelet 按顺序执行 Pod 中的初始化容器,前一个初始化容器成功结束后,下一个初始化容器才开始运行。所有的初始化容器成功执行后,才开始启动工作容器如果 Pod 的任意一个初始化容器执行失败,kubernetes 将反复重启该 Pod,直到初始化容器全部成功(除非 Pod 的 restartPolicy 被设定为 Never)

容器组_配置初始化容器
📕作者简介:过去日记,致力于Java、GoLang,Rust等多种编程语言,热爱技术,喜欢游戏的博主。📘相关专栏系列、spring教程等,大家有兴趣的可以看一看📙系列,系列、系列正在发展中,喜欢Java,GoLang,Rust,的朋友们可以关注一下哦!

Deployment概述
Pod 容器组是 Kubernetes 中最小的调度单元,更多信息请参考 容器组 - 概述Deployment 是最常用的用于部署无状态服务的方式。Deployment 控制器使得您能够以声明的方式更新 Pod(容器组)和 ReplicaSet(副本集)。以“声明”的方式管理 Pod 和 ReplicaSet,其本质是将一些特定场景的一系列运维步骤固化下来,以便快速准确无误的执行。

HackQuest介绍 web3 学习平台
官网地址: https://www.hackquest.io/zhHackQuest是一个专注于Web3技术教育的在线学习平台,旨在帮助全球开发者掌握区块链、加密货币和去中心化应用(DApps)领域的最新技能。该平台汇聚了超过14000名活跃开发者,与100多个领先的Web3生态系统和项目紧密合作,为用户提供全面的教育资源。