-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathResizingArrayStack.cs
182 lines (157 loc) · 4.68 KB
/
ResizingArrayStack.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
namespace SedgewickWayne.Algorithms
{
using System;
using System.Collections;
using System.Runtime.CompilerServices;
using System.Text;
/// <summary>
/// Resizing-array implementation.
/// ・Every operation takes constant amortized time.
/// ・Less wasted space.
/// slower, better memory use
/// </summary>
public class ResizingArrayStack : IStack
{
#region IEnumerable
IEnumerator IEnumerable.GetEnumerator()
{
return new ReverseArrayIterator(this);
}
IEnumerator GetEnumerator()
{
return new ReverseArrayIterator(this);
}
/// <summary>
/// Enumerators can be used to read the data in the collection, but they cannot be used to modify the underlying collection.
/// </summary>
internal sealed class ReverseArrayIterator : IEnumerator
{
int i;
/// <summary>
/// An enumerator remains valid as long as the collection remains unchanged.
/// If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its behavior is undefined.
/// </summary>
readonly ResizingArrayStack parent;
/// <summary>
/// Current returns the same object until either MoveNext or Reset is called.
/// Initially, the enumerator is positioned before the first element in the collection.
/// At this position, Current is undefined.
/// Therefore, you must call MoveNext to advance the enumerator to the first element of the collection before reading the value of Current.
/// </summary>
public object Current
{
get
{
return parent.a[i];
}
}
/// <summary>
/// MoveNext sets Current to the next element.
/// If MoveNext passes the end of the collection, the enumerator is positioned after the last element in the collection and MoveNext returns false.
/// When the enumerator is at this position, subsequent calls to MoveNext also return false.
/// </summary>
/// <returns></returns>
public bool MoveNext()
{
bool hasNext = (i > 0);
i--;
return hasNext;
}
/// <summary>
/// Reset also brings the enumerator back to this position. (before 1st elem)
/// </summary>
public void Reset()
{
// nothing to do, current position is starting position ???
i = parent.N;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public ReverseArrayIterator(ResizingArrayStack resizingArrayStack)
{
this.i = resizingArrayStack.N;
this.parent = resizingArrayStack;
}
}
#endregion
private object[] a;
private int N;
internal static bool s_assertionsDisabled = false;
static ResizingArrayStack()
{
//s_assertionsDisabled = !ClassLiteral<ResizingArrayStack>.Value.desiredAssertionStatus();
}
public ResizingArrayStack()
{
this.a = (object[])new object[2];
}
public override string ToString()
{
var sb = new StringBuilder();
var iterator = new ReverseArrayIterator(this);
while (iterator.MoveNext())
{
sb.Append(iterator.Current);
sb.Append(' ');
}
sb.Remove(sb.Length - 1, 1);
return sb.ToString();
}
#region IStack
public bool IsEmpty { get { return this.N == 0; } }
public void Push(object obj)
{
if (this.N == this.a.Length)
{ // capacity check, repeated doubling
resize(2 * this.a.Length);
}
// increment count and assign
this.a[N] = obj;
this.N++;
}
public object Pop()
{
StackUnderflowCheck();
// store last
object last = a[N - 1];
// gc help
a[N - 1] = null;
// no items update
N--;
// smart resize, halve when size is one-quarter full
if (this.N > 0 && this.N == this.a.Length / 4)
{
this.resize(this.a.Length / 2);
}
return last;
}
public int Size { get { return this.N; } }
public object Peek()
{
StackUnderflowCheck();
return this.a[this.N - 1];
}
void StackUnderflowCheck()
{
if (IsEmpty) throw new NotSupportedException("Stack underflow");
}
/// <summary>
/// Invariant. Array is between 25% and 100% full.
/// </summary>
/// <param name="num"></param>
void resize(int num)
{
if (!ResizingArrayStack.s_assertionsDisabled)
{
if (num < this.N) throw new ArgumentException(num.ToString());
}
object[] array = new object[num];
for (int i = 0; i < this.N; i++)
{
array[i] = this.a[i];
}
this.a = array;
}
#endregion
}
}