• 算法:基于 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 }
  • 相关阅读:
    vs entityframwork Validation failed for one or more entities
    samba配置
    Python中list的拷贝问题
    Android文件存储
    Java接口回调模拟按钮监听
    Android更新UI的五种方式
    Android handler学习笔记
    FBReaderJ学习笔记(四):SelectionPopup样式更改
    FBReaderJ学习笔记(三):Footer底部状态栏更改
    FBReaderJ学习笔记(五):附录
  • 原文地址:https://www.cnblogs.com/happyframework/p/3481889.html
Copyright © 2020-2023  润新知