算法:基于 RingBuffer 的 Deque 实现

背景

前两篇文章介绍了 Queue 的实现,很多类库都引入了 Deque,Deque 可以两头添加和删除,然后在 Deque 之上构建 Queue 和 Stack。

Deque

代码

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 using System.Threading.Tasks;
  6 
  7 namespace DataStuctureStudy.Deques
  8 {
  9     public class Deque<T>
 10     {
 11         private T[] _items = new T[0];
 12         private int _size = 0;
 13         private int _head = -1;
 14         private int _tail = -1;
 15 
 16         private void AllocateNewArray()
 17         {
 18             int newLength = (_size == 0) ? 4 : _size * 2;
 19 
 20             T[] newArray = new T[newLength];
 21 
 22             if (_size > 0)
 23             {
 24                 // copy contents...
 25                 // if the array has no wrapping, just copy the valid range
 26                 // else copy from head to end of the array and then from 0 to the tail
 27 
 28                 // if tail is less than head we've wrapped
 29                 var newIndex = 0;
 30                 if (_tail < _head)
 31                 {
 32                     // copy the _items[head].._items[end] -> newArray[0]..newArray[N]
 33                     for (int index = _head; index < _items.Length; index++)
 34                     {
 35                         newArray[newIndex] = _items[index];
 36                         newIndex++;
 37                     }
 38 
 39                     // copy _items[0].._items[tail] -> newArray[N+1]..
 40                     for (int index = 0; index <= _tail; index++)
 41                     {
 42                         newArray[newIndex] = _items[index];
 43                         newIndex++;
 44                     }
 45                 }
 46                 else
 47                 {
 48                     // copy the _items[head].._items[tail] -> newArray[0]..newArray[N]
 49                     for (int index = _head; index <= _tail; index++)
 50                     {
 51                         newArray[newIndex] = _items[index];
 52                         newIndex++;
 53                     }
 54                 }
 55                 _head = 0;
 56                 _tail = _size - 1; // compensate for the extra bump
 57             }
 58             else
 59             {
 60                 // nothing in the array
 61                 _head = -1;
 62                 _tail = -1;
 63             }
 64 
 65             _items = newArray;
 66         }
 67 
 68         public void EnqueueFirst(T item)
 69         {
 70             // if the array needs to grow
 71             if (_items.Length == _size)
 72             {
 73                 AllocateNewArray();
 74             }
 75 
 76             // since we know the array isn't full and _head is greater than 0
 77             // we know the slot in front of head is open
 78             if (_head > 0)
 79             {
 80                 _head--;
 81             }
 82             else
 83             {
 84                 // otherwise we need to wrap around to the end of the array
 85                 _head = _items.Length - 1;
 86                 if (_tail == -1)
 87                 {
 88                     _tail = _head;
 89                 }
 90             }
 91             _items[_head] = item;
 92             _size++;
 93         }
 94 
 95         public void EnqueueLast(T item)
 96         {
 97             // if the array needs to grow
 98             if (_items.Length == _size)
 99             {
100                 AllocateNewArray();
101             }
102 
103             // now we have a properly sized array and can focus on wrapping issues.
104             // if _tail is at the end of the array we need to wrap around
105             if (_tail == _items.Length - 1)
106             {
107                 _tail = 0;
108             }
109             else
110             {
111                 _tail++;
112 
113                 if (_head == -1)
114                 {
115                     _head = _tail;
116                 }
117             }
118             _items[_tail] = item;
119             _size++;
120         }
121 
122         public T DequeueFirst()
123         {
124             if (_size == 0)
125             {
126                 throw new InvalidOperationException("The deque is empty");
127             }
128 
129             T value = _items[_head];
130 
131             if (_head == _items.Length - 1)
132             {
133                 // if the head is at the last index in the array - wrap around.
134                 _head = 0;
135             }
136             else
137             {
138                 // move to the next slot
139                 _head++;
140             }
141             _size--;
142             return value;
143         }
144 
145         public T DequeueLast()
146         {
147             if (_size == 0)
148             {
149                 throw new InvalidOperationException("The deque is empty");
150             }
151 
152             T value = _items[_tail];
153 
154             if (_tail == 0)
155             {
156                 // if the tai is at the first index in the array - wrap around.
157                 _tail = _items.Length - 1;
158             }
159             else
160             {
161                 // move to the previous slot
162                 _tail--;
163             }
164             _size--;
165             return value;
166         }
167 
168         public T PeekFirst()
169         {
170             if (_size == 0)
171             {
172                 throw new InvalidOperationException("The deque is empty");
173             }
174             return _items[_head];
175         }
176 
177         public T PeekLast()
178         {
179             if (_size == 0)
180             {
181                 throw new InvalidOperationException("The deque is empty");
182             }
183             return _items[_tail];
184         }
185 
186         public int Count
187         {
188             get
189             {
190                 return _size;
191             }
192         }
193     }
194 }
原文地址:https://www.cnblogs.com/happyframework/p/3481889.html