zoukankan      html  css  js  c++  java
  • 第四篇 栈与队列(二)

    一、队列的定义

      队列(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; }
        }
  • 相关阅读:
    在 LR 中如何解决Socket 接收数据的验证
    UE 的文件比较方法
    使用plSQL连接Oracle报错,SQL*Net not properly installed和TNS:无法解析指定的连接标识符
    plsql developer连接oracle数据库
    将列表中的字符以‘*’连接生成一个新的字符串
    ElasticSearch之CURL操作
    MySQL 5.7.21 免安装版配置教程
    C# IL DASM 使用-破解c#软件方法
    For-each Loop,Index++ Loop , Iterator 那个效率更高
    10种简单的Java性能优化
  • 原文地址:https://www.cnblogs.com/xiuyuanjing/p/4163079.html
Copyright © 2011-2022 走看看