您的位置:首页 > 产品设计 > UI/UE

算法:基于 RingBuffer 的 Deque 实现

2013-12-16 12:08 483 查看

背景

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

Deque

代码

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

namespace DataStuctureStudy.Deques
{
public class Deque<T>
{
private T[] _items = new T[0];
private int _size = 0;
private int _head = -1;
private int _tail = -1;

private void AllocateNewArray()
{
int newLength = (_size == 0) ? 4 : _size * 2;

T[] newArray = new T[newLength];

if (_size > 0)
{
// copy contents...
// if the array has no wrapping, just copy the valid range
// else copy from head to end of the array and then from 0 to the tail

// if tail is less than head we've wrapped
var newIndex = 0;
if (_tail < _head)
{
// copy the _items[head].._items[end] -> newArray[0]..newArray

for (int index = _head; index < _items.Length; index++)
{
newArray[newIndex] = _items[index];
newIndex++;
}

// copy _items[0].._items[tail] -> newArray[N+1]..
for (int index = 0; index <= _tail; index++)
{
newArray[newIndex] = _items[index];
newIndex++;
}
}
else
{
// copy the _items[head].._items[tail] -> newArray[0]..newArray

for (int index = _head; index <= _tail; index++)
{
newArray[newIndex] = _items[index];
newIndex++;
}
}
_head = 0;
_tail = _size - 1; // compensate for the extra bump
}
else
{
// nothing in the array
_head = -1;
_tail = -1;
}

_items = newArray;
}

public void EnqueueFirst(T item)
{
// if the array needs to grow
if (_items.Length == _size)
{
AllocateNewArray();
}

// since we know the array isn't full and _head is greater than 0
// we know the slot in front of head is open
if (_head > 0)
{
_head--;
}
else
{
// otherwise we need to wrap around to the end of the array
_head = _items.Length - 1;
if (_tail == -1)
{
_tail = _head;
}
}
_items[_head] = item;
_size++;
}

public void EnqueueLast(T item)
{
// if the array needs to grow
if (_items.Length == _size)
{
AllocateNewArray();
}

// now we have a properly sized array and can focus on wrapping issues.
// if _tail is at the end of the array we need to wrap around
if (_tail == _items.Length - 1)
{
_tail = 0;
}
else
{
_tail++;

if (_head == -1)
{
_head = _tail;
}
}
_items[_tail] = item;
_size++;
}

public T DequeueFirst()
{
if (_size == 0)
{
throw new InvalidOperationException("The deque is empty");
}

T value = _items[_head];

if (_head == _items.Length - 1)
{
// if the head is at the last index in the array - wrap around.
_head = 0;
}
else
{
// move to the next slot
_head++;
}
_size--;
return value;
}

public T DequeueLast()
{
if (_size == 0)
{
throw new InvalidOperationException("The deque is empty");
}

T value = _items[_tail];

if (_tail == 0)
{
// if the tai is at the first index in the array - wrap around.
_tail = _items.Length - 1;
}
else
{
// move to the previous slot
_tail--;
}
_size--;
return value;
}

public T PeekFirst()
{
if (_size == 0)
{
throw new InvalidOperationException("The deque is empty");
}
return _items[_head];
}

public T PeekLast()
{
if (_size == 0)
{
throw new InvalidOperationException("The deque is empty");
}
return _items[_tail];
}

public int Count
{
get
{
return _size;
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐