-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDoubleEndedArrayQueue.cs
141 lines (119 loc) · 2.99 KB
/
DoubleEndedArrayQueue.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
using System.Collections;
namespace compression;
public class DoubleEndedArrayQueue<T> : IList<T>, IEnumerable<T>
{
T[] values = new T[]{};
int front = 0;
int count = 0;
public int Capacity() {
return values.Length;
}
private void Resize() {
T[] newValues = new T[Math.Max(1, count * 2)];
for (int i = 0; i < count; i++) {
newValues[i] = values[ShiftedAndWrappedIndex(i)];
}
front = 0;
values = newValues;
}
public void ShiftRight(int start, int end)
{
for (int dest = end; start < dest; dest--) {
values[ShiftedAndWrappedIndex(dest)] = values[ShiftedAndWrappedIndex(dest - 1)];
}
}
public void ShiftLeft(int start, int end)
{
for (int dest = start - 1; dest < end - 1; dest++) {
values[ShiftedAndWrappedIndex(dest)] = values[ShiftedAndWrappedIndex(dest + 1)];
}
}
public void Add(int index, T value)
{
if (count >= values.Length) Resize();
if (NearBack(index))
{
AddRight(index, value);
}
else
{
AddLeft(index, value);
}
values[ShiftedAndWrappedIndex(index)] = value;
count++;
}
private void AddRight(int index, T value)
{
ShiftRight(index, count);
}
private void AddLeft(int index, T value)
{
ShiftLeft(-1, index);
front = (front - 1) % values.Length;
}
private int PositiveMod(int x, int m) {
return (x + m) % m;
}
private int ShiftedAndWrappedIndex(int index) {
return PositiveMod(front + index, values.Length);
}
public T Get(int index)
{
return values[ShiftedAndWrappedIndex(index)];
}
public T Remove(int index)
{
T removed = values[ShiftedAndWrappedIndex(index)];
if (NearBack(index))
{
RemoveRight(index);
}
else
{
RemoveLeft(index);
}
count--;
if (count * 3 < values.Length) Resize();
return removed;
}
private bool NearBack(int index)
{
return count - 1 - index <= index;
}
private void RemoveRight(int index)
{
ShiftLeft(index + 1, count);
}
private void RemoveLeft(int index)
{
ShiftRight(0, index);
front = (front + 1) % values.Length;
}
public T Set(int index, T value)
{
T replaced = values[ShiftedAndWrappedIndex(index)];
values[ShiftedAndWrappedIndex(index)] = value;
return replaced;
}
public int Size()
{
return count;
}
public T GetContents(int rawIndex) {
return values[rawIndex];
}
public IEnumerator<T> GetEnumerator()
{
for (int i = 0; i < Size(); i++) {
yield return Get(i);
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T value)
{
Add(Size(), value);
}
}