C#实现队列及环形队列(数组)

队列(Queue)

介绍

队列是一种有序列表,只允许对队尾(rear)进行删除操作,对队首(front)进行删除操作,即先入先出(FIFO)。

实现队列需要的内部元素

元素含义
maxSize代表能够存储的数据的个数
front指向队首
rear指向队尾
array[]用于存储数据
void Enqueue(int n)将元素n入队
int Dequeue()将队尾元素出队,同时元素个数-1
int Peek()返回队尾元素,元素个数不变
bool IsFull()队列已满返回true,未满返回false
bool IsEmpty()队列为空返回true,不为空返回false

数组模拟一般队列

内部元素含义

元素含义
maxSize代表能够存储的数据的个数
front指向数组内第一个元素的前一位置
rear指向数组内最后一个元素的位置
array[]用于存储数据
void Enqueue(int n)将元素n入队
int Dequeue()将队尾元素出队,同时元素个数-1
int Peek()返回队尾元素,元素个数不变
bool IsFull()队列已满返回true,未满返回false
bool IsEmpty()队列为空返回true,不为空返回false

分析思路

入队

1.判断队列是否已满,如果已满则直接返回
2.如果未满则将元素加入队列,并将rear向后移

出队

1.判断队列是否为空,如果为空抛出异常
2.如果不为空则返回下标为 front+1 的元素,并将front后移

Peek

1.判断队列是否为空,如果为空抛出异常
2.如果不为空则返回下标为 front+1 的元素

IsFull

rear == maxSize-1 时返回true

IsEmpty

rear == front 时返回true

图解

在这里插入图片描述

代码实现

    class ArrayQueue
    {
        private int _maxSize;    //最大容量
        private int _front;      //队列头  指向队列头的前一个位置
        private int _rear;       //队列尾  指向队列尾的数据
        private int[] _arr;      //用于存放数据的数组

        public ArrayQueue(int maxSize)
        {
            this._maxSize = maxSize;
            this._front = -1;
            this._rear = -1;
            _arr = new int[_maxSize];
        }

        //判断是否已满
        public bool IsFull()
        {
            return _rear == _maxSize - 1;
        }

        //判断队列是否为空
        public bool IsEmpty()
        {
            return _rear == _front;
        }

        //入队
        public void Enqueue(int n)
        {
            //判断队列是否已满
            if (IsFull())
            {
                Console.WriteLine("队列已满,不能增加数据");
                return;
            }
            _arr[++_rear] = n;
        }

        //出队
        public int Dequeue()
        {
            //判断队列是否为空
            if (IsEmpty())
            {
                throw new Exception("队列为空");
            }
            return _arr[++_front];
        }

        //显示头数据
        public int Peek()
        {
            //判断是否为空
            if (IsEmpty())
            {
                throw new Exception("队列为空");
            }
            return _arr[_front + 1];
        }

    }

总结

在这里插入图片描述

可以看出,当rear到达数组的最后一个位置,而front指向数组中间位置时,front之前的空间就是浪费的 (如上图),而此种方法实现的队列做不到数组空间的复用

虽然在数组的前半部分仍然有未被利用的空间,但是当想要继续往队列中添加元素时就会产生数组越界的错误,也被称作“假溢出”。

因而出现了环形队列

环形队列

什么是环形队列

为了达到数组空间的复用,或者说是为了解决“假溢出”的问题,我们把队列的头部和尾部相连接,而这种头尾相接,可以看作是一个“环”的队列就是环形队列。

图解

假设这样一个场景,先将队列存满,然后两次出队,然后再向队列中添加两个元素,可以得到这样一个结果
rear == front == 1 如图所示
在这里插入图片描述
当队列为空和队列已满时 rear 都等于 front,此时判断队列是空队列还是满队列的方法有两种

1.设置一个标记变量,当 front == rear 且 flag == false 时队列为空,当 front == rear 且 flag == true 时队列为满。
2. 当队列为空时 front == rear, 当队列为满时修改其条件,保留一个空置空间。也就是说队列满的时候数组中还有一个空闲的空间,此时就认为队列时满的。

下面介绍第二种解决方案

内部元素含义

元素含义
maxSize代表能够存储的数据的个数+1
front指向数组内第一个元素
rear指向数组内最后一个元素后一位置
array[]用于存储数据
void Enqueue(int n)将元素n入队
int Dequeue()将队尾元素出队,同时元素个数-1
int Peek()返回队尾元素,元素个数不变
bool IsFull()队列已满返回true,未满返回false
bool IsEmpty()队列为空返回true,不为空返回false
int GetSize()获取数组中有效值的个数

分析思路

入队

1.判断队列是否已满,如果已满则直接返回
2.如果未满则将元素加入队列,并将rear向“后移”

后移代码

_rear = (_rear + 1) % _maxSize;		//通过取模来达到 “循环” 的目的
出队

1.判断队列是否为空,如果为空抛出异常
2.如果不为空则返回下标为 front 的元素,并将front后移

后移代码

_front = (_front + 1) % _maxSize;	//通过取模来达到 “循环” 的目的
Peek

1.判断队列是否为空,如果为空抛出异常
2.如果不为空则返回下标为 front 的元素

IsFull

当 (rear+1) % maxSize == front 时队列已满(返回 true)

IsEmpty

rear == front 时返回true

GetSize

当 rear > front 时,有效元素的个数为 rear - front
而当 rear < front 时,此时可以将数组看成两段,第一段是 front 到 maxSize,第二段是 rear - 0 ,数组中有效元素的个数是 rear - front + maxSize

综上可得,队列中有效元素的个数为
(rear - front + maxSize) % maxSize

代码实现

    class CircleQueue
    {
        private int _maxSize;    //最大容量
        private int _front;      //队列头  指向第一个元素
        private int _rear;       //队列尾  指向最后一个元素的后一位置
        private int[] _arr;      //用于存放数据的数组

        public CircleQueue(int maxSize)
        {
            this._maxSize = maxSize;
            _arr = new int[_maxSize];
            _front = 0;
            _rear = 0;
        }

        //判断是否已满
        public bool IsFull()
        {
            return ((_rear + 1) % _maxSize) == _front;
        }

        //判断队列是否为空
        public bool IsEmpty()
        {
            return _rear == _front;
        }

        //添加数据
        public void Enqueue(int n)
        {
            //判断队列是否已满
            if (IsFull())
            {
                Console.WriteLine("队列已满,不能增加数据");
                return;
            }

            //此时rear指向的是最后一个元素的后一位置,因此可以直接添加
            _arr[_rear] = n;
            //将 rear 后移
            _rear = (_rear + 1) % _maxSize;
        }

        //出队
        public int Dequeue()
        {
            //判断队列是否为空
            if (IsEmpty())
            {
                throw new Exception("队列为空");
            }

            //此时front 指向第一个元素
            int val = _arr[_front];

            //将front后移
            _front = (_front + 1) % _maxSize;
            return val;
        }

        //求出当前队列有效数据的个数
        private int GetSize()
        {
            return (_rear + _maxSize - _front) % _maxSize;
        }

        //显示头数据
        public int Peek()
        {
            //判断是否为空
            if (IsEmpty())
            {
                throw new Exception("队列为空");
            }
            return _arr[_front];
        }

    }

两种队列内部元素的对比

元素环形队列顺序存储结构队列
maxSize实际能够存储的元素个数为maxSize-1代表能够存储的数据的个数
front指向数组内第一个元素指向数组内第一个元素的前一位置
rear指向数组内最后一个元素后一位置指向数组内最后一个元素
bool IsFull()(rear+1) % maxSize == frontrear == maxSize -1
bool IsEmpty()rear == frontrear == front
int GetSize()(rear - front + maxSize) % maxSizerear - front
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# 中的字典(Dictionary)、队列(Queue)和数组(Array)是常用的数据结构,它们分别用于存储键值对、先进先出的元素和相同类型的元素。 ### 字典(Dictionary) 字典是一种键值对集合,每个键值对称为一个项(Item),其中键(Key)唯一,对应一个值(Value)。在 C# 中,字典的实现类是 `Dictionary<TKey, TValue>`,其中 `TKey` 为键的类型,`TValue` 为值的类型。 下面是一个简单的示例,演示了如何使用字典: ```csharp Dictionary<string, int> dict = new Dictionary<string, int>(); dict.Add("apple", 2); dict.Add("banana", 3); dict.Add("orange", 4); foreach (KeyValuePair<string, int> item in dict) { Console.WriteLine(item.Key + ": " + item.Value); } // Output: // apple: 2 // banana: 3 // orange: 4 ``` 在上面的示例中,我们创建了一个名为 `dict` 的字典,键的类型为字符串,值的类型为整数。然后,我们使用 `Add` 方法向字典中添加三个项。最后,我们使用 `foreach` 循环遍历字典中的所有项,并输出它们的键和值。 ### 队列(Queue) 队列是一种先进先出的数据结构,每次从队列中取出的元素都是最早插入队列的元素。在 C# 中,队列实现类是 `Queue<T>`,其中 `T` 为元素的类型。 下面是一个简单的示例,演示了如何使用队列: ```csharp Queue<int> queue = new Queue<int>(); queue.Enqueue(1); queue.Enqueue(2); queue.Enqueue(3); while (queue.Count > 0) { int num = queue.Dequeue(); Console.WriteLine(num); } // Output: // 1 // 2 // 3 ``` 在上面的示例中,我们创建了一个名为 `queue` 的队列,元素的类型为整数。然后,我们使用 `Enqueue` 方法向队列中添加三个元素。最后,我们使用 `while` 循环遍历队列中的所有元素,并使用 `Dequeue` 方法取出元素并输出。 ### 数组(Array) 数组是一种固定长度、相同类型的元素集合。在 C# 中,数组可以是一维、二维或多维的。数组的类型可以是任意数据类型,包括自定义数据类型。 下面是一个简单的示例,演示了如何使用数组: ```csharp int[] nums = new int[3]; nums[0] = 1; nums[1] = 2; nums[2] = 3; foreach (int num in nums) { Console.WriteLine(num); } // Output: // 1 // 2 // 3 ``` 在上面的示例中,我们创建了一个名为 `nums` 的整数数组,长度为 3。然后,我们使用下标运算符 `[]` 给数组中的元素赋值。最后,我们使用 `foreach` 循环遍历数组中的所有元素,并输出它们的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值