您现在的位置是:网站首页> 编程资料编程资料

算法系列15天速成 第九天 队列_相关技巧_

2023-05-27 494人已围观

简介 算法系列15天速成 第九天 队列_相关技巧_

一:概念

          队列是一个”先进先出“的线性表,牛X的名字就是“First in First Out(FIFO)”,生活中有很多这样的场景,比如读书的时候去食堂打饭时的”排队“。当然我们拒绝插队。

二:存储结构

         前几天也说过,线性表有两种”存储结构“,① 顺序存储,②链式存储。当然“队列”也脱离不了这两种服务,这里我就分享一下“顺序存储”。

     顺序存储时,我们会维护一个叫做”head头指针“和”tail尾指针“,分别指向队列的开头和结尾。


代码段如下:

复制代码 代码如下:

#region 队列的数据结构
    ///
/// 队列的数据结构
///

///
    public class SeqQueue
    {
        private const int maxSize = 100;

        public int MaxSize
        {
            get { return maxSize; }
        }

        ///


/// 顺序队列的存储长度
///

        public T[] data = new T[maxSize];

        //头指针
        public int head;

        //尾指针
        public int tail;

    }
    #endregion

三:常用操作

      队列的操作一般分为:

      ①: 初始化队列。

      ②:   出队。

      ③: 入队。

      ④: 获取队头。

      ⑤: 获取队长。


1:初始化队列

        这个很简单,刚才也说过了,队列是用一个head和tail的指针来维护。分别设置为0即可。

2:出队

       看着“队列”的结构图,大家都知道,出队肯定跟head指针有关,需要做两件事情,

       第一: 判断队列是否为空,这个我想大家都知道。
       第二: 将head头指针向后移动一位,返回head移动前的元素,时间复杂度为O(1)。



代码段如下:

复制代码 代码如下:

#region 队列元素出队
        ///
/// 队列元素出队
///

///
///
///
        public T SeqQueueOut(SeqQueue seqQueue)
        {
            if (SeqQueueIsEmpty(seqQueue))
                throw new Exception("队列已空,不能进行出队操作");

            var single = seqQueue.data[seqQueue.head];

            //head指针自增
            seqQueue.data[seqQueue.head++] = default(T);

            return single;

        }
        #endregion

3:入队

      这个跟”出队“的思想相反,同样也是需要做两件事情。

      第一:判断队列是否已满。

      第二:将tail指针向后移动一位,时间复杂度为O(1)。

代码段如下:

复制代码 代码如下:

#region 队列元素入队
        ///
/// 队列元素入队
///

///
///
///
///
        public SeqQueue SeqQueueIn(SeqQueue seqQueue, T data)
        {
            //如果队列已满,则不能进行入队操作
            if (SeqQueueIsFull(seqQueue))
                throw new Exception("队列已满,不能入队操作");

            //入队操作
            seqQueue.data[seqQueue.tail++] = data;

            return seqQueue;
        }
        #endregion

4: 获取队头

       知道”出队“和”入队“的原理,相信大家都懂的如何进行”获取队头“操作,唯一不一样的就是

       他是只读操作,不会破坏”队列“结构,时间复杂度为O(1)。

 

代码段如下:

复制代码 代码如下:

#region 获取队头元素
        ///
        /// 获取队头元素
        ///

        ///
        ///
        ///
        public T SeqQueuePeek(SeqQueue seqQueue)
        {
            if (SeqQueueIsEmpty(seqQueue))
                throw new Exception("队列已空,不能进行出队操作");

            return seqQueue.data[seqQueue.head];
        }
        #endregion

5: 获取队长

       大家都知道,我们是用数组来实现队列,所以千万不要想当然的认为数组长度是XXX,

       我们维护的是一个head和tail的指针,所以长度自然就是tail-head咯,时间复杂度为O(1)。

代码段如下:

复制代码 代码如下:

///
/// 获取队列长度
///

///
///
///
        public int SeqQueueLen(SeqQueue seqQueue)
        {
            return seqQueue.tail - seqQueue.head;
        }

然后上一下总的运行代码:

复制代码 代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SeqQueue
{
    public class Program
    {
        static void Main(string[] args)
        {
            SeqQueue seqQueue = new SeqQueue();

            SeqQueueClass queueManage = new SeqQueueClass();

            Console.WriteLine("目前队列是否为空:" + queueManage.SeqQueueIsEmpty(seqQueue) + "\n");

            Console.WriteLine("将ID=1和ID=2的实体加入队列");
            queueManage.SeqQueueIn(seqQueue, new Student() { ID = 1, Name = "hxc520", Age = 23 });
            queueManage.SeqQueueIn(seqQueue, new Student() { ID = 2, Name = "一线码农", Age = 23 });

            Display(seqQueue);

            Console.WriteLine("将队头出队");
            //将队头出队
            var student = queueManage.SeqQueueOut(seqQueue);

            Display(seqQueue);

            //获取队顶元素
            student = queueManage.SeqQueuePeek(seqQueue);

            Console.Read();
        }
        //展示队列元素
        static void Display(SeqQueue seqQueue)
        {
            Console.WriteLine("******************* 链表数据如下 *******************");

            for (int i = seqQueue.head; i < seqQueue.tail; i++)
                Console.WriteLine("ID:" + seqQueue.data[i].ID +
                                  ",Name:" + seqQueue.data[i].Name +
                                  ",Age:" + seqQueue.data[i].Age);

            Console.WriteLine("******************* 链表数据展示完毕 *******************\n");
        }
    }

    #region 学生数据实体
    ///


/// 学生数据实体
///

    public class Student
    {
        public int ID { get; set; }

        public string Name { get; set; }

        public int Age { get; set; }
    }
    #endregion

    #region 队列的数据结构
    ///


/// 队列的数据结构
///

///
    public class SeqQueue
    {
        private const int maxSize = 100;

        public int MaxSize
        {
            get { return maxSize; }
        }

        ///


/// 顺序队列的存储长度
///

        public T[] data = new T[maxSize];

        //头指针
        public int head;

        //尾指针
        public int tail;

    }
    #endregion

    #region 队列的基本操作
    ///


/// 队列的基本操作
///

    public class SeqQueueClass
    {
        #region 队列的初始化操作
        ///
/// 队列的初始化操作
///

///
///
        public SeqQueue SeqQueueInit(SeqQueue seqQueue)
        {
            seqQueue.head = 0;
            seqQueue.tail = 0;

            return seqQueue;
        }
        #endregion

        #region 队列是否为空
        ///


/// 队列是否为空
///

///
///
///
        public bool SeqQueueIsEmpty(SeqQueue seqQueue)
        {
            //如果两指针重合,说明队列已经清空
            if (seqQueue.head == seqQueue.tail)
                return true;
            return false;
        }
        #endregion

        #region 队列是否已满
        ///


/// 队列是否已满
///

///
///
///
        public bool SeqQueueIsFull(SeqQueue seqQueue)
        {
            //如果尾指针到达数组末尾,说明队列已经满
            if (seqQueue.tail == seqQueue.MaxSize)
                return true;
            return false;
        }
        #endregion

        #region 队列元素入队
        ///


/// 队列元素入队
///

///
///
///
///
        public SeqQueue SeqQueueIn(SeqQueue seqQueue, T data)
        {
            //如果队列已满,则不能进行入队操作
            if (SeqQueueIsFull(seqQueue))
                throw new Exception("队列已满,不能入队操作");

            //入队操作
            seqQueue.data[seqQueue.tail++] = data;

            return seqQueue;
        }
        #endregion

        #region 队列元素出队
        ///


/// 队列元素出队
///

///
///
///
        public T SeqQueueOut(SeqQueue seqQueue)
        {
            if (SeqQueueIsEmpty(seqQueue))
                throw new Exception("队列已空,不能进行出队操作");

            var single = seqQueue.data[seqQueue.head];

            //head指针自增
            seqQueue.data[seqQueue.head++] = default(T);

            return single;

        }
        #endregion

        #region 获取队头元素
        ///


/// 获取队头元素
///

///
/// 提示: 本文由整理自网络,如有侵权请联系本站删除!
本站声明:
1、本站所有资源均来源于互联网,不保证100%完整、不提供任何技术支持;
2、本站所发布的文章以及附件仅限用于学习和研究目的;不得将用于商业或者非法用途;否则由此产生的法律后果,本站概不负责!

-六神源码网