C# 队列 | 顺序队列 | 链队列 的原理和代码实现

题外话:嘿嘿,偷懒了两天,吃一天玩一天,今天继续。

PS: 本文的重点代码代码代码!而不是数据结构的一些基础概念和分类;
完全没接触过的同学,可以去看B站王卓教授的视频。


1.什么是队列?

  • 队列是在表尾进行插入操作,在表头进行删除操作的线性表;
  • 即“先进先出”。就跟现实世界的排队一样。

说明: 你不能插队,所以你新来的你去队尾,你在我后面,你比我晚上车。


2.队列有几种?

  • 同样,根据实现队列的基本数据结构不同,分为:
    • 顺序队列: 用数组实现的队列;
    • 链队列: 用链表实现的队列。

3.顺序队列(常用)

  • 用顺序表(数组)实现的队列,叫顺序队列;
  • 顺序队列的基本结构
    • front:用于记录队头;
    • rear:用于记录队尾;
    • MaxSize:用于记录数组最大容积;
    • _array:数组,用于容纳队列中的元素。
  • 抛出一个问题: 如果用数组实现队列,不断的入队出队,会导致数组无法再添加元素了,到顶了,如图。

说明: 类似上图这种情况怎么办?空着的部分浪费不说,整个队列也废掉了?当然不行! 所以我们要想办法,把新的元素放到下面空白的部分,这就需要一定的余数计算了。

  • 解决方法:
    • 首先,我们默认数组永远空一格便于计算。即6个容积的数组,装了5个元素,我们视为该队列已满。
    • 计算元素个数:(rear - front + MaxSize) % MaxSize;
    • 是否为空:个数 == 0 ?true : false;
    • 是否已满:(rear + 1) % MaxSize == front;

4.代码实现顺序队列

namespace YoyoCode
{
    
    
    internal class SqQueue<T>
    {
    
    
        public T[] _array;
        public int MaxSize = 4;
        public int front = 0;
        public int rear = 0;
        public SqQueue() {
    
    
            _array= new T[MaxSize];
        }
        public SqQueue(int size)
        {
    
    
            MaxSize= size;
            _array = new T[MaxSize];
        }
        /// <summary>
        /// 队列是否为空
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
    
    
            return GetCount() == 0;
        }
        /// <summary>
        /// 获取队列中元素的数量
        /// </summary>
        /// <returns></returns>
        public int GetCount()
        {
    
    
            return (rear - front + MaxSize) % MaxSize;
        }
        /// <summary>
        /// 队列是否已满,注意,这个队列空一个视为满(空一个是为了更好的计算)
        /// </summary>
        /// <returns></returns>
        public bool IsFull()
        {
    
    
            return (rear + 1) % MaxSize == front;
        }
        /// <summary>
        /// 入队,从队尾入队
        /// </summary>
        /// <param name="value"></param>
        public void EnQueue(T value)
        {
    
    
            if (IsFull())
            {
    
    
                throw (new OverflowException());
            }
            _array[rear] = value;
            rear = (rear + 1) % MaxSize;
        }
        /// <summary>
        /// 出队,从队头出队
        /// </summary>
        /// <returns></returns>
        public T DeQueue()
        {
    
    
            if (IsEmpty())
            {
    
    
                throw(new NullReferenceException());
            }
            var res = _array[front]; 
            front = (front + 1) % MaxSize;
            return res;
        }
    }
}

5.链队列(不常用)

  • 链表实现的队列,叫链队。
  • 链队的基本结构:
    • front:头结点指针;
    • rear:尾结点指针;
    • LinkQueueNode:普通的链表结点的数据结构。

6.代码实现链队

namespace YoYoCode
{
    
    
    public class LinkQueue<T>
    {
    
    
        public LinkQueueNode<T> Front;
        public LinkQueueNode<T> Rear ;

        public LinkQueue()
        {
    
    
            Front = new LinkQueueNode<T>();
            Front.Next = null;
            Rear = Front;
        }
        //是否为空
        public bool IsEmpty()
        {
    
    
            return Front == Rear;
        }
        //入队
        public void EnQueue(LinkQueueNode<T> node)
        {
    
    
            Rear.Next = node;
            Rear = node;
        }
        //出队
        public LinkQueueNode<T> DeQueue()
        {
    
    
            //队空
            if (IsEmpty())
            {
    
    
                return default;
            }
            LinkQueueNode<T> _res = Front.Next;
            //队中只有一个元素
            if (_res == Rear)
            {
    
    
                Rear = Front;
            }
            Front.Next = _res.Next;
            return _res;
        }
        //获取队头元素(不是头结点)
        public LinkQueueNode<T> GetHead()
        {
    
    
            if (Front.Next != null)
            {
    
    
                return Front.Next;
            }

            return default;
        }
    }

    public class LinkQueueNode<T>
    {
    
    
        public T Data;
        public LinkQueueNode<T> Next;

        public LinkQueueNode(){
    
    }
            
        public LinkQueueNode(T data)
        {
    
    
            Data = data;
        }
    }
}

说明

  1. 这里的链队是有头结点的链队哈,头结点的存在,是为了方便处理链队,其本身不存放任何数值。
  2. 链队相比数组来说,没有复杂的索引计算,所以相对来说更好理解。
  3. 代码里没有写获取元素个数,如果想,再加一个NodeCount属性,自己维护即可。


结束语:针不戳。

猜你喜欢

转载自blog.csdn.net/Liyager/article/details/129062091