经典算法题每日演练——第十九题 双端队列
原文:经典算法题每日演练——第十九题 双端队列

话说大学的时候老师说妹子比工作重要~,工作可以再换,妹子这个。。。所以。。。这两个月也就一直忙着Fall in love,嗨,慢慢调整心态吧,

这篇就选一个简单的数据结构聊一聊,话说有很多数据结构都在玩组合拳,比如说:块状链表,块状数组,当然还有本篇的双端队列,是的,它就是

栈和队列的组合体。

一:概念

我们知道普通队列是限制级的一端进,另一端出的FIFO形式,栈是一端进出的LIFO形式,而双端队列就没有这样的限制级,也就是我们可以在

队列两端进行插入或者删除操作。

二:编码

1:定义结构体

通常情况下,队列的内部都是采用数组来实现,而且带有两个指针head和tail来指向数组的区间段,为了充分利用数组空间,我们也会用%来实

现逻辑上的循环数组,如下图。

 1     public class MyQueue
 2     {
 3         public int head;
 4
 5         public int tail;
 6
 7         public int maxSize;
 8
 9         public int size;
10
11         public T[] list;
12
13         public MyQueue()
14         {
15             head = tail = size = 0;
16             maxSize = 3;
17             list = new T[maxSize];
18         }
19     }

这里有一个注意的细节就是“size字段“,它是为了方便统计队列是否为满或者队列是否为空。

2:队尾入队

刚才也说了,双端队列是可以在队列的两端进行插入和删除的,要注意的是我们用head和tail指针的时候,tail指针是指向元素的下一个位置,

而head指针是指向当前元素,所以我们可以从tail端push数据的时候只要”顺时针“下移一个位置即可。

 1     /// <summary>
 2     /// 队尾入队
 3     /// </summary>
 4     /// <param name="t"></param>
 5     /// <returns></returns>
 6     public bool Push_Tail(T t)
 7     {
 8         //判断队列是否已满
 9         if (myQueue.size == myQueue.list.Length)
10             return false;
11
12         myQueue.list[myQueue.tail] = t;
13
14         //顺时针旋转
15         myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize;
16
17         myQueue.size++;
18
19         return true;
20     }

3:队尾出队

和队尾入队一样,我们只要将tail指针”逆时针“下移一个位置,当然有一个细节需要注意,就是tail指针有存在负值的情况,毕竟我们是做”--操作“的,

所以需要tail+maxSize,即:myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;

 1     /// <summary>
 2     /// 队尾出队
 3     /// </summary>
 4     /// <param name="edges"></param>
 5     /// <param name="t"></param>
 6     public T Pop_Tail()
 7     {
 8         //判断队列是否已空
 9         if (myQueue.size == 0)
10             return default(T);
11
12         //逆时针旋转(防止负数)
13         myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;
14
15         var temp = myQueue.list[myQueue.tail];
16
17         //赋予空值
18         myQueue.list[myQueue.tail] = default(T);
19
20         myQueue.size--;
21
22         return temp;
23     }

4:队首入队

从head端来说,我们push数据的时候是head指针“逆时针”旋转,要注意的是同样要防止负数的产生,并且head指针是指向当前元素。

 1     /// <summary>
 2     /// 队首入队
 3     /// </summary>
 4     /// <param name="t"></param>
 5     /// <returns></returns>
 6     public bool Push_Head(T t)
 7     {
 8         //判断队列是否已满
 9         if (myQueue.size == myQueue.list.Length)
10             return false;
11
12         //逆时针旋转(防止负数产生)
13         myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize;
14
15         //赋予元素
16         myQueue.list[myQueue.head] = t;
17
18         myQueue.size++;
19
20         return true;
21     }

5:队首出队

说到这个方法,我想大家应该都懂了双端队列的大概流程了,这个方法我也不用赘叙了。

 1     /// <summary>
 2     /// 队首出队
 3     /// </summary>
 4     /// <param name="edges"></param>
 5     /// <param name="t"></param>
 6     public T Pop_Head()
 7     {
 8         //判断队列是否已空
 9         if (myQueue.size == 0)
10             return default(T);
11
12         //获取队首元素
13         var temp = myQueue.list[myQueue.head];
14
15         //原来单位的值赋默认值
16         myQueue.list[myQueue.head] = default(T);
17
18         //顺时针旋转
19         myQueue.head = (myQueue.head + 1) % myQueue.maxSize;
20
21         myQueue.size--;
22
23         return temp;
24     }

从上面的四个方法可以看出:

当我们只使用Push_Tail和Pop_Tail的话,那它就是栈。

当我们只使用Push_Tail和Pop_Head的话,那它就是队列。

最后是全部代码:

View Code

  1 using System.Net;
  2 using System;
  3 using System.IO;
  4 using System.Collections.Generic;
  5 using System.Text;
  6 using System.Drawing;
  7 using System.Drawing.Imaging;
  8
  9 class Program
 10 {
 11     static void Main(string[] args)
 12     {
 13         DoubleQueue<int> queue = new DoubleQueue<int>();
 14
 15         queue.Push_Tail(10);
 16         queue.Push_Tail(20);
 17         queue.Push_Tail(30);
 18
 19         queue.Pop_Tail();
 20         queue.Pop_Tail();
 21         queue.Pop_Tail();
 22
 23         queue.Push_Tail(10);
 24         queue.Push_Head(20);
 25         queue.Push_Head(30);
 26         queue.Push_Head(30);
 27
 28         queue.Pop_Tail();
 29         queue.Pop_Tail();
 30         queue.Pop_Head();
 31
 32         queue.Push_Head(40);
 33         queue.Push_Tail(50);
 34         queue.Push_Tail(60);
 35     }
 36 }
 37
 38 /// <summary>
 39 /// 双端队列
 40 /// </summary>
 41 public class DoubleQueue<T>
 42 {
 43     public class MyQueue
 44     {
 45         public int head;
 46
 47         public int tail;
 48
 49         public int maxSize;
 50
 51         public int size;
 52
 53         public T[] list;
 54
 55         public MyQueue()
 56         {
 57             head = tail = size = 0;
 58             maxSize = 3;
 59             list = new T[maxSize];
 60         }
 61     }
 62
 63     MyQueue myQueue = new MyQueue();
 64
 65     /// <summary>
 66     /// 队尾入队
 67     /// </summary>
 68     /// <param name="t"></param>
 69     /// <returns></returns>
 70     public bool Push_Tail(T t)
 71     {
 72         //判断队列是否已满
 73         if (myQueue.size == myQueue.list.Length)
 74             return false;
 75
 76         myQueue.list[myQueue.tail] = t;
 77
 78         //顺时针旋转
 79         myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize;
 80
 81         myQueue.size++;
 82
 83         return true;
 84     }
 85
 86     /// <summary>
 87     /// 队尾出队
 88     /// </summary>
 89     /// <param name="edges"></param>
 90     /// <param name="t"></param>
 91     public T Pop_Tail()
 92     {
 93         //判断队列是否已空
 94         if (myQueue.size == 0)
 95             return default(T);
 96
 97         //逆时针旋转(防止负数)
 98         myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;
 99
100         var temp = myQueue.list[myQueue.tail];
101
102         //赋予空值
103         myQueue.list[myQueue.tail] = default(T);
104
105         myQueue.size--;
106
107         return temp;
108     }
109
110     /// <summary>
111     /// 队首入队
112     /// </summary>
113     /// <param name="t"></param>
114     /// <returns></returns>
115     public bool Push_Head(T t)
116     {
117         //判断队列是否已满
118         if (myQueue.size == myQueue.list.Length)
119             return false;
120
121         //逆时针旋转(防止负数产生)
122         myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize;
123
124         //赋予元素
125         myQueue.list[myQueue.head] = t;
126
127         myQueue.size++;
128
129         return true;
130     }
131
132     /// <summary>
133     /// 队首出队
134     /// </summary>
135     /// <param name="edges"></param>
136     /// <param name="t"></param>
137     public T Pop_Head()
138     {
139         //判断队列是否已空
140         if (myQueue.size == 0)
141             return default(T);
142
143         //获取队首元素
144         var temp = myQueue.list[myQueue.head];
145
146         //原来单位的值赋默认值
147         myQueue.list[myQueue.head] = default(T);
148
149         //顺时针旋转
150         myQueue.head = (myQueue.head + 1) % myQueue.maxSize;
151
152         myQueue.size--;
153
154         return temp;
155     }
156 }

posted on 2015-01-16 11:47 NET未来之路 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/4228234.html

经典算法题每日演练——第十九题 双端队列相关推荐

  1. 经典算法题每日演练——第二十二题 奇偶排序

    原文:经典算法题每日演练--第二十二题 奇偶排序 这个专题因为各种原因好久没有继续下去了,MM吧...你懂的,嘿嘿,不过还得继续写下去,好长时间不写,有些东西有点生疏了, 这篇就从简单一点的一个&qu ...

  2. 经典算法题每日演练——第二十四题 梳排序

    这篇再看看一个经典的排序,梳排序,为什么取名为梳,可能每个梳都有自己的gap吧,大梳子gap大一点,小梳子gap小一点. 上一篇我们看到鸡尾酒排序是在冒泡排序上做了一些优化,将单向的比较变成了双向,同 ...

  3. 经典算法题每日演练——第十题 树状数组

    原文:经典算法题每日演练--第十题 树状数组 有一种数据结构是神奇的,神秘的,它展现了位运算与数组结合的神奇魅力,太牛逼的,它就是树状数组,这种数据结构不是神人是发现不了的. 一:概序 假如我现在有个 ...

  4. 【100题】第五十九题 用C++编写不能被继承的类

    一,题目 用C++设计一个不能被继承的类. 二,分析 在Java中定义了关键字final,被final修饰的类不能被继承.但在C++中没有final这个关键字. 首先想到的是在C++ 中,子类的构造函 ...

  5. 经典算法题每日演练——第六题 协同推荐SlopeOne 算法

    原文:经典算法题每日演练--第六题 协同推荐SlopeOne 算法 相信大家对如下的Category都很熟悉,很多网站都有类似如下的功能,"商品推荐","猜你喜欢&quo ...

  6. 经典算法题每日演练——第一题 百钱买百鸡

    经典算法题每日演练--第一题 百钱买百鸡 原文:经典算法题每日演练--第一题 百钱买百鸡 百钱买百鸡的问题算是一套非常经典的不定方程的问题,题目很简单:公鸡5文钱一只,母鸡3文钱一只,小鸡3只一文钱, ...

  7. 经典算法题每日演练——第七题 KMP算法

    原文:经典算法题每日演练--第七题 KMP算法 在大学的时候,应该在数据结构里面都看过kmp算法吧,不知道有多少老师对该算法是一笔带过的,至少我们以前是的, 确实kmp算法还是有点饶人的,如果说红黑树 ...

  8. 第五章第二十九题(显示日历)(Display calendars)

    第五章第二十九题(显示日历)(Display calendars) **5.29(显示日历)编写程序,提示用户输入年份和代表该年的第一天是星期几的数字,然后在控制台上显示该年的日历表.例如,如果用户输 ...

  9. 《剑指offter》第十九题(js)

    第十九题 顺时针打印矩阵 题目描述 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...

最新文章

  1. xcode 消除警告
  2. (C++)高精度整数的存储、读入、比较和四则运算
  3. pythonunbuffered_python所遇到的坑
  4. Tomcat 8.5 配置 SSL 证书
  5. 我想问一下男生,一个女生那么真诚热情又卑微的喜欢你,你们是怎么做到视而不见的呢?
  6. 【原创】中文分词系统 ICTCLAS2015 的JAVA封装和多线程执行(附代码)
  7. [Android Pro] 组件化:企业级大型项目必经之路
  8. 软件dfmea_DFMEA与PFMEA之间不得不说的关系
  9. matlab分析系统灵敏度,matlab灵敏度分析函数
  10. 如何管理好团队?史玉柱自述
  11. 【例题4-2 uva489】Hangman Judge
  12. NutUI 京东小程序发布了!
  13. 对List集合嵌套了map集合的排序
  14. Java面向对象的主要特征
  15. 计算机里的word怎么重装,word能卸载重装吗 word卸载重装
  16. php常用系统函数库,PHP常用函数大全
  17. JavaScript 内存溢出解决办法 亲测有效
  18. 参加中国移动开发者大会有感
  19. 用 Python 给女友做了个可能会被打死的七夕礼物
  20. 计算机毕业设计基于asp.net校园二手物品交易平台

热门文章

  1. WinCE/Mobile上下滑动浏览DataGrid数据 【转】
  2. chm文件无法正常显示
  3. 学习笔记之Iframe
  4. C# ToString()方法
  5. 利用Python如何实现数据驱动的接口自动化测试
  6. 2017.04.15【NOIP2017提高组】模拟赛B组 T2:渡河
  7. js 编码、解码与asp.net 编码、解码
  8. Log4Net使用入门
  9. (转载)不一样的冒泡排序
  10. 打造最好用的离线QQ截图工具 C#