第四篇 栈与队列(二)

一、队列的定义

  队列(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; }
    }
时间: 2024-08-24 11:14:21

第四篇 栈与队列(二)的相关文章

第四篇 栈与队列(一)

一.栈的定义 栈是限定仅在表尾进行插入和删除操作的线性表:栈又称为后进先出的线性表(LIFO). 栈顶:允许插入和删除操作的一端称为栈顶:而另一端则为栈底. 栈的操作:插入数据称为进栈(压栈.入栈):栈的删除操作称为出栈(弹栈). 如下图所示: 二.栈的抽象数据类型 栈是一种特殊的线性表,因此具有线性表的所有特性.如除根节点以外,有且仅有一个前驱节点等. 三.栈的顺序存储结构及实现 C#代码实现 /// <summary> /// 栈的顺序存储结构 /// </summary> /

数据结构实验之栈与队列二:一般算术表达式转换成后缀式

数据结构实验之栈与队列二:一般算术表达式转换成后缀式 Description 对于一个基于二元运算符的算术表达式,转换为对应的后缀式,并输出之. Input 输入一个算术表达式,以‘#’字符作为结束标志. Output 输出该表达式转换所得到的后缀式. Sample Input a*b+(c-d/e)*f# Output ab*cde/-f*+ #include <stdio.h> #include <stdlib.h> char s[100005]; //分配栈的大小 int m

第四章 栈与队列

一.栈的定义 栈(stack)是限定尽在表尾进行插入和删除操作的线性表. 我们把允许插入和删除的一端成为栈顶(top),另一端成为栈底(bottom),不含任何数据元素的栈称为空栈.栈又称为后进先出(LIFO)的线性表. 图示出栈入栈操作: 二.栈的抽象数据类型 图示栈的各项操作: 由于栈本身就是一个线性表,那么上一章我们讨论了线性表的顺序存储和链式存储,对于栈来说也是同样适用的. 三.栈的顺序存储结构及实现 来看一下栈的结构定义: 若存储栈的长度为StackSize,则栈顶位置top必须小于S

算法:(四)栈和队列

(一)栈和队列的基本性质 栈是先进后出的 队列是先进先出的 栈和队列在实现结构上可以有数组和链表两种形式 数组结构实现较容易 用链表结构较复杂,因为牵扯很多指针操作 (二)队列和栈的基本操作 pop操作(栈尾弹出一个元素) push操作(栈/队列尾加入一个元素) shift操作(队头弹出一个元素) 栈和队列的基本操作,都是时间复杂度都为O(1)的操作 (三)深度优先遍历(DFS)和宽度优先遍历(BFS) 深度优先遍历可以用栈实现 宽度优先遍历可以用队列实现 (四)双端队列和优先级队列 双端队列首

简单数据结构(四)栈和队列的简单应用

     编程判断一个字符串是否是回文.回文是指一个字符序列以中间字符为基准两边字符完全相同,如字符序列" ACBDEDBCA"是回文.      算法思想:判断一个字符序列是否是回文,就是把第一个字符与最后一个字符相比较,第二个字符与倒数第二个字符比较,依次类推,第 i 个字符与第 n-i个字符比较.如果每次比较都相等,则为回文,如果某次比较不相等,就不是回文.因此,可以把字符序列分别入队列和栈,然后逐个出队列和出栈并比较出队列的字符和出栈的字符是否相等,若全部相等则该字符序列就是回

Java数据结构与算法(第四章栈和队列)

本章涉及的三种数据存储类型:栈.队列和优先级队列. 不同类型的结构 程序员的工具 数组是已经介绍过的数据存储结构,和其他结构(链表.树等等)一样,都适用于数据应用中作数据记录. 然而,本章要讲解的是数据结构和算法更多的是作为程序员的工具来运用.它们组要作为构思算法的辅助工具,而不是完全的数据存储工具.这些数据结构的生命周期比那些数据库类型的结构要短的多.在程序操作执行期间它们才被创建,通常它们去执行某项特殊的任务,当完成之后,它们就被销毁. 受限访问 在数组中,只要知道下标就可以访问数据项.或顺

数据结构看书笔记(四)--栈与队列

栈与队列 栈是限定尽在表尾进行插入和删除操作的线性表  队列是只允许在一端进行插入操作.而在另一端进行删除操作的线性表栈的定义: 栈(Stack)是限定仅在表尾进行插入和删除操作的线性表 其中允许插入的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈.栈又称为先进后出(Last In First Out)的线性表,简称为LIFO结构. 特殊之处在与限制了这个线性表的插入和删除位置只能是在栈顶.  栈的插入操作,叫做进栈,也称为压栈.入栈. 栈的删除操作,叫做出

《大话数据结构》--- 第四章 栈与队列

栈(Stack)是限定仅在表尾进行插入和删除操作的线性表. 把允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈.栈又称为后进先出的线性表,简称LIFO结构. 栈的插入操作,叫做进栈,也称压栈.入栈. 栈的删除操作,叫做出栈,也称弹栈. 当两个栈一个占用内存可能太大 但内容较少 另一个占用内存可能有剩余 可以考虑使用一个数组来存两个栈,一个底端从下标0开始,另一个底端从下标n-1开始,只要两个栈不碰头 就可以实现空间的有效利用. 栈的链式存储结构称为栈链. 如果栈的使用过

数据结构系列(四)栈与队列

栈 定义 栈是一种特殊的线性表 操作 存储结构 从存储结构来看,分为顺序栈和链栈,同线性表的划分 应用 递归-菲波那切数列 后缀表达式-逆波兰表示 队列 定义 队列也是一种特殊的线性表 操作 队列是一种先进先出的线性表 FIFIO,允许插入的一端是队尾,允许删除的一端是队头 存储结构 从存储结构来看,分为顺序队列和链队列,同线性表的划分 应用