經典算法題每日演練——第十九題 雙端隊列


     話說大學的時候老師說妹子比工作重要~,工作可以再換,妹子這個。。。所以。。。這兩個月也就一直忙着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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM