第四篇 栈与队列(二)

一、队列的定义

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

  如图所示:

  第四篇 栈与队列(二)

二、队列的抽象数据结构

  因为队列本身是线性表,因此具有线性表的所有特性。而作为先进先出的线性表,也有其自身的一些特性。

  如图所示:

  第四篇 栈与队列(二)

三、循环队列

  在队列的顺序存储结构中,对队列进行插入操作,是在其队尾插入一个元素,可以一直添加到队列已满为止,算法复杂度为O(1),而当执行取出操作时,在队列的头部取出一个元素,同时其后面的元素依此向前移动一位。从而导致其算法复杂度为O(n)。其实这类似与我们日常排队买票的情景,当前面的人买到票以后,离开了,后面的所有等待购票的人依此向前前进一步。

  为了解决上面插入操作时后面的依此向前移动,我们提出了循环队列。

  循环队列:我们把头尾相接的顺序存储结构的队列称为循环队列。

四、循环队列的算法实现

采用空闲一个位置的方式,即N个元素空间的循环队列最多只能存放N-1个有效元素。这也是大多数教材的做法。
1) 循环队列初始化:front=rear=0;
2)入队操作:rear=(rear+1)%size;
3)出队操作:front=(front+1)%size;
4)判断是否为空队列:front==rear;
5)判断队列是否已满:front=(rear+1)%size;
6)遍历队列各元素。

  C#代码如下

 /// <summary>

    /// 循环队列的算法实现

    /// </summary>





    /*

     *算法描述 

     * 采用空闲一个位置的方式,即N个元素空间的循环队列最多只能存放N-1个有效元素。这也是大多数教材的做法。

        1) 循环队列初始化:front=rear=0;

        2)入队操作:rear=(rear+1)%size;

        3)出队操作:front=(front+1)%size;

        4)判断是否为空队列:front==rear;

        5)判断队列是否已满:front=(rear+1)%size;

        6)遍历队列各元素。

     * 

     */



    /*

     *参考资料

     *http://www.cnblogs.com/zhaoyl/archive/2012/09/20/2695136.html

     *http://blog.csdn.net/huangkq1989/article/details/5719529

     * 大话数据结构

     */





    public class CirculeQueue

    {

        /// <summary>

        /// 队列的头指针

        /// </summary>

        public int Front;



        /// <summary>

        /// 队列的尾指针

        /// </summary>

        public int Rear;



        /// <summary>

        /// 队列的数据

        /// </summary>

        public DataType[] Data;



        /// <summary>

        /// 队列的长度

        /// </summary>

        public int Length;



        /// <summary>

        /// 队列的最大值

        /// </summary>

        public int MaxSize;



        public CirculeQueue(int maxSize)

        {

            if (maxSize < 1)

                throw new ApplicationException("The queue size can not less than 1.");

            Data = new DataType[maxSize];

            MaxSize = maxSize;

        }



        /// <summary>

        /// 队列是否为空

        /// </summary>

        /// <returns></returns>

        public bool IsEmpty()

        {

            return Front == Rear;

        }



        /// <summary>

        /// 插入队列元素

        /// </summary>

        /// <param name="element">元素</param>

        public void Enqueue(DataType element)

        {

            //先判断队列是否已满

            if (Front == (Rear + 1) % MaxSize)

                throw new ApplicationException("The Queue is Full.");

            //在队尾插入元素,队尾指针向后移动一位

            Rear = (Rear + 1) % MaxSize;

            Data[Rear] = element;

            Length++;

        }



        /// <summary>

        /// 取出队头元素

        /// </summary>

        /// <returns></returns>

        public DataType Dequeue()

        {

            //先判断队列是否为空

            if (Front == Rear)

                throw new ApplicationException("The Queue is Empty.");

            //从队头取出元素

            Front = (Front + 1) % MaxSize;

            Length--;

            return Data[Front];

        }

    }



    /// <summary>

    /// 队列元素

    /// </summary>

    public class DataType

    {

        public object Data { get; set; }

    }

五、队列的链式存储结构

  队列的链式存储结构,其实就是线性表的单链表,只不不过它只能尾进头出。称为链队列。

  如图

第四篇 栈与队列(二)

  当队列为空时,front和rear都指向头节点。

  链队列的结构:如下图所示

  第四篇 栈与队列(二)

链队列的算法实现

C#代码如下:

  /// <summary>

    /// 链队列的算法实现

    /// </summary>



    /*

     * 算法描述

     * 链队列属于单链表,因此具有单链表的特性

     *  1) 循环队列初始化:front=rear=null;

        2)入队操作:申请存储空间,将队尾指针移动一位;

        3)出队操作:指向队头指针;

     * 

     */



    /*

     * 参考资料

     * http://www.cnblogs.com/iwuyudong/archive/2010/12/20/2234111.html

     * http://blog.163.com/zhoumhan_0351/blog/static/39954227201001411343987/

     * http://www.cnblogs.com/navorse/articles/1889247.html

     * http://blog.chinaunix.net/uid-21768364-id-186080.html

     */

    public class LinkedQueue

    {

        /// <summary>

        /// 队列的头指针

        /// </summary>

        public Node FrontNode;



        /// <summary>

        /// 队列的尾指针

        /// </summary>

        public Node RearNode;



        /// <summary>

        /// 队列的数据

        /// </summary>

        public DataType[] Data;



        /// <summary>

        /// 队列的长度

        /// </summary>

        public int Length;



        public LinkedQueue()

        {



        }



        /// <summary>

        /// 队列是否为空

        /// </summary>

        /// <returns></returns>

        public bool IsEmpty()

        {

            return FrontNode == RearNode;

        }



        /// <summary>

        /// 插入队列元素

        /// </summary>

        /// <param name="element">元素</param>

        public void Enqueue(DataType element)

        {

            //创建新节点存放数据

            Node node = new Node();

            node.Data = element;

            node.NextNode = null;

            //将尾节点指向当前节点

            RearNode.NextNode = node;

            RearNode = node;

            Length++;

        }



        /// <summary>

        /// 取出队头元素

        /// </summary>

        /// <returns></returns>

        public DataType Dequeue()

        {

            //先判断队列是否为空

            if (FrontNode == RearNode)

                throw new ApplicationException("The Queue is Empty.");

            //将要删除的头节点赋给tempNode节点

            Node tempNode = FrontNode.NextNode;

            //将头结点的值赋给数据项data

            DataType data = tempNode.Data;

            //将原队头给点后继p->next 赋值给头给点后继.

            FrontNode = tempNode.NextNode;

            if (RearNode == tempNode)

                RearNode = FrontNode;

            return data;

        }

    }



    public class Node

    {

        /// <summary>

        /// 数据存储单元

        /// </summary>

        public DataType Data { get; set; }



        /// <summary>

        /// 下一个节点

        /// </summary>

        public Node NextNode { get; set; }

    }

 

你可能感兴趣的:(队列)