C#队列
队列(Queue)是插入操作限定在表的尾部而其它操作限定在表的头部进行的线性表。把进行插入操作的表尾称为队尾(Rear),把进行其它操作的头部称为队头(Front)。当对列中没有数据元素时称为空对列(Empty Queue)。对列的操作是按照先进先出(First In First Out)或后进后出( Last In Last Out)的原则进行的,因此,队列又称为FIFO表或LILO表。队列Q的操作示意图如图所示。
队列的形式化定义为:队列(Queue)简记为 Q,是一个二元组,
Q = (D, R)
其中:D 是数据元素的有限集合;
R 是数据元素之间关系的有限集合。
队列的操作是线性表操作的一个子集。队列的操作主要包括在队尾插入元素、在队头删除元素、取队头元素和判断队列是否为空等。与栈一样,队列的运算是定义在逻辑结构层次上的,而运算的具体实现是建立在物理存储结构层次上的。因此,把队列的操作作为逻辑结构的一部分,每个操作的具体实现只有在确定了队列的存储结构之后才能完成。
队列接口 IQueue<T>的定义如下所示。
public interface IQueue<T>//队列接口的定义 { int GetLength(); //求队列的长度 bool IsEmpty(); //判断对列是否为空 void Clear(); //清空队列 void In(T item); //入队 T Out(); //出队 T GetFront(); //取对头元素 }
队列的存储和运算实现
- 顺序队列
用一片连续的存储空间来存储队列中的数据元素, 这样的队列称为顺序队列 (Sequence Queue)。类似于顺序栈,用一维数组来存放顺序队列中的数据元素。队头位置设在数组下标为 0 的端,用 front 表示;队尾位置设在数组的另一端,用 rear 表示。 front 和 rear 随着插入和删除而变化。 当队列为空时, front=rear=-1。图是顺序队列的两个指示器与队列中数据元素的关系图。
当有数据元素入队时,队尾指示器 rear 加 1,当有数据元素出队时,队头指示器 front 加 1。当 front=rear 时,表示队列为空,队尾指示器 rear 到达数组的上限处而 front 为-1 时,队列为满,如图 (c)所示。队尾指示器 rear 的值大于队头指示器 front 的值,队列中元素的个数可以由 rear-front 求得。由图 (d)可知,如果再有一个数据元素入队就会出现溢出。但事实上队列中并未满,还有空闲空间,把这种现象称为“假溢出” 。这是由于队列“队尾入队头出”的操作原则造成的。解决假溢出的方法是将顺序队列看成是首尾相接的循环结构,头尾指示器的关系不变,这种队列叫循环顺序队列( Circular sequenceQueue )。循环队列如图所示。
当队尾指示器 rear 到达数组的上限时, 如果还有数据元素入队并且数组的第0 个空间空闲时,队尾指示器 rear 指向数组的 0 端。所以,队尾指示器的加 1 操作修改为:rear = (rear + 1) % maxsize。队头指示器的操作也是如此。当队头指示器 front 到达数组的上限时,如果还有数据元素出队,队头指示器 front 指向数组的 0 端。所以,队头指示器的加1 操作修改为:front = (front + 1) % maxsize。循环顺序队列操作示意图如图所示。
由图可知,队尾指示器 rear 的值不一定大于队头指示器 front 的值,并且队满和队空时都有 rear=front。也就是说,队满和队空的条件都是相同的。解决这个问题的方法一般是少用一个空间, 如图 (d)所示, 把这种情况视为队满。所以,判断队空的条件是:rear==front,判断队满的条件是:(rear + 1) %maxsize==front。求循环队列中数据元素的个数可由(rear-front+maxsize)%maxsize公式求得。
把循环顺序队列看作是一个泛型类,用数组来存储循环顺序队列中的元素,在类中用字段 data 来表示。用字段maxsize 表示循环顺序队列的容量, maxsize 的值可以根据实际需要修改,这通过类的构造器中的参数 size 来实现, 循环顺序队列中的元素由 data[0]开始依次顺序存放。字段 front 表示队头, front 的范围是 0 到 maxsize-1。 字段rear表示队尾, rear 的范围也是 0 到 maxsize-1。 如果循环顺序队列为空, front=rear=-1。当执行入队列操作时需要判断循环顺序队列是否已满,如果循环顺序队列已满,(rear + 1) % maxsize==front,循环顺序队列已满不能插入元素。
循环顺序队列类 CSeqQueue<T>的实现说明如下所示。
public class CSeqQueue<T> : IQueue<T>//循环顺序队列类的实现 { private int maxsize; private T[] data; private int front; private int rear; public int Maxsize { get { return maxsize; } set { maxsize = value; } } public int Front { get { return front; } set { front = value; } } public int Rear { get { return rear; } set { rear = value; } } public T this[int index] { get { return data[index]; } set { data[index] = value; } } public CSeqQueue(int size) { data = new T[size]; maxsize = size; front = rear = -1; } /* 循环顺序队列的长度取决于队尾指示器 rear 和队头指示器 front。一般情 况下,rear 大于 front,因为入队的元素肯定比出队的元素多。特殊的情况是 rear 到达数组的上限之后又从数组的低端开始,此时,rear 是小于 front 的。 所以,rear 的大小要加上 maxsize。因此,循环顺序队列的长度应该是: (rear-front+maxsize)%maxsize。 */ public int GetLength() { return (rear - front + maxsize) % maxsize; } public bool IsEmpty() { return front == rear; } public void Clear() { rear = front = -1; } public bool IsFull() { return (rear + 1) % maxsize == front; } public void In(T item) { if (IsFull()) { Console.WriteLine("Queue is full"); return; } data[++rear] = item; } public T Out() { T tmp = default(T); if (IsEmpty()) { Console.WriteLine("Queue is empty"); return tmp; } tmp = data[++front]; return tmp; } public T GetFront() { if (IsEmpty()) { Console.WriteLine("Queue is empty!"); return default(T); } return data[front + 1]; } }
2、链队列
队列的另外一种存储方式是链式存储,这样的队列称为链队列(Linked Queue)。同链栈一样,链队列通常用单链表来表示,它的实现是单链表的简化。所以,链队列的结点的结构与单链表一样。由于链队列的操作只是在一端进行,为了操作方便,把队头设在链表的头部,并且不需要头结点。
链队列结点类(Node<T>)的实现如下所示:
public class Node<T>//链队列结点类 { private T data; //数据域 private Node<T> next; //引用域 //构造器 public Node(T val, Node<T> p) { data = val; next = p; } //构造器 public Node(Node<T> p) { next = p; } //构造器 public Node(T val) { data = val; next = null; } //构造器 public Node() { data = default(T); next = null; } //数据域属性 public T Data { get { return data; } set { data = value; } } //引用域属性 public Node<T> Next { get { return next; } set { next = value; } } }
把链队列看作一个泛型类,类中有两个字段 front 和 rear,表示队头指示器和队尾指示器。由于队列只能访问队头的数据元素,而链队列的队头指示器和队尾指示器又不能指示队列的元素个数,所以,与链栈一样,在类增设一个字段 num 表示链队列中结点的个数。
链队列类 LinkQueue<T>的实现说明如下所示。
public class LinkQueue<T> : IQueue<T>//链队列类的实现 { private Node<T> front; //队列头指示器 private Node<T> rear; //队列尾指示器 private int num; //队列结点个数 //队头属性 public Node<T> Front { get { return front; } set { front = value; } } //队尾属性 public Node<T> Rear { get { return rear; } set { rear = value; } } //队列结点个数属性 public int Num { get { return num; } set { num = value; } } public LinkQueue() { front = rear = null; num = 0; } public int GetLength() { return num; } public bool IsEmpty() { return front == rear && num == 0; } public void Clear() { front = rear = null; num = 0; } public void In(T item) { Node<T> node = new Node<T>(item); if (rear == null) { rear = node; } rear.Next = node; rear = node; ++num; } public T Out() { if (IsEmpty()) { Console.WriteLine("Queue is empty!"); return default(T); } Node<T> node = front; front = front.Next; if (front == null) { rear = null; } --num; return front.Data; } public T GetFront() { if (IsEmpty()) { Console.WriteLine("Queue is empty!"); return default(T); } return front.Data; } }
C#队列的更多相关文章
- 消息队列——RabbitMQ学习笔记
消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...
- 消息队列 Kafka 的基本知识及 .NET Core 客户端
前言 最新项目中要用到消息队列来做消息的传输,之所以选着 Kafka 是因为要配合其他 java 项目中,所以就对 Kafka 了解了一下,也算是做个笔记吧. 本篇不谈论 Kafka 和其他的一些消息 ...
- Beanstalkd一个高性能分布式内存队列系统
高性能离不开异步,异步离不开队列,内部是Producer-Consumer模型的原理. 设计中的核心概念: job:一个需要异步处理的任务,是beanstalkd中得基本单元,需要放在一个tube中: ...
- .net 分布式架构之业务消息队列
开源QQ群: .net 开源基础服务 238543768 开源地址: http://git.oschina.net/chejiangyi/Dyd.BusinessMQ ## 业务消息队列 ##业务消 ...
- 【原创经验分享】WCF之消息队列
最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...
- 缓存、队列(Memcached、redis、RabbitMQ)
本章内容: Memcached 简介.安装.使用 Python 操作 Memcached 天生支持集群 redis 简介.安装.使用.实例 Python 操作 Redis String.Hash.Li ...
- Java消息队列--ActiveMq 实战
1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...
- Java消息队列--JMS概述
1.什么是JMS JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送 ...
- 消息队列性能对比——ActiveMQ、RabbitMQ与ZeroMQ(译文)
Dissecting Message Queues 概述: 我花了一些时间解剖各种库执行分布式消息.在这个分析中,我看了几个不同的方面,包括API特性,易于部署和维护,以及性能质量..消息队列已经被分 ...
- [数据结构]——链表(list)、队列(queue)和栈(stack)
在前面几篇博文中曾经提到链表(list).队列(queue)和(stack),为了更加系统化,这里统一介绍着三种数据结构及相应实现. 1)链表 首先回想一下基本的数据类型,当需要存储多个相同类型的数据 ...
随机推荐
- php学习函数
1defined和define区别 2.dirname(__FILE__) 3.set_include_path 4.get_include_path 5.realpath() 6.require_p ...
- (转)JavaScript中的运算符优先级
JavaScript中的运算符优先级是一套规则.该规则在计算表达式时控制运算符执行的顺序.具有较高优先级的运算符先于较低优先级的运算符执行.例如,乘法的执行先于加法. 下表按从最高到最低的优先级列出J ...
- Microsoft Office Project 相关教程 收集
Project教程 如何建立任务间链接 Project教程:[10]如何将项目插入主项目 如何有效使用Project(1)——编制进度计划.保存基准 如何有效使用Project(2)——进度计划的执行 ...
- php curl用法
curl 是使用URL语法的传送文件工具,支持FTP.FTPS.HTTP HTPPS SCP SFTP TFTP TELNET DICT FILE和LDAP.curl 支持SSL证书.HTTP POS ...
- ef join 用法
var customers = DB.Customer.Join(DB.Commission, cst => cst.CommissionId, ...
- Linux Shell 学习总结
1. -bash: ./dd.sh: /bin/bash^M: bad interpreter: 没有那个文件或目录 当出现上面这问题的时候,首先看你的.profile 里面是否配置对了,一般配置为: ...
- Objective-C( Foundation框架 一 NSDictionary (NSMutaleDictionary))
NSDictionary 不可变的字典 创建字典的方法 // 创建字典的方式 NSDictionary *dy = [NSDictionary dictionaryWithObject:@" ...
- hibernate5ID生成策略
1.uuid2:使用JDK自带的UUID生成36位的ID 2.guid: 3.uuid:生成32位的uuid,不符合ETF RFC 4122标准,已被uuid2取代. 4.uuid.hex:等同uui ...
- Java--静态区域块
public class Demo3_2 { static int i=1; static //静态区域块 { //该静态区域块只被执行一次 System.out.println("a&qu ...
- myhandle
#ifndef my_handle_h #define my_handle_h #include <stdint.h> #include "mydef.h" #incl ...