在日常生活中,队列的例子比比皆是,例如在车展排队买票,排在队头的处理完离开,后来的必须在队尾排队等候。在程序设计中,队列也有着广泛的应用,例如计算机的任务调度系统、为了削减高峰时期订单请求的消息队列等等。与栈类似,队列也是属于操作受限的线性表,不过队列是只允许在一端进行插入,在另一端进行删除。在其他数据结构如树的一些基本操作中(比如树的广度优先遍历)也需要借助队列来实现,因此这里我们来看看队列。

1.1 队列的基本特征

数据结构基础温故-3.队列

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。它是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端称为队尾,允许删除的一端称为队头。

1.2 队列的基本操作

数据结构基础温故-3.队列

  (1)入队(Enqueue):将一个数据元素插入队尾;

  (2)出队(Dequeue):读取队头节点数据并删除该节点;

二、队列的基本实现

  既然队列也属于特殊的线性表,那么其实现也会有两种形式:顺序存储结构和链式存储结构。首先,对于Queue,我们希望能够提供以下几个方法供调用:

Queue<T>()

创建一个空的队列

void Enqueue(T s)

往队列中添加一个新的元素

T Dequeue()

移除队列中最早添加的元素

bool IsEmpty()

队列是否为空

int Size()

队列中元素的个数

2.1 队列的顺序存储实现

  与Stack不同,在队列中我们需要定义一个head队头“指针”和tail队尾“指针”,当新元素入队时tail+1,当老元素出队时head+1。下面重点来看看Enqueue和Dequeue两个方法的代码实现。

  (1)入队:Enqueue

        public void EnQueue(T item)
        {
            if (Size == items.Length)
            {
                // 扩大数组容量
                ResizeCapacity(items.Length * 2);
            }

            items[tail] = item;
            tail++;
            size++;
        }

  新元素入队后,tail队尾指针向前移动指向下一个新元素要插入的位置;这里仍然模仿.NET中的实现,在数组容量不足时及时进行扩容以容纳新元素入队。

  (2)出队:Dequeue

        public T DeQueue()
        {
            if (Size == 0)
            {
                return default(T);
            }

            T item = items[head];
            items[head] = default(T);
            head++;

            if (head > 0 && Size == items.Length / 4)
            {
                // 缩小数组容量
                ResizeCapacity(items.Length / 2);
            }

            size--;
            return item;
        }

  在对老元素进行出队操作时,首先取得head指针所指向的老元素,然后将head指针向前移动一位指向下一个将出队的老元素。这里将要出队的元素所在数组中的位置重置为默认值。最后判断容量是否过小,如果是则进行数组容量的缩小。

  下面是完整的队列模拟实现代码,仅供参考,这里就不再做基本功能测试了,有兴趣的读者可以自行测试:

    /// <summary>
    /// 基于数组的队列实现
    /// </summary>
    /// <typeparam name="T">类型</typeparam>
    public class MyArrayQueue<T>
    {
        private T[] items;
        private int size;
        private int head;
        private int tail;

        public MyArrayQueue(int capacity)
        {
            this.items = new T[capacity];
            this.size = 0;
            this.head = this.tail = 0;
        }

        /// <summary>
        /// 入队
        /// </summary>
        /// <param name="item">入队元素</param>
        public void EnQueue(T item)
        {
            if (Size == items.Length)
            {
                // 扩大数组容量
                ResizeCapacity(items.Length * 2);
            }

            items[tail] = item;
            tail++;
            size++;
        }

        /// <summary>v 
        /// 出队
        /// </summary>
        /// <returns>出队元素</returns>
        public T DeQueue()
        {
            if (Size == 0)
            {
                return default(T);
            }

            T item = items[head];
            items[head] = default(T);
            head++;

            if (head > 0 && Size == items.Length / 4)
            {
                // 缩小数组容量
                ResizeCapacity(items.Length / 2);
            }

            size--;
            return item;
        }

        /// <summary>
        /// 重置数组大小
        /// </summary>
        /// <param name="newCapacity">新的容量</param>
        private void ResizeCapacity(int newCapacity)
        {
            T[] newItems = new T[newCapacity];
            int index = 0;
            if (newCapacity > items.Length)
            {
                for (int i = 0; i < items.Length; i++)
                {
                    newItems[index++] = items[i];
                }
            }
            else
            {
                for (int i = 0; i < items.Length; i++)
                {
                    if (!items[i].Equals(default(T)))
                    {
                        newItems[index++] = items[i];
                    }
                }

                head = tail = 0;
            }

            items = newItems;
        }

        /// <summary>
        /// 栈是否为空
        /// </summary>
        /// <returns>true/false</returns>
        public bool IsEmpty()
        {
            return this.size == 0;
        }

        /// <summary>
        /// 栈中节点个数
        /// </summary>
        public int Size
        {
            get
            {
                return this.size;
            }
        }
    }
View Code

相关文章:

  • 2021-11-22
  • 2021-07-22
  • 2021-08-16
  • 2021-08-16
  • 2021-09-11
  • 2021-12-06
猜你喜欢
  • 2021-05-31
  • 2021-11-27
  • 2021-05-19
  • 2021-09-30
  • 2022-02-06
  • 2021-08-22
  • 2021-06-26
相关资源
相似解决方案